3

I'd like to be able to have a (Eloquent) Model implement a class based upon a property of the model once it is created. I think this is the Strategy Pattern, but since I'm doing it from inside a Model and not passing the dependency, it's not the perfect fit. I'm trying to avoid using switch or if-else blocks to create the CompanyXXX APIs, because there are currently 4 CompanyXXX, and it's already unwieldy and we could have up to 20 in a few years.

Example:

interface API
{
    public function getThings();
}

class CompanyOne implements API
{
    public function getThings()
    {
        // Company One API specific stuff to get Things
    }
}


class Property extends Model
{
    // This is an Eloquent Model, this valid is populated from the DB
    public $company; // 'CompanyOne'

    // This is the class implementing the API to use based upon $company
    private $api;

    public function __construct()
    {
        parent::__construct();

        $this->api = new $this->company;
        // Thus, this is an object CompanyOne
    }

    public function getThings()
    {
        $this->api->getThings();
        // CompanyXXX API specific stuff to getThings
    }
}

Thus, I would be able to do things like this in a Controller so it knows which API to use (based on $api) and just does it™. I don't need to know or care what API this Property is using, I just need to getThings.

$property = Property::find(1); // get from DB, has 'api' parameter set

$things = $property->getThings();

Which is wildly more simple compared to current methods that use switch and are now difficult to maintain (we now have 46 switch statements in the code base):

$property = Property::find(1);

switch ($property->api) {
    case 'CompanyOne':
        $api = new CompanyOne;
    case 'CompanyTwo':
        $api = new CompanyTwo;
    // repeat
}

$things = $api->getThings();

So what's the question?

  1. Is this the Strategy Pattern (modified)? Is this another pattern?
  2. Is there a better way (especially in Laravel) to have multiple API classes (as in my example) that are determined from a model's parameter that is 'self-aware' to implement the correct class/system to reduce the use of switch and if-else statements?
2

It's not the strategy pattern - whether it's a modified strategy pattern depends on how far you want to stretch. I'm not sure this approach has a name, because you can't really do this (exactly) in most other languages. The $company field would have to be some kind of factory method in C#/Java/C++.

I haven't done any PHP programming in a long time, so I'm not the best person to ask for best practices. Right now I can't really see why you shouldn't use this capability of PHP, if it really helps you.

However, I also can't really see why you would wrap the API creation like this in the first place. It seems Property::find($x) could just return an instance of API directly.

If you need the Property class to provide additional functionality, you could inject the API object directly, rather than having Property create it.

  • I had a typo that Boss should be Property. I've edited it above. I apologize for the confusion. Property::find($x) returns a Property object, of which API it tries to connect to is decided by the $company field/value. – MECU Jan 4 '18 at 23:20
  • No problem, I figured it would be. – doubleYou Jan 4 '18 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.