laravel - получить одно значение из eloquent модели для импорта с данными в виде одного файла - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть модель под названием PRODUCT, которая имеет отношение один ко многим с моделью REVIEW.таблица REVIEW имеет столбец 'rate', и я хочу, чтобы средняя скорость из таблицы REVIEW была связана с данными PRODUCT при получении всех продуктов.Я попытался создать метод в модели PRODUCT для вызова 'rate' в команде ::with(), чтобы сделать это, и это код:

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

в контроллере:

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

но я продолжаю в конечном итоге с ошибками ..

так возможно ли это сделать в модели или есть какой-либо другой способ?Любая помощь приветствуется.

Ответы [ 4 ]

0 голосов
/ 23 февраля 2019

Все вышеперечисленные решения приводят к проблеме 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 (), он вернет вам коллекцию, которую можно повторять для получения среднего значения.

0 голосов
/ 22 февраля 2019

Ларавел использует много магических методов.Вы можете подключиться к этому с помощью чего-то подобного.

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

, тогда вы можете получить доступ вот так ...

0 голосов
/ 23 февраля 2019

Лучше, чтобы ваши методы определения отношений были как можно более простыми.

public function reviews(){

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

Теперь вы можете использовать это отношение, чтобы получить показатель.Вы можете сделать это по-разному:

1.Добавляя его как добавленное свойство :

Вы можете добавить свойство, которое не является столбцом в вашей модели, в качестве добавленного свойства.

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's avg('column_name):

  • Это дает null, когда нет данных
  • Это дает значение что-то вроде 0.0 еслиВы усредняете нечисловой столбец
  • Дает допустимое значение в формате 3.9265, если присутствует значение, которое превышает 2 десятичных знака (в основном 4)

Таким образом, вы можете иметьваша функция соответственно.

0 голосов
/ 22 февраля 2019

Вы можете попробовать что-то вроде этого:

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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...