Laravel polymorphism is a quite elegant solution. Yesterday, I came up with a problem with the *able_type
column value when using extended versions of the model.
The Problem
Most our code at HYVOR has something called access objects:
1// Project.php2class Project extends Model3{}4 5// AccessProject.php6class AccessProject extends Project 7{}
It simply extends a Laravel model. Then, in routes like /project/{projectId}
, we set the access object in the service container:
1class ProjectMiddleware 2{ 3 public function handle($request, $next) 4 { 5 6 $projectId = $request->route('projectId'); 7 8 $project = Project::find($projectId); 9 10 if (!$project) {11 throw new Exception('Project not found');12 }13 14 app()->instance(15 AccessProject::class,16 (new AccessProject())->newInstance(17 $project->getAttributes(), 18 true19 )20 );21 22 return $next($request);23 }24}
Then, we can easily use the AccessProject
object in our controllers, in a Laravel-ish way (using injection).
1class ProjectController2{3 4 public function update(AccessProject $project)5 {6 // project7 }8 9}
However, in the morph table, the class name varies depending on the currently used class.
The Solution
The solution is as follows.
First, set the getMorphClass
method in the model. You can return the class name or just another string.
1class Project2{3 4 public function getMorphClass()5 {6 return 'project';7 }8 9}
If you return the full class name, the next step is not needed. Here, we set the morph map in the app service provider.
1class AppServiceProvider2{3 public function boot()4 {5 Relation::morphMap([6 'project' => Project::class,7 ]);8 }9}
That’s it!
Comments