【问题标题】:BelongsTo relationship returns null when using relation name "user"使用关系名称“用户”时,BelongsTo 关系返回 null
【发布时间】: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”类中的自定义属性键

标签: laravel laravel-5 eloquent phpunit laravel-5.5


【解决方案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 中的保留名称?它不是模型上的属性。我无法找到任何关于它的文档。我很想看一份清单。
    猜你喜欢
    • 2020-05-16
    • 2016-03-31
    • 2016-02-29
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2014-08-21
    相关资源
    最近更新 更多