Two other options here... One is just call the parent method rather than duplicating the logic. E.g.
<?php
namespace App\Traits;
trait OverridableTrait
{
public function newFromBuilder($attributes = [], $connection = null)
{
$model = parent::newFromBuilder($attributes, $connection);
foreach ($model->attributes AS $k => $v)
{
$override = $model->overridable()->where('key', '=', $k)->first();
if ($override) {
$model->$k = $override->value;
}
}
return $model;
}
}
You're still bound to the interface but at least if newFromBuilder() changes internally everything should still work.
Another option would be to overload the __get() magic method. For example:
<?php
namespace App\Traits;
trait OverridableTrait
{
public function __get($key)
{
$override = $model->overridable()->where('key', $key)->first();
// If there's an override and no mutator has been explicitly defined on
// the model then use the override value
if ($override && !$this->hasGetMutator($key)) {
return $override->value;
}
// If the attribute is not overridden the use the usual __get() magic method
return parent::__get($key);
}
}
This way you pretty much safe from interface change (the __get() magic method is unlikely to change). As a bonus I also added in the hasMutator() check so that you have flexibility in your models to explicitly define a getter for an overridden attribute...
Cheers, Darryl
Could you add a column to the Post
table that was JSON (which can be cast to an array).
You could then just do key-values in that column for overrides.
Then overwrite the magic method for accessing properties, and if the key exists in the overrides, return that instead.
This would mean any internal methods have access to the attributes
array for originals, or the magic method accessor for the modified.
Alternatively, you could override the construct
method, and load the overrides into the attributes instead of the original data.
However, this might cause problems on save
This is only "in my head" code, but I look at the loop over all the attributes, all the time & think that's not very optimal.
Would a better approach be to load all the Post records from the overrideables in a single call and just merge them with your $this->attributes?
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community