I have a two eloquent models model User and Retailer. I want to create a new model “Task” where there there should be a field “added_by” which can denote either a user or a retailer.
How can I create the migration for Task so that there is a field that can denote either user or retailer?
Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('product_id'); $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); $table->morphes('added_by'); $table->timestamps(); });
How can I create a Task which references a user for example?
Task::create([ 'product_id' => 1, 'added_by' => ???? ]);
Also when I get a eloquent instance of task how can i know if the added_by is referencing to a user or a retailer?
Advertisement
Answer
The syntax for the migration is $table->morphs(...)
, not $table->morphes(...)
.
$table->morphs('added_by')
will create the columns added_by_id
and added_by_type
Option 1: 1-M Polymorphic Relationships
You need to define some relationships in the User
, Retailer
and Task
models
User
class User extends Authenticable { public function tasks() { return $this->morphMany(Task::class, 'added_by'); } }
Retailer
class Retailer extends Model { public function tasks() { return $this->morphMany(Task::class, 'added_by'); } }
Task
class Task extends Model { protected $fillable = ['product_id']; public function added_by() { return $this->morphTo(); } }
Eloquent Relationships – One to Many Polymorphic Relations
To add a Task
for an User
or a Retailer
, you use the relationship method.
$user->tasks()->create(['product_id' => $productId]); $retailer->tasks()->create(['product_id' => $productId]);
Eloquent Relationships – Inserting and Updating Related Models
Option 2: M-N Polymorphic Relationships
The other option is to use a Many to Many Polymorphic Relationship between Product
and both User
and Retailer
You need to define some relationships in the User
, Retailer
and Product
nodels
User
class User extends Authenticable { // Optional public function tasks() { return $this->morphMany(Task::class, 'added_by'); } public function products() { return $this->morphToMany(Product::class, 'added_by', 'tasks') ->using(Task::class) ->withTimestamps(); } }
Retailer
class Retailer extends Model { // Optional public function tasks() { return $this->morphMany(Task::class, 'added_by'); } public function products() { return $this->morphToMany(Product::class, 'added_by', 'tasks') ->using(Task::class) ->withTimestamps(); } }
Product
class Product extends Model { // Optional public function tasks() { return $this->hasMany(Task::class, 'product_id'); } public function users() { return $this->morphedByMany(User::class, 'added_by', 'tasks') ->using(Task::class) ->withTimestamps(); } }
Task
use IlluminateDatabaseEloquentRelationsMorphPivot; class Task extends MorphPivot { public $incrementing = true; // Optional public function added_by() { return $this->morphTo(); } // Optional public function product() { return $this->belongsTo(Product::class, 'product_id'); } }
Eloquent Relationships – Many to Many Polymorphic Relation
To associate an User
or Retailer
with a Product
(using Task
as a morph pivot)
$user->products()->attach($productId); $retailer->products()->attach($productId);
Eloquent Relationships – Updating Many to Many Relationships