简体   繁体   中英

Laravel Eloquent - relations method is returning HasMany object and property is returning Collection

I have a simple questions but I cant find any answer in internet.

class Product extends Model
{
    use HasFactory;

    public function variants()
    {
        return $this->hasMany(Variant::class);
    }
}

>>> $p->variants();
=> Illuminate\Database\Eloquent\Relations\HasMany {#4331}
>>> $p->variants;
=> Illuminate\Database\Eloquent\Collection {#4310
     all: [
       App\Models\Variant {#4319
         id: "1",
         name: "VariantOne",
         created_at: null,
         updated_at: null,
         quantity: "2",
         product_id: "1",
       },
     ],
   }

Why while I'm using method variants() I got empty HasMany object but when I use just a variants property, I got a Collection with properly data?

And how did variants property comes up to live? I don't have it defined in my Product class.

Take a look at thedocs . It explains how you can use Eloquent's relations for this particular purpose. It explains more about the dynamic property given here

This is designed to flawlessly be able to query on relationships, while also being able to quickly receive them.

As you said yourself:

  • variants() returns the hasMany relation, which is just an addition on the query Builder . You use this when you want to query further on this relation: Product::find(1)->variants()->where('quantity', '>', 0)->get()
  • variants returns the Collection instance just like if you had done variants()->get() , except you can continue to access this Collection from the Product Model , it won't re-call them from the database. When querying on this, you'll be querying on the Collection , not the query Builder .

It's because variant is a dynamic property. You could achive something similar (simplified) this way:

class Model
{
    public function dynamicProperty()
    {
        return 'dynamic value';
    }

    public function __get(string $property)
    {
        if ($property === 'dynamicProperty') {
            return $this->dynamicProperty();
        }
    }
}

Of course, laravel does a lot more under the hood but variant is much like variants()->get() and HasOne / HasMany / BelongsTo is mostly a wrapper for Builder .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM