Добавьте разбивку на страницы в отношения и получите отношения отношений — Laravel

#php #laravel

Вопрос:

Я создаю веб-сайт форума, используя Laravel и Vue.

У меня есть три таблицы: форумы, сообщения и пользователи. На одном форуме может быть несколько сообщений, в каждом сообщении есть пользователь, создавший это сообщение.

Когда пользователь нажимает на один форум, я хочу отобразить последние 10 сообщений на этом форуме методом разбиения на страницы.

Forum.php

 <?php
namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Forum extends Model {
    use HasFactory;

    protected $table = 'forums';
    protected $guarded = [];

     /**
      * Get the forum posts
      * @return IlluminateDatabaseEloquentRelationsHasMany
      */
    public function posts() {
        return $this->hasMany(Post::class)->orderBy('created_at', 'DESC');
    }
}
 

Post.php

 <?php
namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Post extends Model {
    use HasFactory;

    protected $table = 'posts';
    protected $guarded = [];

    /**
     * Get the post's user
     * @return IlluminateDatabaseEloquentRelationsBelongsTo
     */
    public function user() {
        return $this->belongsTo(User::class);
    }
}
 

User.php

 <?php
namespace AppModels;

use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;

class User extends Authenticatable {
    use HasFactory, Notifiable;

    /**
     * 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',
    ];

    /**
     * Get the user posts
     * @return IlluminateDatabaseEloquentRelationsHasMany
     */
    public function posts() {
        return $this->hasMany(Post::class);
    }
}
 

Здесь я получаю сообщения на форуме с пользователями.

ForumService.php

 <?php
namespace AppServices;

use AppModelsForum;

class ForumService {
    public static function getForumPosts($forumId) {
        $forum = Forum::with('posts.user')->find($forumId);
        dd($forum);
    }
}
 

Однако я хочу получить только 10 сообщений и получить пользователя каждого сообщения, так как же мне это сделать в отношениях? Сообщения разбиты на страницы, но как мне теперь получить пользователя для публикации? Поскольку синтаксис точки применим к пользователю, поэтому я разбиваю на страницы пользователя, а не сообщения.

ForumService.php

 <?php
namespace AppServices;

use AppModelsForum;

class ForumService {
    public static function getForumPosts($forumId) {
        $forum = Forum::with(
            [
                'posts' => function ($query) { // How do I get the post user?
                    return $query->paginate(10);
                }
            ]
        )->find($forumId);
        dd($forum);
    }
}
 

Ответ №1:

Просто добавьте with метод в область запроса созданной вами функции.

  $forum = Forum::with(
            [
                'posts' => function ($query) {
                    // returns posts with user  
                    return $query->with('user')->paginate(10);
                }
            ]
        )->find($forumId);
 

Теперь вы можете получить доступ к первому пользователю, $forum->posts[0]->user который не будет запрашивать базу данных, а будет предварительно выбирать пользователей и заполнять ее в коллекции paginator.

Ответ №2:

Поскольку у вас уже есть идентификатор форума, вы можете извлекать только те сообщения, которые принадлежат этому Forum форуму, и разбивать их на страницы следующим образом

  public static function getForumPosts($forumId) {
    return Forum::find($forumId)->posts()->paginate(10);
}
 

Если вы хотите создать нетерпеливый Post создатель нагрузки, вы можете выполнить это следующим образом

 public static function getForumPosts($forumId) {
    return Forum::find($forumId)->posts()->with(['user'])->paginate(10);
}