Laravel-设置关系模型的默认值


Laravel - Set Default Value for Relation Models

我有一个表帐户:

act_id,
act_name,
act_address

我有一个表地址:

add_id,
add_street1,
<other fields you'd expect in an address table>

accounts.act_address是addresses.add_id的外键。在Laravel中,我有我的Account模型:

use LaravelBook'Ardent'Ardent;
use Illuminate'Database'Eloquent'SoftDeletingTrait;
class Account extends Ardent
{
    use SoftDeletingTrait;
    protected $table = 'accounts';
    protected $primaryKey = 'act_id';
    public static $rules = array
    (
        'act_name' => 'required|unique:accounts'
    );
    protected $fillable = array
    (
        'act_name'
    );
    public function address()
    {
        return $this->hasOne('Address', 'add_id', 'act_address');
    }
}

正如你所看到的,我在这里建立了一对一的关系。(当然,Address模型也有一个"belongsTo")。这一切都有效。

问题是,地址外键可以为null,因为帐户不需要地址。因此,如果我试图访问Account->地址,而它没有,我会得到一个"尝试访问非对象属性"错误。

如果帐户记录没有一个集合,我想做的是将Account->address设置为一个新的address对象(所有字段都为空)。

我所能做的就是在模型中创建第二种方法:

public function getAddress()
{
    return empty($this->address) ? new Address() : $this->address;
}

或者,在飞行中添加它:

if (empty($account->address))
    $account->address = new Address();

第一个解决方案非常接近,但我真的希望保留访问地址的功能,将其作为属性而不是方法。

所以,我的问题是:
如果账户->地址为空/null,我如何让账户->地址返回新地址()

哦,我试着覆盖$属性,比如:

protected $attributes = array
(
    'address' => new Address()
);

但这就造成了一个错误。

使用访问器:

编辑:由于是belongsTo而不是hasOne关系,所以这有点棘手-您不能将模型与不存在的模型相关联,因为后者没有id

public function getAddressAttribute()
{
    if ( ! array_key_exists('address', $this->relations)) $this->load('address');
    $address = ($this->getRelation('address')) ?: $this->getNewAddress();
    return $address;
}
protected function getNewAddress()
{
    $address = $this->address()->getRelated();
    $this->setRelation('address', $address);
    return $address;
}

然而,现在你需要这个:

$account->address->save();
$account->address()->associate($account->address);

这不是很方便。您也可以将新实例化的地址保存在getNewAddress方法中,或者覆盖Account save方法,以自动进行关联。无论如何,对于这种关系,我不确定这样做是否有意义。对于hasOne来说,这会很好。


以下是hasOne关系的外观

public function getAddressAttribute()
{
    if ( ! array_key_exists('address', $this->relations)) $this->load('address');
    $address = ($this->getRelation('address')) ?: $this->getNewAddress();
    return $address;
}
protected function getNewAddress()
{
    $address = $this->address()->getRelated();
    $this->associateNewAddress($address);
    return $address;
}
protected function associateNewAddress($address)
{
    $foreignKey = $this->address()->getPlainForeignKey();
    $address->{$foreignKey} = $this->getKey();
    $this->setRelation('address', $address);
}

您可以在单个访问器中完成所有这些操作,但这是它"应该"的样子。