I’m building a Laravel 10 model for a database I can’t change (since it’s 3rd party). I want to effectively map the column name to something else inside the program.
All model functionality should utilize the new name, but all queries against the database should run with the original name.
Here’s what I tried.
The migration
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('test_models', function (Blueprint $table) {
$table->id();
$table->string('test');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('test_models');
}
};
The Model
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class TestModel extends Model
{
use HasFactory;
protected $appends = ['test_changed'];
public $hidden = ['test'];
public function __call($method, $parameters)
{
if($method === 'getTestChangedAttribute'){
return $this->getAttribute('test');
} else if ($method === 'serTestChangedAttribute'){
return $this->setAttribute('test', $parameters[0]);
}
return parent::__call($method, $parameters);
}
public function getAttribute($key)
{
if($key === 'test_changed'){
$key = 'test';
}
return parent::getAttribute($key);
}
public function setAttribute($key, $value)
{
if($key === 'test_changed'){
$key = 'test';
}
return parent::setAttribute($key, $value);
}
}
This works great
TestModel::all();
However, something like this
TestModel::where('test_changed', 'test 1')->get();
Fails with the following:
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘test_changed’ in ‘where clause’ (Connection: mysql, SQL: select * from test_models
where test_changed
= test 1)
How can I effectively change the property to ‘test_changed’ anywhere it may be used?
2
Answers
Alright, after reading through the Laravel source (and a lot of trial and error), I've determined the following was the best solution in my application & covered as many scenarios as I could throw at it.
This allows the extended Model to do something like this
In the case of the where
Model::where()
I then did an explicit convert with a static propertyCreate a parent abstract class (ParentModel class below). Notice this approach fits better giving the existing functionality and structures you have already.
Afterwards override $colums in child models and you should be good to perform queries as defined by you.