The rewritten title is: What causes a "possible infinite loop" when accessing another model attribute in an appended attribute of a model?
P粉786432579
P粉786432579 2023-09-04 17:47:10
0
1
471
<p>My <strong>Laravel 9</strong> application has two models: the <code>brand</code> model and the <code>product</code> model. Each <code>product</code> belongs to one <code>brand</code>, and one <code>brand</code> belongs to multiple <code>products</code> (1: n relationship). The <code>product</code> model should provide a "calculated" (additional) property called <code>title_medium</code> that concatenates the brand title and product title upon request. </p> <p>Once I try to access <code>$this->brand</code> in the product model's <code>getTitleMediumAttribute()</code> method, <code>xdebug</code> The <code>possibleInfiniteloop</code> exception will be thrown and execution will be canceled (after N iterations). I think this has something to do with relationships and load sequences (eager loading) but I can't find a solution so far. </p> <h2>Brand Model</h2> The <p><code>brand</code> model has an attribute <code>title</code> and has a number of <code>products</code> belonging to <code>brand</code>. </p> <pre class="brush:php;toolbar:false;">namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Str; class Brand extends Model { use HasFactory; /*** Additional attributes for this model*/ protected $appends = [ 'prices' ]; protected $fillable = [ 'title' ]; /*** The "booted" method of the model. * * @return void*/ protected static function booted() { static::creating(function ($brand) { $brand->slug = Str::slug($brand->title, '-', 'de'); }); } /*** Returns all products for a brand * * @return HasMany*/ public function products(): HasMany { return $this->hasMany(Product::class); } }</pre> <h2>Product model number</h2> <p>Each <code>product</code> belongs to a <code>brand</code>. The additional attribute <code>title_medium</code> should concatenate the brand title and product title.</p> <pre class="brush:php;toolbar:false;">namespace App\Models; class Product extends Model { use HasFactory, Searchable, Filterable; protected $fillable = [ 'title', 'brand_id', 'image' ]; /*** Additional attributes for this model*/ protected $appends = [ 'title_long', 'lowest_price', 'highest_discount_percent_price', 'latest_price_date', 'price_count' ]; /*** The "booted" method of the model. * * @return void*/ protected static function booted() { static::creating(function ($product) { $product->slug = Str::slug($product->title_long, '-', 'de'); }); } /*** Product belongs to one brand*/ public function brand(): BelongsTo { return $this->belongsTo(Brand::class); } /*** Get the combined title from product and brand*/ public function getTitleMediumAttribute(): string { // THIS CAUSES A "POSSIBLE INFINITE LOOP EXCEPTION" in xdebug return $this->brand->title . ' ' . $this->title; } }</pre></p>
P粉786432579
P粉786432579

reply all(1)
P粉306523969

Try using attribute instead of getTitleMediumAttribute, like this and tell me if you still get the same error (using this method instead of `getTitleMediumAttribute):

public function titleMedium(): Attribute
{
    return Attribute::get(
        fn () => "{$this->brand->title} $this->title",
    );
}

Attribute is \Illuminate\Database\Eloquent\Casts\Attribute

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template