Laravel - Extending Model

2019-07-11 04:49发布

问题:

I've created a BaseModel class, which extends from Model. It seemed like everything was working fine, but now I've run into a problem when saving. I'm overriding the save() method in this BaseModel. I'd just like to add some attributes to the model before saving. So I do that, then call return parent::save($options);. The method signature is still the same: public function save(array $options = []).

It appears to be grabbing the name of the BaseModel class for the table name when performing the insert (it's using base_models as the table name), rather than the actual model that is being saved. Has anyone run into this before? What is the proper way of extending from the model class?

I originally created some traits to handle some extra functionality, but thought it would be a better idea to just create a base model and have my models extend from that instead.

回答1:

In your model (the child one that extends the base model) add the table name explictly for example:

class SomeChildModel extends BaseModel {

    // Manually set the table name
    protected $table = 'table_name';

}


回答2:

I realized that I previously had a static method that was creating an instance of itself using new self() and would set a few attributes, back when I was using the methods from a trait. It was fine before, but now since I moved the methods into the base model, that method was actually being called on the base model itself rather than the class that had the trait.

I was basically using the static method to instantiate the class, as I've read it's one way to avoid cluttering the constructor. But I just opted to do it in the constructor this time around since it made sense, so that was my solution.



回答3:

Laravel will use snake case of the class name by default (the class where save method is called), if no $table instance variable is set. In your case it will use snake case of the BaseModel as a table name. You have two solutions:

Solution 1:

In classes which extends BaseModel add the $table instance variable as follow:

class User extends BaseModel {
    protected $table = 'table_name'; // Your table name in the database;
}

Solution 2:

You can use Laravel Eloquent's Events, which allows you to hook into various points in the model's lifecycle.

You can hook into the save method as follow and make your changes. You can use these methods in your BaseClass, in traits, etc. For example in your BaseModel:

class BaseModel extends Model
{
    /**
     * Listen for save event
     */
    protected static function boot()
    {
        parent::boot();

        static::saving(function($model)
        {
            if ( ! $model->isValid()) {
                return false;
            }
        });
    }
}

The above will always call isValid before a model is saved into the storage. In this case it will return false and will not save the object.

For more info see the official docs here. Let me know if it isn't clear.