PHP Laravel OOP

Extending Models with Method Overrides: A Case Study

Sometimes, the core functionality of a framework needs a little customization to perfectly fit the nuances of a specific application. Recently, we faced a situation where we needed to extend our Tenant model to directly handle subscription checks, which required overriding some core Cashier methods.

The Challenge

Our application uses a multi-tenant architecture. Each tenant needs to manage its own subscriptions. Cashier, a subscription billing library, provides excellent tools for managing subscriptions. However, we wanted to encapsulate all subscription-related logic directly within the Tenant model to simplify access and maintain consistency. This meant overriding Cashier's default subscription-checking methods to ensure they queried the subscriptions associated with the specific tenant.

The Solution: Method Overrides

To achieve this, we overrode Cashier's methods directly within our Tenant model. This allowed us to modify the query logic to fetch subscriptions related to the current tenant.

Here's a simplified example:

namespace App\Models;

use Laravel\Cashier\Subscription;

class Tenant extends Authenticatable
{
    /**
     * Determine if the tenant is on trial.
     *
     * @param  string|null  $plan
     * @return bool
     */
    public function onTrial($plan = null)
    {
        return $this->subscriptions()->active()->where('name', 'default')->exists() &&
               $this->subscriptions()->active()->where('name', 'default')->first()->onTrial();
    }

    /**
     * Get the tenant's subscriptions.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function subscriptions()
    {
        return $this->hasMany(Subscription::class);
    }
}

In this example, the onTrial method is overridden to query the subscriptions table directly through the Tenant model's relationship. This ensures that the trial status check is always performed in the context of the current tenant.

Consistent Code Formatting

Alongside the functional changes, we also addressed code styling inconsistencies. Specifically, we standardized the placement of curly braces in constructors across various classes to maintain a uniform coding style. This seemingly small change contributes significantly to the overall readability and maintainability of the codebase.

Key Takeaways

  • Method Overriding: Extending model functionality by overriding methods can provide a clean and intuitive way to encapsulate complex logic.
  • Consistency: Maintaining a consistent code style improves readability and reduces cognitive load for developers.
  • Encapsulation: Centralizing subscription logic within the Tenant model simplifies access and ensures consistency across the application.
Gerardo Ruiz

Gerardo Ruiz

Author

Share: