如何解决如何在 Laravel 中最好地优化这些查询?
{{ Auth::user() ? ($post->ratings()->where('user_id',Auth::user()->id)->exists() ? 'You rated ' . $post->userrating($post) : '') : '' }}
在我的 post
模型中可以访问的 2 个函数是:
public function ratings() {
return $this->hasMany(rating::class);
}
public function userrating(Post $post) {
return $this->ratings()->where([
['post_id','=',$post->id],['user_id',Auth::user()->id]
])->first('stars')->stars / 2;
}
这是我的 index
中的 postcontroller
:
public function index() {
$posts = Post::with('user')->withAvg('ratings','stars')->paginate(100);
return view('posts.index',[
'posts' => $posts,]);
}
然而,这需要大约 1 秒钟来加载每个页面,因为它必须执行该代码 100 次。
我在原始 MysqL 中进行了此查询,它加载结果的速度明显加快:
select `posts`.*,(select avg(`ratings`.`stars`) from `ratings` where `posts`.`id` = `ratings`.`post_id`) as `ratings_avg_stars`,(SELECT count(*) FROM ratings WHERE post_id = posts.id and user_id = 1) as rated from `posts` where `posts`.`deleted_at` is null
如果我把它放在我的 postcontroller
中,我认为页面加载速度会更快,我不知道如何将 MysqL 转换为 Eloquent,我尝试了一个查询转换器,但那些卡在子查询上.
解决方法
我相信您正在寻找 Constrain Your Eager Loading 并为 Post
创建一个访问修改器。
你可以看到我的小提琴 here。
这种方法的作用是,使用受约束的急切加载一次性加载所有必要的数据,并且访问修改器将在将 ratingAverage
附加到帖子时已经加载了这种关系。
通过这种方式,您可以避免任何不必要的数据库调用或方法调用来重新计算您已有的值。
架构:
Schema::create('users',function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('posts',function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('title');
$table->string('body');
$table->timestamps();
});
Schema::create('ratings',function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->unsignedInteger('post_id');
$table->integer('stars');
$table->timestamps();
});
型号:
use \Illuminate\Database\Eloquent\Relations\Pivot;
class User extends Model
{
protected $guarded = [];
}
class Rating extends Pivot
{
protected $table = 'ratings';
protected $guarded = [];
public static function rate(User $user,Post $post,int $stars)
{
return static::create([
'user_id' => $user->id,'post_id' => $post->id,'stars' => $stars
]);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
}
class Post extends Model
{
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
public function ratings()
{
return $this->hasMany(Rating::class);
}
public function getRatingAverageAttribute()
{
return $this->ratings->sum('stars') / $this->ratings->count();
}
}
控制器:
public function index() {
$posts = Post::query()->with(['ratings' => function ($query) {
$query->where('user_id',Auth::id());
}])->get();
return view('posts.index',[
'posts' => $posts,]);
}
最后在刀片中:
@if($post->ratings->count())
{{ 'You rated ' . $post->ratingAverage }}
@endif
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。