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.

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

报告相同问题?

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀