php – Trait is not fired when I use the constructor-ThrowExceptions

Exception or error:

My trait is not fired when I use the constructor of the class. My project use laravel 7.0

trait LogUserDB
{
    public static function bootLogUserDB()
    {
        self::creating();

        self::updating(
            function ($model) {
                $user = Auth::user();
                if ($user !== null && $user->id >= 0 && Schema::hasColumn($model->table, 'updated_by')) {
                    $model->updated_by = $user->id;
            }
        });

        self::deleting();
    }
}

abstract class AbstractBaseModel extends Model
{
    use LogUserDB;

    public function loadInfoSchema(){}
}

And that is my class that I can’t use the construtor

class EmailsModel extends AbstractBaseModel
{
    protected $table = 'cad_emails';
    protected $primaryKey = "id";

    public function __construtor($request){
        /**
         * If I create the constructor my field is not updated
         */
    }

}

In my controller

Class XYZController extends BaseModel 
{
    $emailModel = new EmailsModel() 
    $emailEdit  = $emailModel->find(1);
    $emailEdit->email = 'teste@test.com';
    $emailEdit->save() // $emailEdit->update()

    dd('end');
}

When I run this example without constructor my field “updated_by” is updated with ID the user, when I use the construtor the field does not update

What is the problem? I have no idea why updated_by by field is not updated with constructor.

How to solve:

At first you should follow the constructor signature in Model.php, which is:

public function __construct(array $attributes = [])
{
    // ...
}

So, your model should be like this:

public function __construtor(array $attributes = [], $request = null)
{
    parent::__construct($attributes); // This is required

    $this->request = $request;
}

To get the parent’s constructor be called, you must call parent::__construct($attributes) method because, traits booting are done in the constructor method in the Model.php file.

If you want to construct your model now then you may use something like this:

// Assumed you've $request in the scope
$emailModel = new EmailsModel([], $request);

To be more clear, check the Model.php, you’ll see something like this:

public function __construct(array $attributes = [])
{
    $this->bootIfNotBooted();

    $this->initializeTraits();

    $this->syncOriginal();

    $this->fill($attributes);
}

In this case the, bootIfNotBooted method boots the traits so you need to call the parent constructor manually.

A suggestion: You don’t need to pass the $request in the constructor, You can access the Request facade from the model if required. Maybe think about the design decision of your models. Also, there are methods available to create, update e.t.c, you can use those methods without manually constructing a model.

Leave a Reply

Your email address will not be published. Required fields are marked *