Не отображается имя пользователя с помощью отношений
Есть код отображения
@foreach($chats as $chat)
<a class="flex items-center px-3 py-2 text-sm transition duration-150 ease-in-out border-b border-gray-300 cursor-pointer hover:bg-gray-100 focus:outline-none">
<img class="object-cover w-10 h-10 rounded-full" src="INGAME_free-file.png" alt="username" />
<div class="w-full pb-2">
<div class="flex justify-between">
<span class="block ml-2 font-semibold text-gray-600">{{ $chat->sender == Auth::user()->id ? $chat->recipient->name : $chat->sender->name }}</span>
<span class="block ml-2 text-sm text-gray-600">25 minutes</span>
</div>
<span class="block ml-2 text-sm text-gray-600">bye</span>
</div>
</a>
@endforeach
В моделе чат я делаю 2 отношения
public function sender()
{
return $this->belongsTo(User::class, 'sender');
}
public function recipient()
{
return $this->belongsTo(User::class, 'recipient_id');
}
И получается так, что функция recipient возвращает имя пользователя, а функция sender нет. Если вывести $chat->sender, то он покажет правильный id пользователя, но достучаться до его имени не получается
Ответы (1 шт):
У вас ошибка в том, что имя метода и имя связующего ключа одинаковые. Переименуйте поле в таблице sender на sender_id и всё заработает. Плюс это правильный подход в плане наименования. Не надо смешить стили написания и так далее. Где-то писать sender где-то Sender, а где-то sender_id.
После того как исправите. Возникает следующая проблема, которую будете замечать и отслеживать сразу как наберётесь больше опыта. Это касается вывода на страницу.
Нельзя в цикле (в данном случае в цикле foreach($chats as $chat)) делать вызов связующего отношения (в данном случае $chat->sender) таким способом как Вы делаете. Так как когда вы делаете данную операцию, то на каждом этапе цикла идёт запрос к базе данных. То есть если у вас в переменной $chats будет 100 элементов, то будет 100 доп запросов к бд. Если зайдут 10 пользователей на сайт одновременно, то будет 1000 запросов в секунду, в результате сервер может упасть.
Решение
В ларавель есть два метода для ленивой загрузки Первый метод load(). Вызывается на коллекции элементов (лучше в контроллере) $chats->load('sender') (можно передавать массив зависимостей $chats->load([...])). В результате когда будет произведён вызов sender то ларавель поймет что надо минимизировать кол-во запросов. То есть данные будут загружены только тогда, когда Вы их запросите при этом минимизировав нагрузку
Второй метод решающий проблему это ->with('sender') работает точно так же за исключением того, что он сразу в коллекцию результатов выполнения запроса подгружает необходимые зависимости. И поэтому вызывается на билдере Chat::where('recipient_id', Auth::user()->id)->with('sender')... После в переменной $chats сразу будет массив с отправителем. И вызов $chat->sender не будет делать запроса в принципе. Подробнее можете почитать в документации, когда лучше использовать один, а когда другой.