1

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.

2 Answers 2

5

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',
];
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Jonas, that is a really good answer. The only reason I didn't choose it was for reasons of visibility. It seemed more self-documenting by just using accessors and mutators, but I wrestled with that choice :)
I added it because I wasn't sure about your database size. If you have hundreds of columns, creating accessors and mutators for each one might get out of hand ;-)
1

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();

Comments

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.