1

I'm using Laravel 5.4 And I'm trying to inject a $order class into a trait that's going to implemented by a model. Like this:

class Forum extends Model
{
    use Orderable; 

The constructor of the trait looks like this:

trait Orderable
{
    public $orderInfo;

    public function __construct(OrderInterface $orderInfo)
    {
        $this->orderInfo = $orderInfo;
    }

My service provider looks like this:

public function register()
{
    $this->app->bind(OrderInterface::class, function () {
        return new Order(new OrderRepository());
    });

    $this->app->bind(OrderRepositoryInterface::class, function () {
        return new OrderRepository();
    });
}

The constructor of my Order class looks like this:

public function __construct(OrderRepositoryInterface $orderInfo)
{
    $this->orderInfo = $orderInfo;
}

But I receive the error:

Type error: Argument 1 passed to App\Forum::__construct() must implement interface Project\name\OrderInterface, array given, called in /home/vagrant/Code/Package/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 268

The OrderRepository class is implementing the OrderRepositoryInterface. The Order class is implementing the OrderInterface interface.

App\Forum is the model that uses the Orderable trait.

What could I be doing wrong here?

5
  • App\Forum throws the error, but that isnt noted here. Commented Mar 7, 2017 at 12:44
  • @JustOnUnderMillions I've made an update! Commented Mar 7, 2017 at 12:46
  • So while calling app->bind( the error shows up, here you have to dig in. Class declaration seems right. Or is something wrong with this statement: must implement interface Project\name\OrderInterface Is the namespace fully right? Commented Mar 7, 2017 at 12:47
  • Under witch fully namespace is the trait Orderable? -- forget this. You have to check the use of namespaces. Do check declared classes with var_dump(get_declared_classes()); at the end of a script. Commented Mar 7, 2017 at 12:49
  • I've checked all namespaces they are correct! Commented Mar 7, 2017 at 12:56

2 Answers 2

1

You are extending Model. This class already has a __construct that you need to use. This __construct expects array $attributes = [] as the first argument.

So in your __construct you also need to have this as the first argument and pass this to the parent class:

public function __construct(array $attributes = [], OrderRepositoryInterface $orderInfo)
{
    $this->orderInfo = $orderInfo;
    parent::__construct($attributes);
}

However you can work around using __construct in laravel using boot.

For example in a Model:

class Forum extends Model
{
    protected static function boot()
    {
        parent::boot();
        // Do something
    }
}

Or in a Trait:

trait Orderable
{
    public static function bootOrderableTrait()
    {
        static::created(function($item){
            // Do something
        });
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks that makes sense. But then I receive: Type error: Too few arguments to function App\Forum::__construct(), 1 passed in /home/vagrant/Code/Package/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 268 and exactly 2 expected any idea?
What happens if you change your it to: __construct(array $attributes = [], OrderRepositoryInterface $orderInfo = null)
I updated my answer with a way to use boot instead of __construct
If I make it = null it does not crash anymore. But then is $orderInfo empty. With your bootOrderableTrait example where/how do I instantiate the OrderRepositoryInterface that's being bound to OrderRepository class?
0

In PHP it's not possible to have multiple constructors. If you will look to Model:

public function __construct(array $attributes = [])

it expect array. That's why I assume that somewhere in Model array passed to constructor instead of 'OrderInterface'.

2 Comments

So what I'm trying is not possible?
Maybe it's better to add setter method instead of overriding constructor in trait. Or extend class and override constructor there

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.