Wednesday, March 29, 2017

Laravel: How to have comments on multiple content types?

I have a 'comments' table that has a foreign key of 'content_id' and a qualifier column (if you will) of 'content_type'. The possible values in that column would be e.g. articles, clubs, challenges. Since Articles, Clubs, and Challenges each are their own type of content (different tables, models, controllers etc) and each have an auto-incrementing primary key field (id: 1,2,..,n) when associating through a hasMany I would like to use the content_id and content_type columns on the comments table to differentiate between comments with foreign content_id of 1 that belong to Article 1 and not Club 1 or Challenge 1.

I could have tables/types of ArticleComment, ClubComment, and ChallengeComment but that smells to me. In SQL I would just say (basically) select * from commments where content_id = 1 and content_type = 'article'.

mysql> select * from comments where content_id = 1 and content_type = 'article';
+----+---------+------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+
| id | user_id | content_id | content_type | body                                                                                                                                                                                                                                                         | created_at          | updated_at          |
+----+---------+------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+
|  1 |      51 |          1 | article      | Laborum veniam placeat velit aut doloribus rem vitae quisquam. Qui occaecati dolores cupiditate et. Ut nam cupiditate vitae impedit blanditiis recusandae. Non temporibus minima quae rem occaecati temporibus molestiae. Eligendi ipsa laborum velit natus. | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  2 |      52 |          1 | article      | Quos et molestiae sequi aut. Dolorum eius dolorem est et sint voluptas ut. Ut ab et hic sed tenetur eaque. Neque aut qui labore animi architecto sit. Sunt excepturi laborum pariatur at dolorem est.                                                        | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  3 |      53 |          1 | article      | Quae ducimus minus et architecto non. Quas delectus accusantium sunt ipsam quisquam voluptas. Autem quo assumenda aut qui.                                                                                                                                   | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  4 |      54 |          1 | article      | Ut officiis totam doloremque et amet est. Modi et quia dolores fugit modi temporibus. Dicta dolor nemo enim. Unde quos ab voluptatum nihil ducimus reiciendis accusantium. Qui vel rem sunt sit quasi autem.                                                 | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  5 |      55 |          1 | article      | Velit saepe vero officia reiciendis sed nisi aut. Aliquam id dolorem eum qui molestiae dolores quam. Error adipisci possimus voluptatem aut. Sed odio quae et esse veniam quisquam est.                                                                      | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  6 |      56 |          1 | article      | Totam similique illum autem ut odio nihil. Placeat sunt labore suscipit sapiente et totam et. Modi autem aut ut et dolorem laudantium et. Hic laboriosam vel odio accusantium dolor quia soluta.                                                             | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  7 |      57 |          1 | article      | Voluptas facere dolores porro quas est. Dolorem sunt quis adipisci ut. Et et vero minus similique beatae distinctio ducimus. Voluptas iure laudantium incidunt aut.                                                                                          | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  8 |      58 |          1 | article      | Aut libero temporibus necessitatibus et vel sit officia sit. Esse aliquid placeat amet illum dolor aut fugiat.                                                                                                                                               | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
|  9 |      59 |          1 | article      | Repellat ducimus ipsa adipisci aliquid. Mollitia laborum ea omnis aut error error. Hic dolore qui vero nobis repellendus exercitationem amet dolores. Corrupti facere labore incidunt reprehenderit quo officia.                                             | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
| 10 |      60 |          1 | article      | Deserunt quae provident veritatis rerum unde. Voluptas dolores quia velit repellat ad ipsa saepe. Officiis corporis magni id ullam deleniti. Porro aut non veniam dolore quas suscipit.                                                                      | 2017-03-29 15:09:13 | 2017-03-29 15:09:13 |
+----+---------+------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+
10 rows in set (0.00 sec)

My comments relationship on my models looks like this:

    return $this->hasMany(Comment::class, 'content_id');

and it, rightly so, grabs all comments with content_id matching the article as well as everything other piece of content with that ID.

I would like to add in some qualifier so I can say "and content_type = 'mytype'". I've done a bit of googling and haven't found a straight-forward way to do what I assume would be a simple differentiation.

I don't like the code smelly (IMO) version of multiple comment types and I could do the Drupal-type setup where I have a node/content table that store all this type of content then references another table but I think I'd be in a similar scenario with also adding in some complication to the storing of these types.

Any clues or tips?



via Steven Jackson

Advertisement