Support the ongoing development of Laravel.io →
posted 8 years ago
Eloquent
Last updated 2 years ago.
0

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

0

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

0

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?

0

Sign in to participate in this thread!

Eventy

Your banner here too?

jobbrown jobbrown Joined 20 Jan 2015

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.