ou can use a shared controller for this with some explicit model binding. The following is untested code, it provides the general idea rather than copy and pasteable. Let me know if you run into any issues.
-
Create a new
CommentableModel
that extendsModel
-
Extend
Photo
andVideo
fromCommentableModel
instead ofModel
-
Create a controller, and in your
create
method typehintCommentableModel $commentable
— so within the method you do$commentable->comments->create()
-
Create a new global routing constraint which is a regular expression for your commentable types, e.g:
Route::pattern('commentableType', 'photo|video')
-
Create your route for your controller, using your global constraint, e.g:
Route::get('comments/{commentableType}/{commentable}/create', 'CommentableController@create');
-
Create your explicit route model binding which uses the
commentable
parameter to determine the model type, e.g:
Route::bind('commentable', function ($id) {
$type = app()->request->route('commentableType');
$models = ['video' => Video::class, 'photo' => Photo::class];
$model = $models[$type];
return (new $model)->where('id', $id)->firstOrFail(); // you could use findOrFail here if you're using IDs instead of slugs but I used where just as an example
});
Then when a user visits https://www.example.com/comments/photo/1/create
your create
method on CommentableController
will be called, with the Photo of ID 1 injected as the CommentableModel
.
Note: you could improve this code by creating a configuration that contains your commentable models and their keys, and from there you could pull that in to both your route constraint and model binding, that would produce more maintainable code. Stick both the route binding and constraints in a service provider just for the commentable code.