【问题标题】:Laravel 5.5 eager loading throws error - Trying to get property of non-objectLaravel 5.5 急切加载抛出错误 - 试图获取非对象的属性
【发布时间】:2018-07-21 23:06:22
【问题描述】:

我看到很多人在使用 Eager 加载和 Laravel 时遇到问题,我也是其中之一。 我收到错误:尝试获取非对象的属性

解决方案:我需要在我的模型中包含public $incrementing = false;。请参阅底部的扩展答案

我查看了其他堆栈溢出答案,但没有一个解决了这个问题:这是 all 我的代码

我的 2 个迁移文件

create_authors_table

<?php

# database/migrations/1970_01_01_000001_create_authors_table

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAuthorsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('authors', function (Blueprint $table) {
            $table->string('author_id');
            $table->string('first_name');
            $table->string('last_name');
            $table->timestamps();

            $table->primary('author_id');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('authors');
    }
}

create_books_table

<?php

# database/migrations/1970_01_01_000002_create_books_table

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->string('book_id');
            $table->string('title');
            $table->string('author_id');
            $table->timestamps();

            $table->foreign('author_id')->references('author_id')->on('authors');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('books');
    }
}

接下来,这是我的路线

routes/web.php

<?php

# routes/web.php
Route::get('/books', 'BookController@index');

我有 2 个模型

模型/Author.php

<?php

# app/Models/Author.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{
    protected $primaryKey = 'author_id';

    public function book()
    {
        return $this->hasMany('App\Models\Book');
    }
}

Models/Book.php

<?php

# app/Models/Book.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $primaryKey = 'book_id';

    public function author()
    {
        return $this->belongsTo('App\Models\Author', 'author_id');
    }
}

这是我的 BookController

<?php

# app/Http/Controllers/BookController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Book;

class BookController extends Controller
{
    public function index()
    {
        $books = Book::with('author')->get();


        $results = [];
        foreach ($books as $book) {
            $result = new \stdClass();
            $result->title = $book->title;
            $result->author_first_name = $book->author->first_name;
            $result->author_last_name = $book->author->last_name;
            $results[] = $result;
        }

        dd($results);
    }
}

以下是一些用于填充数据库的测试数据:

insert into authors (author_id, first_name, last_name, created_at) 
values 
(
  'ceefb81f-48bb-ff07-1002-27fd8b7272b4', 'Charles', 'Coal', '2018-02-11 00:00:00'
);

INSERT INTO books (book_id, title, author_id, created_at)
VALUES 
(
  'a4e58f2a-36f5-f2fb-960c-c60e2689b337', 'Killing Coal', 'ceefb81f-48bb-ff07-1002-27fd8b7272b4',
  '2018-02-11 00:00:00'
),
(
  'a4e58f2a-36f5-f2fb-960c-c60e2689b338', 'Cleaning Coal', 'ceefb81f-48bb-ff07-1002-27fd8b7272b4',
  '2018-02-11 00:00:01'
),
(
  'a4e58f2a-36f5-f2fb-960c-c60e2689b339', 'Using Coal', 'ceefb81f-48bb-ff07-1002-27fd8b7272b4',
  '2018-02-11 00:00:02'
);

我已经打开了 MySQL 的登录,可以看到有 2 个查询正在运行

# turn on logging by running the following in MySQL
SET GLOBAL log_output = "FILE";
SET GLOBAL general_log_file = "/tmp/mysql.logfile.log";
SET GLOBAL general_log = 'ON';

这是 MySQL 日志文件的输出

2018-02-11T18:52:21.426064Z   262 Prepare   select * from `books`
2018-02-11T18:52:21.426348Z   262 Execute   select * from `books`
2018-02-11T18:52:21.426539Z   262 Close stmt    
2018-02-11T18:52:21.430560Z   262 Prepare   select * from `authors` where `authors`.`author_id` in (?)
2018-02-11T18:52:21.430689Z   262 Execute   select * from `authors` where `authors`.`author_id` in ('ceefb81f-48bb-ff07-1002-27fd8b7272b4')

但是,由于某种原因,关系没有关联

解决方案 因为,我使用的是 GUID 而不是自动递增的整数,所以我不得不告诉 Eloquent 主键不是自动递增的。 Laravel 在幕后试图将我的 GUID 转换为整数。

<?php
# app/Models/Book.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $primaryKey = 'book_id';

    # HAD TO ADD THIS
    public $incrementing = false;

    public function author()
    {
        return $this->belongsTo('App\Models\Author', 'author_id');
    }
}

应用程序/模型/作者

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{
    protected $primaryKey = 'author_id';

    # HAD TO ADD THIS
    public $incrementing  = false;

    public function book()
    {
        return $this->hasMany('App\Models\Book');
    }
}

【问题讨论】:

    标签: php mysql laravel-5 eloquent eager-loading


    【解决方案1】:

    对于Book 模型,您需要定义第三个参数book_id

    public function author()
    {
       return $this->belongsTo('App\Models\Author', 'book_id', 'author_id');
    } 
    

    如果您的父模型不使用 id 作为其主键,或者您希望 要将子模型加入不同的列,您可以传递第三个 指定您的父表的自定义的 belongsTo 方法的参数 关键

    【讨论】:

    • 感谢您的快速响应,但是,如果我添加第三个参数Column not found: 1054 Unknown column 'authors.book_id' in 'where clause' (SQL: select * from authors where authors.book_id in (ceefb81f-48bb-ff07-1002-27fd8b7272b4),则会出现以下错误
    • 啊! yrv16!你很聪明。你有 2 个键转置:函数 Book::author() 应该是:return $this-&gt;belongsTo('App\Models\Author', 'book_id', 'author_id');
    • 不!如果作者超过 1 位,则无法正常工作 :-( 针对 MySQL 运行的查询是 select * from authors where authors.author_id in (0, 39)
    • @KearneyTaaffe 如果你使用belongsTo,这意味着一本书只属于一个作者,如果你想要一本书可以属于许多作者,你需要使用多对多关系。在 Laravel 中,它的名称为 belongsToMany
    • 是的,很好。所以,我找到了解决方案:我需要将public $incrementing = false; 放入我的模型中。这已经解决了问题
    猜你喜欢
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 2018-03-03
    • 2018-07-04
    • 1970-01-01
    • 2016-06-13
    相关资源
    最近更新 更多