#laravel
#laravel
Вопрос:
Я хочу получить аватар пользователя из моей таблицы пользователей, когда у меня есть только имя пользователя из моей таблицы сообщений.
Я пытался создать цикл foreach следующим образом:
$posts = Post:all();
foreach($posts as $post) {
$user = User::where('name', $post->creator)->get();
}
return view('welcome')->with('posts', $posts)->with('user', $user);
Затем зацикливаю его, на мой взгляд, следующим образом:
@foreach($posts as $post)
@foreach($user as $creator)
<span>{{ $creator->avatar }}</span>
<span>{{ $post->post_url }}</span>
@endforeach
@endforeach
Но он возвращает мне то же изображение аватара, а не изображение аватара пользователя, которое принадлежит сообщению.
Моя модель пользователя:
protected $fillable = [
'name', 'email', 'password', 'avatar', 'full_name', 'slug'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function posts() {
return $this->hasMany(Post::class, 'creator','name');
}
Модель публикации:
protected $fillable = [
'creator', 'post_url', 'game', 'likes', 'created_at'
];
public function user() {
return $this->belongsTo(User::class);
}
Мой web.php:
Route::get('/', 'PostController@main_page');
Моя функция main_page:
public function main_page()
{
$posts = Post:all();
foreach($posts as $post) {
$user = User::where('name', $post->creator)->get();
}
return view('welcome')->with('posts', $posts)->with('user', $user);
}
Может кто-нибудь просветить меня и направить на правильный путь? Спасибо!
Ответ №1:
Вы переопределяете $user
переменную для каждого сообщения. Вместо этого сохраните его в массиве:
$posts = Post::all();
$users = [];
foreach($posts as $post) {
$users[$post->id] = User::where('name', $post->creator)->get();
}
return view('welcome')->with('posts', $posts)->with('users', $users);
Затем в представлении:
@foreach($posts as $post)
<span>{{ $users[$post->id]->avatar }}</span>
<span>{{ $post->post_url }}</span>
@endforeach
Но лучшим решением было бы сохранить id
имя пользователя внутри posts
таблицы, а не только имя, и добавить связь. Тогда код будет:
$posts = Post::with('user')->get();
return view('welcome')->with('posts', $posts);
with('user')
предварительно загружает связь, чтобы не генерировать слишком много запросов. Если вам нужен только аватар, вы можете повысить его производительность, используя with('user:avatar')
вместо этого.
Тогда представление будет выглядеть так:
@foreach($posts as $post)
<span>{{ $post->user->avatar }}</span>
<span>{{ $post->post_url }}</span>
@endforeach
Комментарии:
1. Спасибо за ваш подробный ответ. Я совсем новичок в laravel и попытался добавить связь к своей пользовательской модели следующим образом: общедоступная функция avatar() { return $this->belongsTo(‘name’, ‘avatar’); } но я получаю сообщение об ошибке, вызванной вызовом неопределенного метода IlluminateDatabaseEloquentBuilder:: all() что я делаю не так?
2. Рад помочь. Вам нужна
user()
связь сPost
классом. Вы можете взять пример из документации и заменитьPost
наUser
иComment
наPost
.3. Или вы можете сделать это по имени, как в вашем обновленном вопросе. 🙂 Но вам также необходимо определить обратную зависимость в
Post
модели.4. Спасибо! У меня уже есть отношение user() в моей модели Post, которое возвращает return $this->belongsTo(User::class); это правильно?
5. Для меня это выглядит правильно. Просто имейте в виду, что это выдаст ошибку, если нет пользователя с определенным именем (например, если пользователь изменил его). Чтобы предотвратить это, вы можете либо использовать
optional($post->user)->avatar
(ничего не напечатает, если пользователь не найден), либо определить связь с идентификатором.
Ответ №2:
Прежде всего, этот подход вызовет проблемы с производительностью и логикой .. лучше заменить идею получения пользователя по его имени идентификатором или убедиться, что имя уникально.. однако вот исправление
$posts = Post:all();
$user = []; // should be an array because you're looping over it.
foreach($posts as $post) {
$user[] = User::where('name', $post->creator)->get();
}
return view('welcome')->with('posts', $posts)->with('user', $user);
Я рекомендую установить связь между пользователями и post на основе внешнего ключа
смотрите: красноречивые отношения
Ответ №3:
Если вы знаете sql, вы можете отправить в базу данных что-то вроде:
SELECT avatar FROM users WHERE username="John_15";
Комментарии:
1. Я на неправильном пути или не выполняю User::where(‘name’, $post-> creator)-> get(); то же самое? помимо того, что он возвращает объект и не только аватар, но и то же самое, если я правильно помню?
2. Содержит ли возвращаемый объект поле аватара?