Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

andrew_mcburney's avatar

OOP vs functional approach

Hey guys, I am a JS dev but have been learning PHP and Laravel specifically for a while now.

I find I default back to functional programming paradigms a lot, and am working on refactoring a specific feature to be more OOP in nature.

Is the below approach a viable OOP solution here? Are there other typical patterns to use in OOP or Laravel specifically?

The original code basically grabbed a value from a tenant’s subscription plan, and then used a utility service that I stored in Support/isValidValue.php

Based on the boolean value returned by isValidBoostValue, I would do some logic in the application.

Example:

$companyBoostValue = tenant->getPlanMetaData('boostValue') // this may or may not actually be valid

if(isValidBoostValue($companyBoostValue)){ done some logic here }

OOP approach:

create a Trait, and assign it to the Tenant model.

Then, I can have a private method on the trait that handles the “isValidBoostValue” helper rather than its own file, and then a method can basically return the value if it is valid, or some default value.

The app itself doesn’t need to know it’s valid or not, just the actual outcome, which I think makes sense for adding the isValidBoostValue to the trait class as a private method.

Also, I have multiple similar methods that are needed, which would all live on the same trait. The trait would be something like InterpretsSubscriptionMetadata

0 likes
4 replies
LaryAI's avatar

Absolutely, your instinct to encapsulate this logic within your models using OOP principles is spot-on and aligns well with Laravel conventions. Here’s a breakdown of your approach and some suggestions:

1. Using a Trait

Creating a trait like InterpretsSubscriptionMetadata is a good way to group related logic that can be shared across models. This keeps your code DRY and organized.

2. Encapsulation

By making isValidBoostValue a private method within the trait, you encapsulate the validation logic, exposing only what’s necessary to the rest of your application. This is a solid OOP practice.

3. Returning the Value or a Default

You can provide a public method that returns either the valid value or a default, hiding the validation details from consumers of your model.

Example Implementation

Here’s how you might structure this in your Laravel app:

// app/Models/Traits/InterpretsSubscriptionMetadata.php

namespace App\Models\Traits;

trait InterpretsSubscriptionMetadata
{
    public function boostValue()
    {
        $value = $this->getPlanMetaData('boostValue');
        return $this->isValidBoostValue($value) ? $value : $this->defaultBoostValue();
    }

    private function isValidBoostValue($value)
    {
        // Your validation logic here
        return is_numeric($value) && $value > 0;
    }

    private function defaultBoostValue()
    {
        // Define your default value here
        return 10;
    }
}

And in your Tenant model:

// app/Models/Tenant.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Traits\InterpretsSubscriptionMetadata;

class Tenant extends Model
{
    use InterpretsSubscriptionMetadata;

    // ...
}

Usage:

$boostValue = $tenant->boostValue();
// Use $boostValue directly, it's guaranteed to be valid or default

4. Alternatives and Patterns

  • Service Classes: For more complex logic, consider a dedicated service class (e.g., SubscriptionMetadataInterpreter). This is especially useful if the logic grows or needs to be reused outside Eloquent models.
  • Value Objects: For strict type safety and encapsulation, you could wrap subscription metadata in value objects.
  • Custom Eloquent Accessors: You could also use Eloquent accessors (getBoostValueAttribute) for computed properties.

5. Laravel Best Practices

  • Traits are great for sharing logic, but avoid overusing them for unrelated concerns.
  • Keep your models focused; if logic gets too complex, refactor to services or value objects.

Summary:
Your OOP approach using a trait is idiomatic Laravel and a solid improvement over scattered helper functions. It keeps your logic close to your domain models and makes your codebase easier to maintain and extend.

Let me know if you’d like to see an example using a service class or value object!

jlrdw's avatar

I suggest taking the 30 days to learn laravel (free) course. And use laravel conventions. It automatically puts you in MVC mode.

Don't worry about OOP, just do good MVC and you are good to go.

1 like

Please or to participate in this conversation.