Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting model belongsTo attributes

class Batch extends Eloquent {
    public function coupons() {
        return $this->hasMany('Coupon');
    }
}

class Coupon extends Eloquent {
    public function batch() {
        return $this->belongsTo('Batch');
    }
    public function price() {
        $batch = $this->batch;
        return $batch->price;
    }
}

$coupon->price gives me this error:-

LogicException Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

However, $coupon->batch->price works just fine.

What am I missing?

like image 892
Zayin Krige Avatar asked Dec 17 '25 13:12

Zayin Krige


1 Answers

Your issue here is that you define a non-relationship method price() but you call it as if it was a relationship method (i.e. you call it as a property and not as a method).

The code you should be using to get the Coupon's price is:

$coupon->price();

The reason the relationship thing works (i.e. $coupon->batch over $coupon->batch()) is that Laravel has some special logic in - basically it catches you trying to access a property (->batch in this case) and checked to see if there's a corresponding method (->batch()). If there is one, it calls it and expects it to return a relationship, and then it calls ->first() of ->get() on that relationship depending on whether it's a single-result or a multiple-result relationship.

So what's happening in your code here is that you call $coupon->price and Laravel, behind the scenes, decides that being as there's a ->price() method it must be a relationship. It calls the method, checks that it returns one of the Laravel relationship types, and when it doesn't, throws that LogicException.

The general rules of thumb is this:

  • If you want an actual property (i.e. anything defined on the table) or the results of a relationship query, use property access
  • If you want anything else (i.e. behaviour you're defined using a method) you must call the method directly

Also, sometimes there is a good reason to call a relationship as the method rather than the property - calling the method returns something you can add query builder constraints on to, whereas calling the property gets you all the results. So say Coupons can be enabled or disabled (for example), the following holds:

  • $batch->coupons gets you all coupons that the batch has
  • $batch->coupons()->whereEnabled(1)->get() gets you all enabled coupons for a given batch
  • $batch->coupons()->orderBy('order')->get() gets you all the coupons that the batch has, ordered by a field called order
  • $coupon->batch gets you the given coupon's batch

Hopefully that explains the difference between Eloquent's use of methods versus properties for relationships, and why all augmented behaviour (like price on coupon in your example, but not price on batch, which is inherent behaviour) must be called as a method.

like image 61
alexrussell Avatar answered Dec 20 '25 01:12

alexrussell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!