Two libraries provide each inside a trait, a method to override a default base class method.
// This is a Framework base class
class Model {
function getAttribute($key) {
return "Model->$key";
}
}
// This is a trait from library A which provides extra stuff
trait HasUuid {
function getAttribute($key) {
if ($key==='uuid') return "HasUuid->$key";
return parent::getAttribute($key);
}
}
// This is a trait from library B which provides extra stuff
trait HasQuantity {
function getAttribute($key) {
if ($key==='quantity') return "HasQuantity->$key";
return parent::getAttribute($key);
}
}
Now, I have a class in my application which inherits from Model and needs to use both traits.
PHP allows to alias the trait functions in order to resolve naming conflicts between libraries. So here is what I end up with:
class Product extends Model {
use HasUuid { getAttribute as getHasUuidAttribute; }
use HasQuantity { getAttribute as getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
We end up with a recursion issue: when calling the overridden trait methods, their refer to the parent::getAttribute method which triggers another call to Product::getAttribute which recurses infinitly.
How can we solve this recursion issue, by keeping access to both trait features?
Of course, as the traits each come from a library, I cannot change their code.
You can take advantage of making these private using a private keyword.
class Product extends Model {
use HasUuid { getAttribute as private getHasUuidAttribute; }
use HasQuantity { getAttribute as private getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With