Laravel получает один связанный атрибут

У меня есть приложение laravel, которое позволяет пользователям публиковать сообщения. Каждый пост имеет цену (хранится в виде целого числа) и принадлежит университету, который, в свою очередь, принадлежит стране, в которой есть валюта.

Каждый раз, когда я получаю сообщения, я хочу вернуть и валюту. Я мог бы сделать with('university.country'), но это вернет все детали как по университету, так и по стране.

Я мог бы добавить getCurrencyAttribute и определить там логику, но мутаторы, похоже, не для этого, тем более, что если я получу все сообщения, каждое сообщение будет запускать два собственных запроса, просто чтобы получить валюту. Это 3 запроса для получения одного сообщения, что быстро сказывается при возврате более 10 сообщений.

public function getCurrencyAttribute() {
        return $this->university->country->currency;
    }

    public function getPriceAttribute($value) {
        return "{$this->currency}{$value}";
    }

^ пример выше: нет необходимости в appends, потому что price автоматически перезаписывается. Это проблема, как видно на DebugBar (в модели Post вызываются два новых запроса, которые, хотя и ожидались, становятся неэффективными при получении большого количества сообщений): Laravel получает один связанный атрибут

Как лучше всего каждый раз получать одно связанное поле?

Полный код на GitHub.

Вы можете показать свой точный запрос?

Jackowski 18.04.2018 12:54

Запрос Eloquent изначально довольно прост: Post::get(). Смотрите полный код на GitHub :)! В настоящее время используется метод with для получения валюты, но он кажется неэффективным.

Michał 18.04.2018 12:59

Вы можете использовать именно аксессоры, они предназначены для получения значения настраиваемого атрибута из модели.

thefallen 18.04.2018 15:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
1
3
82
1

Ответы 1

Вы можете ограничить количество столбцов активной загрузки:

Post::with('webometricUniversity:uni-id,country_id',  
    'webometricUniversity.country:id,currency')->get();

Если он вам всегда нужен, добавьте это в свою модель Post:

protected $appends = ['currency'];

protected $with = ['webometricUniversity:uni-id,country_id',  
    'webometricUniversity.country:id,currency'];

public function getCurrencyAttribute() {
    return $this->webometricUniversity->country->currency;
}

Тогда вы можете просто использовать Post::get() и $post->currency.

Я мог бы - но в идеале мне всегда нужна валюта при получении цены, поэтому я хотел бы настроить ее в модели, чтобы она всегда вытягивалась.

Michał 18.04.2018 19:49

Я расширил свой ответ.

Jonas Staudenmeir 18.04.2018 19:53

Выглядит хорошо, и хотя я еще не пробовал, похоже, он отлично работает! Единственное, что это просто выглядит для меня в том смысле, что я ожидал, что laravel уже будет какой-то реализацией или помощником, который занимается моей проблемой - это просто кажется обычным случаем, особенно для супер-нормализованных баз данных

Michał 18.04.2018 20:32

Как $withнет «реализация или помощник, решающий мою проблему»?

Jonas Staudenmeir 18.04.2018 20:34

Да, я думаю, вы правы: P Просто любопытно, если я установлю $with в модели, как вы показали выше, а затем снова вызову with('webometricUniversity') в контроллере, чтобы получить все сведения об университете, будет ли таблица удаляться дважды или laravel объединит withs ? Как вы думаете, это вообще правильный подход к валюте и ценообразованию в db: P?

Michał 18.04.2018 20:42

Они объединяются, и with() имеет приоритет над $with.

Jonas Staudenmeir 18.04.2018 20:55

Если вам нужна валюта всегда, возможно, денормализация стоит того.

Jonas Staudenmeir 18.04.2018 21:04

Хорошо, код определенно работает, но я хотел бы получить его плоскую, а не вложенную, иначе говоря, чтобы поле валюты было только полем цены, а не вложено в webometricUniversity.country. Как я это сделал? Мне буквально просто нужно поле валюты ...

Michał 19.04.2018 13:51

Вы используете аксессуар: getCurrencyAttribute: return $this->webometricUniversity->country->currency;

Jonas Staudenmeir 19.04.2018 13:53

Да, это определенно работает. Я видел в нескольких статьях, как я уже упоминал в вопросе, что использование мутаторов / аксессуаров для этого не является хорошей идеей и не для того, для чего они предназначены ... но если это работает, то работает;)! Если вы обновите свой ответ, также включите protected $appends = [ 'currency' ];, чтобы другие могли видеть, как всегда прикреплять атрибут;)

Michał 19.04.2018 13:57

Я обновил свой ответ. Я не вижу причин, по которым это было бы плохой идеей.

Jonas Staudenmeir 19.04.2018 14:04

Просто на что-то наткнулся. При вызове списка сообщений каждое сообщение дополнительно выполняет запрос, чтобы получить университет, затем страну, всего 2 новых (нежелательных) запроса на сообщение вместо 1 запроса, чтобы получить все сообщения и валюту ... Есть мысли?

Michał 10.05.2018 16:24

Вы используете ускоренную загрузку?

Jonas Staudenmeir 10.05.2018 16:43

Нет, мне он нужен как атрибут, так как он переопределяет значение цены по умолчанию ... Жадная загрузка вернет меня к исходной точке. Могу ли я загрузить атрибут?

Michał 10.05.2018 17:11

Можете ли вы добавить в свой вопрос код, который вы используете?

Jonas Staudenmeir 10.05.2018 17:25

Просто сделал :) Также я обновил весь код на GitHub, что может дать немного больше информации :)

Michał 10.05.2018 18:12

Где вы получаете доступ к currency и / или price?

Jonas Staudenmeir 10.05.2018 20:11

Вызов Post::get() в контроллере сообщений в простейшем смысле. В модели уже есть поле цены, поэтому, когда я получаю атрибут цены, он просто перезаписывает значение новым, как в вопросе. На GitHub он немного расширен, но вы заметите, что мне не нужно специально называть атрибут цены: github.com/mwargan/JustBookr/blob/master/app/Http/Controller‌ s /…

Michał 10.05.2018 20:58
Post::get() выполняет запросы для university и country?
Jonas Staudenmeir 10.05.2018 23:58

Ну, получая сообщения, он автоматически вызывает getPriceAttribute, который затем, в свою очередь, запрашивает university, а затем country для каждого полученного сообщения ... Итак, насколько я вижу, и панель отладки сообщает мне, да, он выполняет два других запрашивает один раз для каждого возвращенного сообщения.

Michał 11.05.2018 00:01

Я не могу воспроизвести это.

Jonas Staudenmeir 11.05.2018 00:03

Странно ... что тут могло помочь? Добавляете скриншоты запросов отладочных панелей?

Michał 11.05.2018 00:05

Позвольте нам продолжить обсуждение в чате.

Jonas Staudenmeir 11.05.2018 00:06

Другие вопросы по теме