【问题标题】:Loading the Model relationship from RAM in Eloquent在 Eloquent 中从 RAM 中加载模型关系
【发布时间】:2015-12-27 00:59:43
【问题描述】:

当我们加载 Laravel Eloquent 模型及其关系时,如下所示:

$user = User::with('Interest')->find(1);

查询MySQL如下:

100 Prepare   select * from `users` where `users`.`id` = ? limit 1
100 Execute   select * from `users` where `users`.`id` = '1' limit 1
100 Close stmt        
100 Prepare   select `interest_id`, `user_interests`.`user_id` as `pivot_user_id`, `user_interests`.`interest_id` as `pivot_interest_id` from `interests` inner join `user_interests` on `interests`.`id` = `user_interests`.`interest_id` where `user_interests`.`user_id` in (?)
100 Execute   select `interest_id`, `user_interests`.`user_id` as `pivot_user_id`, `user_interests`.`interest_id` as `pivot_interest_id` from `interests` inner join `user_interests` on `interests`.`id` = `user_interests`.`interest_id` where `user_interests`.`user_id` in ('1')
100 Close stmt 
100 Quit

在下一行,我想访问已加载的 Interest 模型,在我看来,它已经被 ::with 语句预先加载了。但是,当我尝试像这样访问interest_id 时:

$user->interest->interest_id;

我看到另一个数据库查找出现在 MySQL 查询日志中访问相同的已预加载关系:

100 Prepare   select `interest_id`, `user_interests`.`user_id` as `pivot_user_id`, `user_interests`.`interest_id` as `pivot_interest_id` from `interests` inner join `user_interests` on `interests`.`id` = `user_interests`.`interest_id` where `user_interests`.`user_id` = ?
100 Execute   select `interest_id`, `user_interests`.`user_id` as `pivot_user_id`, `user_interests`.`interest_id` as `pivot_interest_id` from `interests` inner join `user_interests` on `interests`.`id` = `user_interests`.`interest_id` where `user_interests`.`user_id` = '1'
100 Close stmt        
100 Quit

我希望 Laravel 为我提供已经加载的关系,但它却再次查询 MySQL。我看到当我使用getRelation('Interest') 时,它确实返回了已经在User::with('Interest') 上加载的关系并且不再查询MySQL,如下所示:

$user->getRelation("Interest")->interest_id;

我想知道这是否是要走的路,如果我对使用 ::with 进行急切加载的期望完全错误?或者也许还有其他最佳实践来访问预加载的关系而不是再次查询 MySQL。在我看来,多次查询数据库以获取相同的信息更昂贵。

用户模型

<?php namespace App\Models;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use App\Models;

class User extends Model implements AuthenticatableContract, CanResetPasswordContract {

    use Authenticatable, CanResetPassword;

    protected $table = 'users';

    protected $fillable = ['name', 'email', 'password'];

    protected $hidden = ['password', 'remember_token', 'created_at', 'updated_at'];

    public function Interest()
    {
        return $this->belongsToMany('App\Models\Interest', 'user_interests', 'user_id', 'interest_id')->select(array('interest_id'));
    }

}

兴趣模型

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Interest extends Model
{
    protected $table = 'interests';

    protected $fillable = ['description', 'parent_id'];

    protected $hidden = ['created_at', 'updated_at'];

}    

【问题讨论】:

  • 这种行为不正常。请在您定义关系的位置提供您的模型代码。为什么你渴望加载时使用“兴趣”,而访问时使用“兴趣”?
  • @JaviStolz,您的评论让我注意到了“资本”问题。我已将 User 模型中的函数声明更改为小写复数,如下所示:public function interests() { ... } 以及它被调用的地方,现在一切都按预期工作。奇怪的是它也适用于资本问题并且没有抛出异常。
  • 尝试添加反向关系。也尝试删除-&gt;select(array('interest_id'))

标签: laravel eloquent


【解决方案1】:

你的代码是$user-&gt;interest-&gt;interest_id;,你的函数是public function Interest()

PHP 函数区分大小写。

【讨论】:

    猜你喜欢
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2016-02-26
    • 2019-09-20
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多