Extending Eloquent Models in Laravel (use different tables)

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Extending Eloquent Models in Laravel: Class Inheritance vs. Database Structure As a senior developer working with Laravel and Eloquent, we often encounter design patterns that cross the boundary between object-oriented programming (OOP) and relational database design. The scenario you’ve described—creating specialized lead types like `RefinanceLead` extending a general `Lead` class—is a classic application of inheritance. However, when bridging this OOP concept to Laravel's Eloquent ORM and database structure, we need to understand how the framework handles data persistence. Let’s dive into your questions regarding implementing polymorphic models using separate tables in Laravel. --- ## Does Class Inheritance Make Sense for Eloquent? From a pure Object-Oriented Programming standpoint, yes, defining `Lead` as a base class and extending it with specific lead types like `RefinanceLead` is conceptually sound. It promotes code reuse by allowing common methods and properties to be defined once in the parent class. However, when working within the Laravel Eloquent framework, we must distinguish between the *application logic* (PHP classes) and the *data persistence layer* (database tables). Eloquent’s primary focus is mapping models directly to database tables. Therefore, achieving this structure requires choosing an appropriate data modeling strategy rather than relying solely on PHP inheritance to dictate the table structure. ## How Eloquent Handles Data: Table-Per-Class Strategy Your intuition about creating separate tables—a `leads` table and a `refinance_leads` table—is often referred to as the **Table-Per-Class** pattern, which is a valid way to handle polymorphic data in relational databases. If you explicitly want each lead type to have its own dedicated table, Eloquent will manage these cleanly through standard migrations and models: 1. **`leads` Table:** Stores the common attributes shared by all leads (e.g., name, contact info, creation date). 2. **`refinance_leads` Table:** Stores the specific attributes unique to refinance leads (e.g., interest rate details, loan amount required). This approach keeps your data normalized and allows for highly optimized querying specific to each lead type. You would define relationships between these tables using foreign keys. For instance, `refinance_leads` would have a one-to-one relationship back to the main `leads` table. ## Utilizing Data Across Models The key challenge is ensuring that an instance of `RefinanceLead` can access data from the parent `Lead` model via Eloquent. This is achieved through explicit **Eloquent Relationships**, not just PHP inheritance alone. You do not rely on PHP's class inheritance to automatically pull data across tables; you use database relationships to define how these models connect. ### Implementation Example Here is a conceptual look at how this structure would be implemented in Laravel: **1. Migrations:** We create separate migrations for each entity. ```php // database/migrations/..._create_leads_table.php Schema::create('leads', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('status')->default('new'); $table->timestamps(); }); // database/migrations/..._create_refinance_leads_table.php Schema::create('refinance_leads', function (Blueprint $table) { $table->id(); $table->foreignId('lead_id')->constrained('leads'); // Foreign key linking back to the parent $table->decimal('interest_rate')->nullable(); $table->timestamps(); }); ``` **2. Models (Relationships):** The models define how they interact. ```php // app/Models/Lead.php class Lead extends Model { public function refinanceLead() { // Eloquent relationship to find the specific subclass data return $this->hasOne(RefinanceLead::class); } } // app/Models/RefinanceLead.php class RefinanceLead extends Model { public function lead() { // Relationship back to the parent Lead model return $this->belongsTo(Lead::class); } } ``` When you retrieve a `RefinanceLead` instance, you can easily access the shared data from the parent `Lead` table using the defined relationship: ```php $refiLead = RefinanceLead::find(1); // Accessing shared lead information directly echo $refiLead->lead->name; // Outputs the name from the 'leads' table echo $refiLead->lead->status; // Outputs the status from the 'leads' table ``` This demonstrates that while PHP class inheritance is powerful for domain modeling, Eloquent uses database relationships to execute the necessary JOINs and data retrieval, ensuring data integrity and efficient querying. This approach aligns perfectly with best practices outlined by the Laravel team regarding data relationships (as discussed on [laravelcompany.com](https://laravelcompany.com)). ## Conclusion The strategy of using class inheritance for defining your lead types is excellent for structuring your application's business logic. However, to make this structure work seamlessly with Eloquent and relational databases, you must delegate the persistence mapping to database relationships. By separating concerns—using distinct tables for each type and linking them via foreign keys—you achieve a clean, scalable, and highly performant data architecture. This separation ensures that your application benefits from both strong OOP design and robust relational data management.