Laravel Map DB Column Names Using Proper Convention to Actual DB Column Names in Model

自作多情 提交于 2019-12-10 11:54:07

问题


We're building a portal to replace part of an existing application as step one, but the DB schema holds to absolutely no conventions. Aside from the lack of any constraints, indexes, etc the names of columns are not descriptive and not snake-cased.

Is it possible to map DB table column names so that the portal uses proper descriptive and snake-cased column names like first_name but writes to the actual database column first to at least have the portal be a first step towards cleaning up the tech debt?

For example, similar to how the table name (Model::table) can be set if the table name doesn't follow convention:

Example

private $columns = [
    // convention => actual
    'first_name' => 'first',
    'last_name' => 'last',
    'mobile_phone' => 'phone',
    'home_phone' => 'otherPhone', // seriously!?
];

I've looked through Model and the HasAttributes trait, but I'm still hoping that this might exist, or someone has found a way to do this as a temporary solution.


回答1:


You can create a parent class for all your models:

abstract class Model extends \Illuminate\Database\Eloquent\Model {

    protected $columns = [];

    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();
        foreach ($this->columns as $convention => $actual) {
            if (array_key_exists($actual, $attributes)) {
                $attributes[$convention] = $attributes[$actual];
                unset($attributes[$actual]);
            }
        }
        return $attributes;
    }

    public function getAttribute($key)
    {
        if (array_key_exists($key, $this->columns)) {
            $key = $this->columns[$key];
        }
        return parent::getAttributeValue($key);
    }

    public function setAttribute($key, $value)
    {
        if (array_key_exists($key, $this->columns)) {
            $key = $this->columns[$key];
        }
        return parent::setAttribute($key, $value);
    }

}

Then override $columns in your models:

protected $columns = [
    'first_name' => 'first',
    'last_name' => 'last',
    'mobile_phone' => 'phone',
    'home_phone' => 'otherPhone',
];



回答2:


The proper way is to use accessors and mutators.

Defining An Accessor

public function getFirstNameAttribute() {
    return $this->first;
}

Then, you can access the value by $model->first_name.

Defining A Mutator

public function setFirstNameAttribute($value) {
    $this->attributes['first'] = $value;
}

Then, you can mutate the value for example:

$model->first_name = 'first_name';
$model->save();


来源:https://stackoverflow.com/questions/49546915/laravel-map-db-column-names-using-proper-convention-to-actual-db-column-names-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!