8

I'm using Laravel 5.1 but this isn't specific to that framework, it's more of a general PHP question.

There's a parent class with traits specified:

namespace Illuminate\Foundation\Auth;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

class User extends Model implements
  AuthenticatableContract,
  AuthorizableContract,
  CanResetPasswordContract {
    use Authenticatable, Authorizable, CanResetPassword;
}

Then I have the User class I'm concerned with extending from that:

namespace App\Api\V1\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;

class User extends Authenticatable {
  use EntrustUserTrait {
    EntrustUserTrait::can insteadof \Illuminate\Foundation\Auth\Access\Authorizable;
  }
}

The EntrustUserTrait has a can() method that conflicts with the Authorizable trait. However, the Authorizable trait is on the parent class, so this throws an error Required Trait wasn't added to App\Api\V1\Models\User.

I've searched around and there's plenty of information on overriding traits declared within the child class, but I can't seem to find anything about overriding traits from the parent class.

2
  • You don't need to do insteadof at all. can will override the parent's can. Commented Apr 5, 2016 at 16:01
  • Except it doesn't, it throws an error about not applying the trait because it conflicts with another trait. I think this is some edge case, though, as the example below does work and overrides the other trait. I'm not exactly sure what the difference is, though. Commented Apr 6, 2016 at 18:44

1 Answer 1

5

Consider the following code:

<?php    
trait AA {
    function f() { 
        echo "I'm AA::f".PHP_EOL;
    }
}
class A {
    use AA;
}
trait BB {
    function f() { 
        echo "I'm BB::f".PHP_EOL;
    }
}
class B extends A {
    use BB;
}
$b = new B();    
$b->f();

I'm BB::f

I believe that traits work like copy-paste code. The trait code is treated like a "copy-pasted" code in the class it's used in so you can pretend that the trait is not really inherited but it's code is just part of the parent class.

Sign up to request clarification or add additional context in comments.

2 Comments

Indeed your example works. Perhaps the difference between that and my situation is that the parent class implements an interface requiring it to implement the method? Or maybe that the interface is defining a different function signature? I'm not sure. But I just decided to create a separate class rather than extending the parent, since all it does is implement the contracts and add the traits.
Different method signatures would indeed cause conflicts if that is the case.

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.