undefined associatedModel function in CartItem's __get method
rucky96 opened this issue · 5 comments
Hi,
I was trying to get the associated model from the cart item with $cartItem->model
. However, it returns null.
I have seen that in CartItem class there is a call to the associatedModel function within __get method:
/**
* Get an attribute from the cart item or get the associated model.
*
* @param string $attribute
*
* @return mixed
*/
public function __get($attribute)
{
if (property_exists($this, $attribute)) {
return $this->{$attribute};
}
$decimals = config('cart.format.decimals', 2);
switch ($attribute) {
case 'model':
if (isset($this->associatedModel)) {
return with(new $this->associatedModel())->find($this->id);
}
// no break
case 'modelFQCN':
if (isset($this->associatedModel)) {
return $this->associatedModel;
}
// no break
case 'weightTotal':
return round($this->weight * $this->qty, $decimals);
}
$class = new ReflectionClass(config('cart.calculator', DefaultCalculator::class));
if (!$class->implementsInterface(Calculator::class)) {
throw new InvalidCalculatorException('The configured Calculator seems to be invalid. Calculators have to implement the Calculator Contract.');
}
return call_user_func($class->getName().'::getAttribute', $attribute, $this);
}
I have not seen where this function is defined. I have removed the '()' and now it works for me, is this a bug?
Edited your messages markdown for readability. For multi-line code blocks you have to use three ``` like this before the first and after the last line :)
Hi,
I was trying to get the associated model from the cart item with
$cartItem->model
. However, it returns null.I have seen that in CartItem class there is a call to the associatedModel function within __get method:
/** * Get an attribute from the cart item or get the associated model. * * @param string $attribute * * @return mixed */ public function __get($attribute) { if (property_exists($this, $attribute)) { return $this->{$attribute}; } $decimals = config('cart.format.decimals', 2); switch ($attribute) { case 'model': if (isset($this->associatedModel)) { return with(new $this->associatedModel())->find($this->id); } // no break case 'modelFQCN': if (isset($this->associatedModel)) { return $this->associatedModel; } // no break case 'weightTotal': return round($this->weight * $this->qty, $decimals); } $class = new ReflectionClass(config('cart.calculator', DefaultCalculator::class)); if (!$class->implementsInterface(Calculator::class)) { throw new InvalidCalculatorException('The configured Calculator seems to be invalid. Calculators have to implement the Calculator Contract.'); } return call_user_func($class->getName().'::getAttribute', $attribute, $this); }
I have not seen where this function is defined. I have removed the '()' and now it works for me, is this a bug?
i got same issue, which '()' you removed as temp solution ? can you mark it up for my reference ?
if i had to guess i think you are talking about:
if (isset($this->associatedModel)) {
return with(new $this->associatedModel())->find($this->id);
}
And yes, associatedModel
is not a function in the CartItem class. associatedModel
is an attribute that should contain the FQCN of your model, so it should be a string like \\App\\Models\\Model
. In PHP you can initiate a class from a SQCN like so:
$fqcn = MyClass::class;
$instance = new $fqcn()
$instance = new (MyClass::class)();
$instance = new ('\\Namespace\\MyClass')();
So the () should be valid there, the automated tests are working too. Can you please check the value of associatedModel
, if it is null your model is simply not associated.
if i had to guess i think you are talking about:
if (isset($this->associatedModel)) { return with(new $this->associatedModel())->find($this->id); }
And yes,
associatedModel
is not a function in the CartItem class.associatedModel
is an attribute that should contain the FQCN of your model, so it should be a string like\\App\\Models\\Model
. In PHP you can initiate a class from a SQCN like so:$fqcn = MyClass::class; $instance = new $fqcn() $instance = new (MyClass::class)(); $instance = new ('\\Namespace\\MyClass')();
So the () should be valid there, the automated tests are working too. Can you please check the value of
associatedModel
, if it is null your model is simply not associated.
I'm newbie for php and laravel.
this my sample controller function store
Cart::add($item->id, $item->name, 1, $item->price, $item->weight)
->associate('App\Model\Product');
and this in CartItem.php
switch ($attribute) {
case 'model':
if (isset($this->associatedModel)) {
return with(new $this->associatedModel())->find($this->id);
}
// no break
case 'modelFQCN':
if (isset($this->associatedModel)) {
return $this->associatedModel;
}
// no break
case 'weightTotal':
return round($this->weight * $this->qty, $decimals);
}
so where i should put these codes ?
$fqcn = MyClass::class;
$instance = new $fqcn()
$instance = new (MyClass::class)();
$instance = new ('\\Namespace\\MyClass')();
No no, this is just an example.
Important for you:
MyClass::class === '\\MyClass';
So use YourModel::class
or use \\ to escape the \. \ is the escape character and has always to be used with caution in strings
https://en.m.wikipedia.org/wiki/Escape_character
https://stackoverflow.com/a/25459324
So in your case you could try:
Cart::add($item->id, $item->name, 1, $item->price, $item->weight)
->associate('\\App\\Model\\Product');
Or, what i prefer due to better type hinting (but sometimes is not the right choice for example if Product is not available up until execution so you can not reference it):
Cart::add($item->id, $item->name, 1, $item->price, $item->weight)
->associate(Product::class);
@rucky96 Check modelFQCN which is associatedModel directly. If it is not null and model does return null it maybe can not find the model via the id so it maybe got (soft-)deleted.