Let's define the current scenario, we have a photos table, posts and comments. We want to store photos from posts and comments which requires polymorphic relation.

What is polymorphic relationship?

According to official Laravel documentation, polymorphic relationship is:

"A polymorphic relationship allows the child model to belong to more than one type of model using a single association. For example, imagine you are building an application that allows users to share blog posts and videos. In such an application, a Comment model might belong to both the Post and Video models."

OK, got it.... a complicated name for such a common feature... back to our example.

So, we want to create Post, and Photos table and connect them with polymorphic relationship. And let's make it even more real-life example, we will add a connection to post category, and later on we can query for similar posts based on post category

Example of polymorphic relationship in Laravel

First, let's create the posts table with a foreign key to the categories table:

                    Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->unsignedBigInteger('category_id');
    $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
    $table->timestamps();
});
                  

Next, let's create the photos table with the polymorphic relation to Post (and potentially other models):

                    Schema::create('photos', function (Blueprint $table) {
    $table->id();
    $table->string('url');
    $table->unsignedBigInteger('photoable_id');
    $table->string('photoable_type');
    $table->timestamps();
});

                  

Note the photoable_id and photoable_type columns, which are used to store the ID and type of the model that the photo belongs to. This allows the photos table to be used for multiple models with a polymorphic relation.

Now, let's create the Post and Photo models with their respective relationships:

                    class Post extends Model
{
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function photos()
    {
        return $this->morphMany(Photo::class, 'photoable');
    }
}

class Photo extends Model
{
    public function photoable()
    {
        return $this->morphTo();
    }
}
                  

In the Post model, we define a photos relationship using the morphMany method, which allows the Post model to have many Photo models associated with it. We also define a category relationship using the belongsTo method, which indicates that the Post model belongs to a Category model.

In the Photo model, we define a photoable relationship using the morphTo method, which allows the Photo model to be associated with any model that implements the MorphOne or MorphMany relationships.

Now, let's see an example of how to query posts with photos:

                    $posts = Post::with('photos')->get();
                  

In the above code, we use the with method to eagerly load the photos relationship for all posts.

Finally, let's see an example of how to get similar posts (with photos) based on a selected photo category:

                    $photoCategory = 'landscape';

$similarPosts = Post::whereHas('photos', function ($query) use ($photoCategory) {
        $query->where('category', $photoCategory);
    })
    ->with(['photos' => function ($query) use ($photoCategory) {
        $query->where('category', $photoCategory);
    }])
    ->get();

                  

In the above code, we use the whereHas method to filter posts that have at least one photo with the selected category. We also use the with method to eagerly load the photos relationship for the matching posts, and we use a nested closure to filter the photos by category as well.

Note that the category column in the photos table is assumed to store the category of the photo.