微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Laravel 中最好地优化这些查询?

如何解决如何在 Laravel 中最好地优化这些查询?

我在 post.blade.PHP 中有一个简单的脚本

{{ 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,我尝试了一个查询转换器,但那些卡在子查询上.

如何将 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 举报,一经查实,本站将立刻删除。