Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Eloquent polymorphic relationships to categorise data in Laravel

In my application, I have a categories table, and multiple tables including services and articles that need to be categorised. For convenience, I want to use a polymorphic model for this data.

A category is created to be used by either services or articles. Once a table has been defined as a services table, for example, it is not going to be displayed as a possible category to add articles to.

This also applies to listing. I will have a menu for articles, and a menu for services, and each of these will list just article or service categories, whether they be empty or whether they contain their respective types.

A service category, for example, can be used for many services. Similarly, a service can have many categories - but only service categories.

As it stands, my database is possibly insufficient. I have not used a pivot-table, but when I tried to use one, it didn't allow me to select just article categories or service categories; in fact, it couldn't differ between the two at all.

The schema as it stands.

Basically, I need to be able to:

  • Get a list of all categories usable by services (possibly where('categorizable_type', 'App\Service')?)
  • Get a list of all categories usable by articles (possibly where('categorizable_type', 'App\Article')?)
  • Get a list of all articles/services in a category
  • Get a list of all categories used by an article/service

In this ideal situation, I can easily add new (or existing) articles/services to categories, too:

$category = App\Category::find(1);
$article = new App\Article();
$article->title = 'This is an article title.';
$category->articles()->save($article);

And I can easily add new (or existing) categories to articles/services:

$article = App\Article::find(1);
$category = new App\Category();
$category->title = 'This is a category title.';
$article->categories()->save($category);
like image 439
Forest Avatar asked Sep 05 '25 03:09

Forest


1 Answers

Well, your database and your model definitions look fine, as well as your code for adding a category to an article. However, your code for adding an article to a category is a little off.

First, there is no $category->articles() method. To access the related objects, you use your defined relationship: $category->categorizable(). Also, the relationship attribute, $category->categorizable will contain the loaded related object, and it will automatically either be an Article or a Service object, depending on what is related.

Second, this is the morphTo() side of the relationship; it behaves like the belongsTo(), and has similar methods. For example, there is no save() method, but you have the associate() method. This means you have to create your article first, and then associate it with the category. Also, associate() does not automatically save, so you need to call that, as well.

$article = new App\Article();
$article->title = 'This is an article title.';
$article->save();

$category = App\Category::find(1);
$category->categorizable()->associate($article);
$category->save();

// showing use of relationship attribute
$related = $category->categorizable;
echo get_class($related);
like image 119
patricus Avatar answered Sep 07 '25 17:09

patricus