laravel-从雄辩模型中获取单个值,并将其与数据作为单个字段导入

时间:2019-02-22 19:12:38

标签: laravel eloquent model

我有一个称为PRODUCT的模型,它与模型REVIEW有一对多的关系。 REVIEW表中有一个“ rate”列,当我检索所有产品时,我希望REVIEW表中的平均率与PRODUCT数据相关联。 我试图在PRODUCT模型中创建一种方法,以在::with()命令中调用“ rate”来执行该操作,这就是代码:

class Product extends Model{
public function rate(){
    return $this->hasMany('App\Review')->select('rate')->avg('rate');
}

在控制器中:

return Product::with('rate')->get();

但是我总是遇到错误。

那么有可能在模型中做到这一点,或者还有其他方法吗? 任何帮助表示赞赏。

4 个答案:

答案 0 :(得分:1)

您可以尝试以下操作:

class Product extends Model{

    public function review(){
        return $this->hasMany('App\Review');
    }

    public function rate(){
        return $this->review()->avg('rate'); // chain your query here
    }

}

然后您可以通过以下方式访问它:

$product = Product::find(1);
dd($product->rate()->get());

答案 1 :(得分:1)

Laravel使用许多魔术方法。您可以使用类似这样的内容。

class Product extends Model{
    public function Reviews(){
        return $this->hasMany(Review::class);
    }
    public functions getRatingAttribute(){
        return $this->Reviews->avg('rate');
    }
}

然后您可以像这样访问...

Product::find(1)->rating;

答案 2 :(得分:1)

最好使您的方法尽可能容易地定义关系。

public function reviews(){

    return $this->hasMany('App\Review');
}

现在,您可以使用此关系来获取费率。您可以通过不同的方式进行操作:

1。将其添加为appended property

您可以添加模型中没有列的属性作为附加属性。

protected $appends = ['rate'];

,然后具有分配值的功能:

public functions getRateAttribute(){

     return $this->reviews->avg('rate') ?? 0;
}

问题是,顾名思义,附加属性始终附加在模型实例上。

因此,如果您只执行以下操作:

$product = Product::first();

即使您不需要费率,laravel仍然会为您准备好$product->rate,因此它将进行平均查询。

2。将其作为方法:

当您可以将其作为方法创建时,这是一个选项:

public functions getRate(){

     return $this->reviews->avg('rate') ?? 0;
}

它的优点是,您可以在需要时使用它。这样可以节省很多不必要的查询,即使您不需要它,也可以使用附加属性函数来完成。

然后可以使用它:

$product = Product::first();

// The query fo average will be done below only when you call `getRate` on `$product`

$rate = $product->getRate();

如果我可以选择的话,我会把它作为选项2。

也请注意Laravel的avg('column_name)

  • 如果没有数据,它将显示null
  • 如果对非数字列求平均值,它会给0.0之类的值
  • 如果存在的值大于2个小数点(大多数为4个),则以格式3.9265给出有效值

因此您可以相应地使用功能。

答案 3 :(得分:0)

所有上述解决方案均导致N + 1问题。您可以在下面尝试实现热切加载

namespace App;
use DB;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class Product extends Model
{
    public function reviews()
    {
        return $this->hasMany('\App\Review');
    }

    public function ScopeAverageRating(Builder $query){
        return $query->withCount(['reviews as average_rating' => function ($query) {
            $query->select(DB::raw("avg(rate)"));
        }]);
    }

}

然后在您的控制器中,您可以使用App \ Product :: AverageRating()它将返回您的集合,可以对其进行迭代以获取average_rating。