不确定我是不是正确使用急切加载,在存在的关系上获取 null

Posted

技术标签:

【中文标题】不确定我是不是正确使用急切加载,在存在的关系上获取 null【英文标题】:Not sure if I am using eager loading correctly, getting null on a relationship that exists不确定我是否正确使用急切加载,在存在的关系上获取 null 【发布时间】:2014-09-14 01:03:36 【问题描述】:

我在处理这个雄辩的问题时遇到了困难,希望有人能帮助我。

除了作者关系之外,查询工作正常,当我知道作者和关系都存在时,它返回 null。 (数据库中没有没有作者的书)

这里是有问题的代码:

//  BookController.php
$categories = array(1,2,3,4);
$audience_age = 15;

$books = Book::with(array('categories','author'))->whereHas('categories', function($q) use ($categories, $audience_age) 

    $q->whereIn('id', $categories)->where('audience_age', '<=', $audience_age)->where('status', '=', 'active');
)->take(50)->get(array('id','data'));


//  Book.php
public function author()

    return $this->belongsTo('Author');



//  Author.php
public function books()

    return $this->hasMany('Book');



//  authors migration
Schema::create('authors', function($table)

    $table->increments('id');
    $table->string('name');
    $table->string('status');
    $table->timestamps();
    $table->softDeletes();
);         


//  books migration
Schema::create('books', function($table)

    $table->increments('id');
    $table->integer('author_id')->unsigned();
    $table->foreign('author_id')->references('id')->on('authors');
    $table->string('name');
    $table->text('data');
    $table->string('status');
    $table->timestamps();
    $table->softDeletes();
);

我通过选择一本书 ID#40 验证了这种关系确实存在并且有效,并单独运行了这个查询:

print_r(Book::find(40)->author->toJSON()); 

这样加载时发现作者没有问题。

我已经使用我疯狂的 googl'in 技能几个小时试图弄清楚这一点,但到目前为止什么都没有......非常感谢任何帮助!

更新 --

查看DB::getQueryLog()后发现查询中作者的ID设置为0 ["query"]=> string(55) "select * from authors where authors.id in (?)" ["bindings"]=> array(1) [0]=> int( 0)

【问题讨论】:

更简单的方法是打印出后台生成的 SQL 语句。你能打印出 DB::getQueryLog() 看看 Eloquent 产生了什么吗? 调用它如何在关系中返回null 在Author查询中好像没有设置作者的ID,设置为0:select * from authors where authors.id in (?)" [ "绑定"]=> 数组(1) [0]=> int(0) 通常,如果我渴望加载多个关系,我只需传递一个模型字符串,即 with('categories', 'author'),你是否尝试过不使用数组? 是的,我确实尝试过。查询双向工作,但仍不返回作者 【参考方案1】:

你的代码唯一的问题是没有得到foreign key链接BookAuthor

$books = Book:: ... ->get(array('id','data'));

这样 Eloquent 不知道要查找什么,因此它设置了合理的默认值 0

只需将author_id 包含在select 中:

$books = Book:: ... ->get(array('id', 'data', 'author_id'));

它会按预期工作。

【讨论】:

6 个月后,我遇到了同样的问题,您的回答再次帮助了我。会再次 +1【参考方案2】:

我不知道如何使用 ORM,但我能够使用 DB::raw 使查询正常工作。

如果我知道如何让它在 ORM 中工作,我会回来更新我的答案。

现在,我是这样完成的:

$results = DB::select(DB::raw("SELECT b.id, b.data, au.id as author_id, GROUP_CONCAT(c.id) as categories
    FROM books b
    INNER JOIN book_category bc ON bc.book_id = b.id
    INNER JOIN categories c ON c.id = bc.category_id 
    INNER JOIN authors au ON au.id = b.author_id 
    WHERE c.id IN (1,2,3,4) 
    LIMIT 2"));

【讨论】:

以上是关于不确定我是不是正确使用急切加载,在存在的关系上获取 null的主要内容,如果未能解决你的问题,请参考以下文章

急切加载与加入获取相同吗?

急切加载关系

Laravel 动态关系 - 在急切加载时访问模型属性

Laravel 混合获取 Eloquent 急切加载嵌套多个模型

带有约束的 Laravel 嵌套急切加载

使用 Laravel 将两个模型合并到一个分页查询中,并带有急切加载的关系