doupian6118 2019-04-01 10:44
浏览 112
已采纳

Laravel渴望加载错误“试图获取非对象的属性... / BelongsToMany.php”

Laravel 5.8

I'm having an issue getting eager loading to work on some models but not on others.

Using artisan tinker I can run;

$p = App\Programme::find(34)->reviews

and get the correct result. If I change this to;

$p = App\Programme::with('reviews')->find(34)

So that the reviews are eager loaded, it fails with the error

PHP Notice:  Trying to get property of non-object in .../vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php on line 301

output from artisan with query log, bindings and execute time

$p = App\Programme::with('destinations', 'reviews')->find(34)

"select * from `programmes` where `programmes`.`id` = ? and `programmes`.`deleted_at` is null limit 1"
array:1 [
  0 => 34
]
1.08


"select `destinations`.*, `programme_destination`.`programme_id` as `pivot_programme_id`, `programme_destination`.`destination_id` as `pivot_destination_id`, `programme_destination`.`created_at` as `pivot_created_at`, `programme_destination`.`updated_at` as `pivot_updated_at` from `destinations` inner join `programme_destination` on `destinations`.`id` = `programme_destination`.`destination_id` where `programme_destination`.`programme_id` in (34)"
[]
0.88


"select `reviews`.*, `programme_reviews`.`programme_id` as `pivot_programme_id`, `programme_reviews`.`review_id` as `pivot_review_id`, `programme_reviews`.`created_at` as `pivot_created_at`, `programme_reviews`.`updated_at` as `pivot_updated_at` from `reviews` inner join `programme_reviews` on `reviews`.`id` = `programme_reviews`.`review_id` where `programme_reviews`.`programme_id` in (34)"
[]
0.85

The final query if run manually works just fine.

I can run the exact same two commands using either the User or Destination models and get a successful response. So there must be something different about the relationship of $programme->reviews when compared to $programme->user or $programme->destinations

Here are my models (trimmed to the relevant functions);

App\BaseModel

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Contracts\Auditable;
use Log;
use DB;

class BaseModel extends Model
{
    protected $guarded = ['alias', 'created_at', 'updated_at', 'deleted_at', 'slug'];

    public $custom_attributes = [];
    public $index_attributes = ['alias', 'user'];


    public function alias()
    {
        return $this->morphOne('App\Alias', 'aliased');
    }

    public function user()
    {
        return $this->belongsTo('App\User');
    }

}

App\Programme

<?php

namespace App;

use App\BaseModel;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Contracts\Auditable;
use Log;

class Programme extends BaseModel implements Auditable
{
    use SoftDeletes;
    use \OwenIt\Auditing\Auditable;


    protected $table = 'programmes';

    protected $dates = ['deleted_at'];


    function __construct(array $attributes = array())
    {
        parent::__construct($attributes);
    }

    public function destinations()
    {
        return $this->belongsToMany('App\Destination', 'programme_destination')
            ->withTrashed()
            ->withTimestamps();
    }

    public function reviews()
    {
        return $this->belongsToMany('App\Review', 'programme_reviews')
            ->withTrashed()
            ->withTimestamps();
    }
}

App\Review

<?php

namespace App;

use App\BaseModel;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Contracts\Auditable;
use Log;

class Review extends BaseModel implements Auditable
{
    use SoftDeletes;
    use \OwenIt\Auditing\Auditable;

    protected $fillable = ['title', 'name', 'first_name', 'last_name', 'review_type', 'email_address', 'created_at'];


    function __construct(array $attributes = array())
    {
        parent::__construct($attributes);
    }

    public function programmes()
    {
        return $this->belongsToMany('App\Programme', 'programme_reviews')
            ->withTrashed()
            ->withTimestamps();
    }
}

I can run $p = App\Programme::with('destinations', 'alias')->find(34) successfully. Here's the model for destinations

App\Destination

<?php

namespace App;

use App\BaseModel;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Contracts\Auditable;


class Destination extends BaseModel implements Auditable
{
    use SoftDeletes;
    use \OwenIt\Auditing\Auditable;


    protected $table = 'destinations';

    protected $dates = ['deleted_at'];


    function __construct(array $attributes = array())
    {
        parent::__construct($attributes);
    }

    public function programmes()
    {
        return $this->belongsToMany('App\Programme', 'programme_destination')
            ->withTrashed()
            ->withTimestamps();
    }
}

It seems the relationship works based on the first artisan command, so why does this not work when eager loading?

For reference here are the database create codes;

programmes

CREATE TABLE `programmes` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(191) NOT NULL COLLATE 'utf8_unicode_ci',
    `destination_id` INT(10) UNSIGNED NULL DEFAULT NULL,
    `user_id` INT(10) UNSIGNED NOT NULL DEFAULT '1',
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `programmes_user_id_foreign` (`user_id`),
    INDEX `programmes_destination_id_foreign` (`destination_id`),
    CONSTRAINT `programmes_destination_id_foreign` FOREIGN KEY (`destination_id`) REFERENCES `destinations` (`id`),
    CONSTRAINT `programmes_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

reviews

CREATE TABLE `reviews` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `title` VARCHAR(191) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `name` VARCHAR(191) NOT NULL COLLATE 'utf8_unicode_ci',
    `first_name` VARCHAR(191) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `last_name` VARCHAR(191) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `email_address` VARCHAR(191) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

programme_reviews - many to many

CREATE TABLE `programme_reviews` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `programme_id` INT(10) UNSIGNED NOT NULL,
    `review_id` INT(10) UNSIGNED NOT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `programme_reviews_review_id_foreign` (`review_id`),
    INDEX `programme_id` (`programme_id`),
    CONSTRAINT `programme_reviews_programme_id_foreign` FOREIGN KEY (`programme_id`) REFERENCES `programmes` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT `programme_reviews_review_id_foreign` FOREIGN KEY (`review_id`) REFERENCES `reviews` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

destinations

CREATE TABLE `destinations` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(191) NOT NULL COLLATE 'utf8_unicode_ci',
    `user_id` INT(10) UNSIGNED NOT NULL DEFAULT '1',
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `destinations_parent_id_index` (`parent_id`),
    INDEX `destinations_user_id_foreign` (`user_id`),
    CONSTRAINT `destinations_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

programme_destinations one to many

CREATE TABLE `programme_destination` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `programme_id` INT(10) UNSIGNED NOT NULL,
    `destination_id` INT(10) UNSIGNED NOT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `programme_destination_programme_id_foreign` (`programme_id`),
    INDEX `programme_destination_destination_id_foreign` (`destination_id`),
    CONSTRAINT `programme_destination_destination_id_foreign` FOREIGN KEY (`destination_id`) REFERENCES `destinations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT `programme_destination_programme_id_foreign` FOREIGN KEY (`programme_id`) REFERENCES `programmes` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

The only real difference between $programme->destinations and $programme->reviews is that reviews is a many to many relationship.

  • 写回答

1条回答 默认 最新

  • dongxieyi9115 2019-04-02 08:30
    关注

    So I've found the answer to this niggling query thanks to outside help.

    My question as is would not have been answerable, as the problem actually existed with a $pivot class variable I had assigned on the Programme model (and removed for the post to attempt to shorten it).

    This variable clashed with Laravel's internal workings, which seems quite obvious now I know about it.

    Changing $pivot to anything else allowed the relationship to be eager loaded correctly.

    It's unlikely someone will have the same issue as me, but who knows, it may help someone avoid the error I encountered.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败