使用关系名称“用户”时,BelongsTo 关系返回 null

Posted

技术标签:

【中文标题】使用关系名称“用户”时,BelongsTo 关系返回 null【英文标题】:BelongsTo relationship returns null when using relation name "user" 【发布时间】:2018-04-23 14:40:25 【问题描述】:

在 Laravel 5.5 中创建简单的一对一关系时,每当我使用方法/关系名称 user 时,$person->user 都会返回一个 null 值。如果我将名称更改为fooUserlogin,代码似乎可以正常工作。这是我遇到同样问题的第二个项目。谁能看到我做错了什么?

个人模型:

public function user() 
    return $this->belongsTo(User::class, 'user_id', 'id');

public function foo() 
    return $this->belongsTo(User::class, 'user_id', 'id');

public function getUser() 
    if ($this->user_id) 
        return User::find($this->user_id);
     else 
        return null;
    

在个人测试中:

$user = factory(User::class)->create();
$person = factory(Person::class)->create(['user_id' => $user->id]);

// This works                 
$this->assertTrue( $person->getUser()->is($user) );

// This works
$this->assertTrue( !is_null($person->foo) );
if ( $person->foo ) 
    $this->assertTrue( $person->foo->is($user) );


// This fails
$this->assertTrue( !is_null($person->user) );
if ( $person->user ) 
    $this->assertTrue( $person->user->is($user) );

根据要求,这里是与 Person 相关的所有代码, 整个 App\Models\Person.php

use App\Models\User;
use App\Models\Asset;
use App\Traits\HasGuid;
use App\Traits\HasNotes;
use App\Traits\HasModifiedBy;
use App\Traits\HasAttachments;
use App\Traits\HasRelationships;
use App\Transformers\PersonTransformer;
use App\Models\Abstracts\HasTypeModelAbstract;
use App\Models\Interfaces\HasTypeModelInterface;

class Person extends HasTypeModelAbstract implements HasTypeModelInterface 

    use HasModifiedBy,
        HasNotes,
        HasAttachments,
        HasRelationships;

    protected $fillable = [
        'person_type_id',
        'email',
        'fname',
        'lname',
        'user_id',
        'modified_by_user_id',
        'audited_at',
        'custom_attributes'
    ];
    protected $casts = [
        'custom_attributes' => 'json',
        'user_id' => 'integer',
        'modified_by_user_id' => 'integer',
        'person_type_id' => 'integer'
    ];
    protected $dates = [
        'audited_at'
    ];

    public static $transformer = PersonTransformer::class;

    public function user() 
        return $this->belongsTo(User::class, 'user_id', 'id');
    

    public function type() 
        return $this->belongsTo(PersonType::class, 'person_type_id');
    

    public function assets() 
        return $this->hasMany(Asset::class, 'person_id');
    

性状:

trait HasNotes 

    protected static function bootHasNotes() 
        static::deleting(function ($instance) 
            $instance->notes->each(function ($note) 
                $note->delete();
            );
        );
    

    public function notes() 
        return $this->morphMany(Note::class, 'notable');
    



trait HasModifiedBy 

    protected static function bootHasModifiedBy() 
        static::saving(function ($instance) 
            $instance->modified_by_user_id = Auth::id();
        );
    

    public function modifiedBy() 
        return $this->belongsTo(User::class, 'modified_by_user_id');
    



trait HasAttachments 

    protected static function bootHasAttachments() 

        static::deleting(function ($instance) 
            $instance->attachments->each(function ($attachment) 
                $attachment->delete();
            );
        );
    

    public function attachments() 
        return $this->morphMany(Attachment::class, 'attachable');
    



trait HasRelationships 

    protected static function bootHasRelationships()
    
        static::deleting(function ($instance) 
            Relation::forObject( $instance )->delete();
        );
    


    public function related()  ...[long polymorphic relationship here]... 

/App/Models/Abstracts/HasTypeModelAbstract

use Illuminate\Database\Eloquent\Model;

// This thing just appends some custom attributes dynamically in the JSON and array forms. And no, 'user' is not a custom attribute key.

abstract class HasTypeModelAbstract extends Model 

public function newFromBuilder($attributes = array(), $connection = NULL) 
    $instance = parent::newFromBuilder($attributes);
    $instance->appendCustomAttributes();
    return $instance;


protected function appendCustomAttributes() 
    $this->append( $this->getCustomAttributesFromType() );


public function getCustomAttributesFromType() 
    if ($this->type) 
        return $this->type->custom_attributes ?
                array_keys((array) $this->type->custom_attributes) : [];
     else 
        return [];
    


protected function setCustomAttributesFromType($attributes = array()) 
    if ($this->type) 
        $custom_attribute_keys = $this->getCustomAttributesFromType();
        $custom_attributes = (array) $this->custom_attributes ?: [];
        foreach ($custom_attribute_keys as $key) 
            $attributes[$key] = array_get($custom_attributes, $key);
        
    
    return $attributes;


protected function addMutatedAttributesToArray(array $attributes, array $mutatedAttributes) 

    $this->appendCustomAttributes($this, $attributes);
    $attributes = $this->setCustomAttributesFromType($attributes);
    return parent::addMutatedAttributesToArray($attributes, $mutatedAttributes);


protected function mutateAttribute($key, $value)

    $keys = $this->getCustomAttributesFromType();
    if ( in_array($key, $keys) ) 
        return $this->getCustomAttributeValue( $key, $value );
    
    return parent::mutateAttribute($key, $value);


protected function getCustomAttributeValue($key, $value) 
    $custom_attributes = (array) $this->custom_attributes ?: [];
    return array_get($custom_attributes, $key, $value);

【问题讨论】:

您的 Person 模型或方法 getUserAttribute 中是否有 user 列? 不。我还检查了所有遗传特征等。 您能否在整个文件中包含您使用的任何自定义特征? 完成。请注意,“用户”不是“HasTypeModelAbstract”类中的自定义属性键 【参考方案1】:

说实话 - 快速查看代码我没有发现任何问题,但这并不意味着一切都很好。

如果我是你,我会尝试将 Person 模型限制为:

class Person extends \Illuminate\Database\Eloquent\Model 

    protected $fillable = [
        'person_type_id',
        'email',
        'fname',
        'lname',
        'user_id',
        'modified_by_user_id',
        'audited_at',
        'custom_attributes'
    ];
    protected $casts = [
        'custom_attributes' => 'json',
        'user_id' => 'integer',
        'modified_by_user_id' => 'integer',
        'person_type_id' => 'integer'
    ];
    protected $dates = [
        'audited_at'
    ];

    public static $transformer = PersonTransformer::class;

    public function user() 
        return $this->belongsTo(User::class, 'user_id', 'id');
    

    public function type() 
        return $this->belongsTo(PersonType::class, 'person_type_id');
    

    public function assets() 
        return $this->hasMany(Asset::class, 'person_id');
    


现在我将验证一切是否正常。如果没问题,现在您可以进一步调查,添加一个特征并验证,添加第二个特征并验证,最后从同一个类扩展。

某处肯定有错误,但查看这段代码很难找到任何东西

【讨论】:

【参考方案2】:

user 是 eloquent 中的保留名称。

尝试用户而不是用户

public function User() 
return $this->belongsTo(User::class, 'user_id', 'id');

【讨论】:

我知道我可以更改方法名称。我在上面提到它适用于“用户”。您在哪里发现“用户”是 Eloquent 中的保留名称?它不是模型上的属性。我无法找到任何关于它的文档。我很想看一份清单。

以上是关于使用关系名称“用户”时,BelongsTo 关系返回 null的主要内容,如果未能解决你的问题,请参考以下文章

Laravel:更改其函数名称时,belongsTo 不起作用

Laravel:belongsTo()关系假设一对多关系而不是一对一

CakePHP hasOne belongsTo 关系,编辑/添加相同动作

如何渴望对同一张表加载多个belongsTo关系?

Laravel 5 leftJoin on belongsTo 关系

Laravel Eloquent 中的 Audit belongsTo 关系