Reputation: 331
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?
Upvotes: 1
Views: 1854
Reputation: 15879
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
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
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 Illuminate\Database\Eloquent\Relations\MorphPivot;
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
Upvotes: 2