Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Вы не вошли.

#1 17.06.2017 12:16:12

Androbim
Участник с 23.06.2015
Сообщений: 248

Eloquent, алиас для динамического атрибута

Доброго времени суток!

1...
2       ->with(['score' => function ($query) use ($competitor) {
3            $query->whereIn('competitor_id', [$competitor->id]);
4        }])
5        ->with(['score as score_actual' => function ($query) use ($competitor) {
6            $query->whereIn('competitor_id', [$competitor->id])->whereIn('is_actual', [1]);
7        }])
8...

В пятой строчке тупо, на "а вдруг?!", указан алиас для динамического атрибута 'score as score_actual', и это не работает:

Call to undefined relationship [score as score_actual] on model [App\Referee]

Возможно ли какое-то корректное решение, на уровне контроллера, в этой ситуации?

С уважением.

Не в сети

#2 17.06.2017 17:01:11

constb
Участник с 19.02.2015
Сообщений: 508

Re: Eloquent, алиас для динамического атрибута

очевидно – добавить на модель App\Referee связь score_actual, с where

Не в сети

#3 17.06.2017 22:05:35

Androbim
Участник с 23.06.2015
Сообщений: 248

Re: Eloquent, алиас для динамического атрибута

Ну, это да. А на уровне контроллера никак? :-(
Считайте, ради интереса уже.

Не в сети

#4 18.06.2017 09:17:52

constb
Участник с 19.02.2015
Сообщений: 508

Re: Eloquent, алиас для динамического атрибута

во-первых

Ну, это да. А на уровне контроллера никак?

с помощью ->with() – нет, with грузит конкретные связи и кладёт их в конкретные атрибуты модели. естественно что несмотря на то что score и score_actual связывают referee с одной и той же моделью, у них разная логика и разный смысл, поэтому это разные связи.

если взять абстрактный пример: модель Post и у неё есть поля written_by (belongsTo), approved_by (belongsTo) и связь commented_by (hasMany) – все три связи идут на модель User, но их семантика различается и нет смысла пытаться их объединить как-то в одну, это просто разные связи

я понимаю что ты смотришь на это с точки зрения построения sql-запроса, его таблиц и полей, а не с точки зрения ORM, поэтому у тебя возникает этот вопрос. если смотреть со стороны объектов и их связей, то надо спросить себя – логически связь score_actual – это то же самое что score или нет?

во-вторых

Считайте, ради интереса уже.

я думаю что ты это делаешь не ради интереса а ради оптимизации. и тут тебе такой вопрос – а нужно ли выбирать данные (score_actual) которые у тебя уже есть? ведь в score эти actual уже есть, а поскольку $referee->score это коллекция с полем actual на моделях, тебе вообще ничего не стоит получить эти score_actual из этой коллекции уже в момент когда они нужны!

мой вариант – добавить на App\Referee метод

public function getScoreActualAttribute() {
    return $this->score->whereIn('is_actual', [1]);
}

теперь если ты загрузил связь score с нужными тебе условиями, то в $referee->score_actual ты получишь те же данные но с фильтром по actual – на один запрос в базу меньше, данные те же. бери и выводи в шаблоне или обрабатывай в коде как тебе нужно

Не в сети

#5 18.06.2017 12:13:49

Androbim
Участник с 23.06.2015
Сообщений: 248

Re: Eloquent, алиас для динамического атрибута

Да, спасибо, решение очевидно и ответ принят, я так и поступлю.
Каюсь, я действительно не задумывался особо, что из себя представляет, на самом деле, динамический атрибут - поля из JOUN или вложенный SELECT..? Работает, и ладно. Пока не столкнулся с вышеописанной ситуацией.

Конечно же, данные в наборе есть и вот это (css-стили убрал)   - работает:

@foreach($referee->score as $score)
     @if($score->is_actual == 0)
         <small>{{$score->score}}</small>&nbsp;&nbsp;&nbsp;&nbsp;
         <small>{{ date('d.m.Y', strtotime($score->created_at)) }}</small>
     @else
          <small>{{$score->score}}</small>&nbsp;&nbsp;&nbsp;&nbsp;
          <small>{{ date('d.m.Y', strtotime($score->created_at)) }}</small>
          <br>
      @endif
@endforeach

Это, как ты наверняка догадался, отображается история баллов, и, в зависимости от значения поля is_actual применяется тот или иной стиль.
А если, где-то в другом месте, нужно отобразить только актуальный балл?
А может, есть способ в представлении как-то вытащить актуальный балл из этого,

 ->with(['score' => function ($query) use ($competitor) {$query->whereIn('competitor_id', [$competitor->id]);

При условии, что актуальный всегда существует, если какие-то баллы вообще имеются. Ну, и если это поэлегантнее, чем в цикле перебрать :-)

Ну, а ежели это никак, воспользуюсь "модельным" решением.

Не в сети

#6 18.06.2017 14:12:01

constb
Участник с 19.02.2015
Сообщений: 508

Re: Eloquent, алиас для динамического атрибута

во-первых, использование &nbsp; и <br> для позиционирования элементов? я очень надеюсь что это черновая вёрстка и никогда не пойдёт в продакшен smile

во-вторых, а актуальный балл – он в единственном числе существует или в нескольких? я не понял самой структуры – referree назначают баллы, а потом из них вычисляется какой-то один актуальный и он сохраняется в ту же таблицу вместе со всеми остальными баллами что ли?

Не в сети

#7 18.06.2017 14:30:19

Androbim
Участник с 23.06.2015
Сообщений: 248

Re: Eloquent, алиас для динамического атрибута

Эх... Ладненько, в принципе, ответ на вопрос я получил, за что "весьма Вами благодарен" :-)

Не в сети

Подвал раздела