laravel model attributes aliases - best practice

31 Views Asked by At

I use an old database on a legacy system that should be migrated to a new laravel system on the long term. The naming of the database columns is not clean an convenient, so I'd like to add attribute aliases to make the migration more easy in the future.

E.g. the table has columns like PascalCase and OtherLanguageThanEnglish those names should be pascal_case and english_column_name in the migrated table.

In the meantime - to use both systems without changing everything - the model should have some "translation matrix" like

protected $cleanAttributes = [
    'PascalCase'                => 'pascal_case',
    'OtherLanguageThanEnglish'  => 'english_column_name',
];

so I can access them with $model->pascalCase and $model->englishColumnName.

I know there is the magic getPascalCaseAttribute() method, but this seems a bit repetitive, especially if the table has lots of columns. And how can I set those new attributes?

Edit

Just learned of the existence of the methods getAttributes() and setAttributes() so i extracted a trait

<?php

namespace App\Models\Traits;

use Illuminate\Support\Str;

trait HasAttributeAliases
{
    public function getAttribute($key)
    {
        if (!isset($this->map)) $map = [];
        else $map = $this->map;

        if (in_array($key, $map)) {
            return $this->attributes[array_search($key, $map)];
        } elseif (in_array(Str::snake($key), $map)) {
            return $this->attributes[array_search(Str::snake($key), $map)];
        } else {
            if (in_array($key, array_keys($this->attributes))) return $this->attributes[$key];
            elseif (in_array($key, array_keys($this->relations))) return $this->relations[$key];
            else return null;
        }
    }

    public function setAttribute($key, $value)
    {
        if (!isset($this->map)) $map = [];
        else $map = $this->map;

        if (in_array($key, $map)) {
            $this->attributes[array_search($key, $map)] = $value;
        } elseif (in_array(Str::snake($key), $map)) {
            $this->attributes[array_search(Str::snake($key), $map)] = $value;
        } else {
            $this->attributes[$key] = $value;
        }
    }
}

That can be used in the Model in combination with an array $protected $map = ['old_key' => 'new_key' ...]

Is this practicable? Any drawbacks for "overriding" standard Model functionallity?

0

There are 0 best solutions below