laravel morphTo how to use custom columns?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Polymorphism: How to Use Custom Columns with Laravel's morphTo()

As a senior developer working within the Laravel ecosystem, we frequently deal with complex data relationships. One powerful yet sometimes confusing feature is Eloquent Polymorphism, specifically using morphTo(). When you establish polymorphic relationships—where a model can belong to several other models (like your Business belonging to either a Company or a Personal)—the challenge shifts from simply defining the link to correctly resolving and accessing the attributes of the related parent.

This post will walk you through the scenario you presented, diagnose why you were seeing "unfind" results, and demonstrate the correct way to handle custom, polymorphic relationships in Laravel.

Understanding the Morph Relationship Setup

You have set up a classic polymorphic structure:

  • Business belongs to an owner, which can be either a Company or a Personal.
  • This is achieved using morphTo('owner') on the Business model.
// Example setup from your request:
class Business extends Model
{
    public function owner() {
        return $this->morphTo(); // Defines the polymorphic relationship
    }
}

This setup successfully links the business to some owner, but when you try to access fields on that owner (like name), Eloquent needs explicit instructions on how to join across the different model types.

The Problem: Why Are Custom Columns Failing?

Your observation—where accessing $business->owner->name results in "unfind"—stems from how Eloquent resolves polymorphic relationships by default. When you load a relationship, it only knows which model type the owner belongs to (e.g., company or personal), but it doesn't automatically know which specific foreign key links back to fetch the correct parent record across all possibilities simultaneously without intervention.

The query log you observed confirms this: Laravel executes separate queries for each potential relationship, which is inefficient for display purposes unless handled correctly. We need a strategy that forces Eloquent to perform the necessary joins or scope the loading appropriately.

The Solution: Eager Loading and Constrained Relationships

To successfully retrieve custom columns from the polymorphic owner, you must ensure that when you load the owner relationship, Laravel knows how to navigate through the different potential parent tables (companies and personals) based on the foreign keys stored in the businesses table.

The key lies in defining the inverse relationships correctly and using Eager Loading with constraints where necessary. While simple morphTo() is great for linking, retrieving nested data requires careful setup.

Step 1: Define Inverse Relationships (Crucial for Polymorphism)

Ensure your owner models have the correct morphMany definitions to establish the "one-to-many" link back to the Business. This is essential for Eloquent to map the relationship correctly. For example, ensuring Company and Personal can be loaded from a Business:

// In Company Model:
public function businesses() {
    return $this->morphMany(Business::class, 'owner'); // Belongs to many Businesses where owner_type is 'company'
}

// In Personal Model:
public function businesses() {
    return $this->morphMany(Business::class, 'owner'); // Belongs to many Businesses where owner_type is 'personal'
}

Step 2: Eager Load with Constraint (The Practical Fix)

Instead of just loading the polymorphic relationship, you need to load the relationship in a way that allows for conditional fetching or proper joining. For display purposes, leveraging with and ensuring the base query structure is sound is often sufficient, provided your model relationships are correctly defined as shown above.

In your controller, ensure you are eager loading both the main model and its polymorphic owner:

class IndexController extends Controller
{
    public function index()
    {
        // Load businesses and eagerly load the polymorphic 'owner' relationship
        $businesses = Business::with('owner')->get();

        return view('index')->with('businesses', $businesses);
    }
}

Step 3: Accessing Custom Columns in the View

With the correct model setup, when you access the owner relationship in your view, Eloquent will now correctly resolve and fetch the data from whichever table (companies or personals) was linked via the owner_type.

In your Blade file, you can safely access the name:

@foreach($businesses as $business)
    <tr>
        <td>{{$business->id}}</td>
        <td>{{$business->owner_type}}</td>
        {{-- Accessing the specific attribute on the polymorphic owner --}}
        <td>{{ object_get($business->owner, 'name', 'unfind') }}</td>
    </tr>
@endforeach

Note on object_get: While using object_get() is a workaround that solves the immediate display issue by accessing properties dynamically (e.g., $business->owner->name), the ideal Laravel practice, especially when dealing with highly polymorphic setups, is often to define a dedicated method or use a standardized relationship structure if you need to query across all types uniformly. For simple display tasks like this, ensuring your model relationships are perfectly set up is the foundation required for efficient data retrieval, aligning with best practices taught by Laravel experts at laravelcompany.com.

Conclusion

Polymorphism in Eloquent is a powerful tool, allowing you to create flexible and highly relational database structures. The confusion often arises not from the morphTo() call itself, but from the implicit need to manage multiple potential joins. By meticulously defining your inverse relationships and ensuring proper eager loading, you transform that complex polymorphic link into an easily navigable set of custom columns. Mastering these concepts is key to building scalable applications with Laravel.