I'm trying to take advantage of the Laravel's Polymorphic Relationships
I'm building an app where I have 3 tables: products
, expenses
and hunts
.
Each product, expense or hunt belongs to a category. I used to have 3 other different tables product_categories
, expenses_categories
and hunts_categories
but I didn't like doing it this way so I did a little bit of research and found about this Polimorphic Relationships thing but I'm not really sure how to use it.
I've create a new category
table with the following columns
$table->id();
$table->string('name');
$table->integer('categorizable_id');
$table->string('categorizable_type');
$table->foreignId('icon_id')->constrained();
My models looks like
class Product extends Model
{
public function category () {
return $this->morphOne(Category::class, 'categorizable');
}
}
class Expense extends Model
{
public function category () {
return $this->morphOne(Category::class, 'categorizable');
}
}
class Hunt extends Model
{
public function category () {
return $this->morphOne(Category::class, 'categorizable');
}
}
class Category extends Model
{
public function icon () {
return $this->belongsTo(Icon::class);
}
public function categorizable () {
return $this->morphTo();
}
}
I only want 5 categories for the expenses
table so I'm seeding them directly to the database but products categories and hunt categories are created by the user
In my CategorySeeder.php
file I have the following function
public function run()
{
DB::table('categories')->insert([
['name' => 'Advertising', 'icon_id' => 1, 'categorizable_id' => ?, 'categorizable_type' => 'App\Models\Expense'],
['name' => 'Utilities', 'icon_id' => 2],
['name' => 'Shopping', 'icon_id' => 3],
['name' => 'Payroll', 'icon_id' => 4],
['name' => 'Other', 'icon_id' => 5]
]);
}
Since I want those categories before creating any expense. What should I do with categorizable_id
column?
CodePudding user response:
You don't need to use polymorphic relationships for this. You can simply have a categories table:
$table->id();
$table->string('name');
$table->foreignId('icon_id')->constrained();
And then have a category_id
column on your product
, expenses
, and hunts
tables:
$table->foreignId('category_id')->constrained();
Each of your Product
, Expense
, and Hunt
models would have a category
method:
public function category()
{
return $this->belongsTo(Category::class);
}
And then your Category
model could have something like this:
public function products()
{
return $this->hasMany(Product::class);
}
public function expenses()
{
return $this->hasMany(Expense::class);
}
public function hunts()
{
return $this->hasMany(Hunt::class);
}
A polymorphic relationship would be useful if you had a Note
model, for example, which could belong to either a product or an expense. In that case, you would have the columns notable_type
and notable_id
on your notes
table, and then use morphOne
on your Product
and Expense
models.