1

I found some useful packages that extend the functionality of Eloquent, For example: Sentry, Revisionable. Now I understand that you cannot extend multiple classes, and that there are ways as proxies or just using another class as a property somehow.

What would be the best practice to create a model that benefits from multiple packages?

1 Answer 1

5

We have some options:

Dependency Injection:

use ExternalClass;

class Model extends Eloquent {

    private $external;

    public function __construct(ExternalClass $external)
    {
        $this->external = $external;
    }

    public function doWhatever() 
    {
        return $this->external->do();
    }

    public function __call($name, $arguments)
    {
        return call_user_func_array(array($this->external,$name), $arguments);
    }
}

You don't have to pass a class to your model, Laravel will try to instantiate and inject that class for you.

edit

And you don't have to rewrite all methods, see this magic method __call? It will be fired automatically by PHP everytime a method is not found in your class, so you can use it to forward that call to your external class.

end-edit

Traits: (this is PHP 5.4+)

class Model extends Eloquent {

    use MyTraits;

    public function doWhatever() 
    {
        return $this->do();
    }
}

trait MyTraits {

    public function do()
    {
        /// this metho will be available in your class 
    }

}

You can also use the Repository Pattern:

class DataRepository {

    private $user;

    private $external;

    public function __construct(User $user, ExternalClass $external)
    {
        $this->user = $user;

        $this->external = $external;
    }

    public function allUsers() 
    {
        return $this->user->all();
    }

    public function doWhatever() 
    {
        return $this->external->do($this->user);
    }
}

There some others, but your project is what will really tell you what's best.

EDIT

Note that you have to be aware of the __call magic method, because Laravel also uses it to deliver dynamic methods, like whereColumnname() and you risk breaking by using it. But this is also something you can circumvent with a little more code:

public function __call($name, $arguments)
{
    // If the method is not one of your package ones, try execute an Eloquent (parent) one

    if ( ! in_array($name, ['methodA', 'methodB', 'methodC']))
    {
        return parent::__call($name, $arguments);
    }
    else
    {
        return call_user_func_array(array($this->external,$name), $arguments);
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

Traits is php 5.4 no? (I'm on 5.3 with current project)
Dependency injection or/with the repository pattern has, in my experience, led to the most maintainable applications.
Yeah, so you cannot use Traits, but I think that traits are for other kind of usage anyway. :)
so basicly, with Dependency Injection I have to rewrite ALL the methods... and props
Not really, just edited to add a magic method that can save a lot of rewriting.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.