Как получить аватар пользователя, если у меня есть только имя пользователя?

#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. Содержит ли возвращаемый объект поле аватара?