我从getReward1
和getReward2
得到了不同的结果:
:
class User extends Authenticatable
{
public function Products()
{
return $this->hasMany('AppProduct', 'user_id');
}
public function getReward1()
{
return $this
->Products
->where('reward', '>', 0)
->where('status', 0)
->sum('reward'); // sum = 7,690,000
}
public function getReward2()
{
return $this
->Products()
->where('reward', '>', 0)
->where('status', 0)
->sum('reward'); // sum = 7,470,000
}
}
getReward1
返回7,690,000,getReward2
返回7,470,000(两个不同的值)
$this->Products
和$this->Products()
有什么不同?
$this->products;
// Returns a Collection
$this->products();
// Returns a Relation instance, which is a query builder and can be of type HasMany, BelongsTo...
$this->products()->get();
// Is EXACTLY like doing $this->products for the first time.
主要区别在于products()
只是一个尚未执行的查询,而products
是该查询的实际结果。
老实说,即使名字相同,可能会让人混淆,但它们之间没有其他相似之处。
一个简单的类比:
DB::table('products')->where('user_id', 18); //could be the $user->products()
DB::table('products')->where('user_id', 18)->get(); //could be $user->products
这只是一个类比,内部并不完全是这样,但是你明白了。
为了增加更多的混乱,集合方法通常与你在查询中找到的方法相似;都有where()
,first()
…
要记住的主要事情是,使用括号,您仍然在构建查询。在调用get
或first
之前,您一直处于查询生成器中。
没有,你已经有了你的结果,你是在一个集合(https://laravel.com/docs/8.x/collections)。
关于getReward1
和getReward2
之间的差异,如果没有看到数据库结构,很难确切地知道发生了什么。
它可以是很多东西,但是当你调用sum
方法时,你是在getReward1
的Collection实例上调用它,在getReward2
的查询生成器上调用它(你实际上是在用SELECT SUM(reward)...
执行查询)。
$this->Products()
将返回查询生成器的一个实例。随后的where
子句将约束DB查询,然后只返回您想要的产品。这些将不会存储在模型实例中。
$this->Products
将从DB中获取所有产品,并将它们作为Eloquent Collection存储在模型实例中。随后的where子句将在Eloquent Collection上执行。
本质上,方法在DB中做所有的事情,然而,属性是获取所有的行,然后用PHP限制它。