Define Custom Polymorphic Types With Laravel
Lets start.
How to Define Custom Polymorphic Types
1.Create laravel project and connect to database in .env file.
composer create-project laravel/laravel VideoApp --prefer-dist
2.Create Model and Migrate it.
To implement One To Many Polymorphic Relationships in Laravel, we need models: Posts,Video
and Comment
.
Now we need to create Posts,Video
and Comment
models in fresh project so for that run below commands in comand prompt.
php artisan make:model Post -m
php artisan make:model Video -m
php artisan make:model Comment -m
3.After Created Models we need to Implement code in Model and migration files as below
2020_09_07_111619_create_posts_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
2020_09_07_132636_create_videos_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVideosTable extends Migration
{
public function up()
{
Schema::create('videos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('url');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('videos');
}
}
2020_09_07_132747_create_comments_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCommentsTable extends Migration
{
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('body');
$table->integer('commentable_id');
$table->string('commentable_type');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('comments');
}
}
Migrate the schema files using the following command
php artisan migrate
Models
Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'name', 'body '
];
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
Videos.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Video extends Model
{
protected $fillable = [
'title', 'url'
];
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
Comments.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $fillable = [
'body', 'commentable_id', 'commentable_type'
];
public function commentable()
{
return $this->morphTo();
}
}
You may also retrieve the owner of a polymorphic relation from the polymorphic model by accessing the name of the method that performs the call to morphTo
. In our case, that is the commentable
method on the Comment
model. So, we will access that method as a dynamic property:
$comment = App\Comment::find(1);
$commentable = $comment->commentable;
The commentable
relation on the Comment
model will return either a Post
or Video
instance, depending on which type of model owns the comment.
Custom Polymorphic Types
By default, Laravel will use the fully qualified class name to store the type of the related model. For instance, given the one-to-many example above where a Comment
may belong to a Post
or a Video
, the default commentable_type
would be either App\Post
or App\Video
, respectively. However, you may wish to decouple your database from your application's internal structure. In that case, you may define a "morph map" to instruct Eloquent to use a custom name for each model instead of the class name:
Add this in post model and access the variable names in controller
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
You may determine the morph alias of a given model at runtime using the getMorphClass
method. Conversely, you may determine the fully-qualified class name associated with a morph alias using the Relation::getMorphedModel
method:
use Illuminate\Database\Eloquent\Relations\Relation;
$alias = $post->getMorphClass();
$class = Relation::getMorphedModel($alias);
Note:When adding a "morph map" to your existing application, every morphable *_type
column value in your database that still contains a fully-qualified class will need to be converted to its "map" name.