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

时间:2014-10-10 15:21:40

标签: php laravel-4 eloquent

我有一个表帐户:

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,我有我的账户模型:

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');
    }
}

正如您所看到的,我在这里建立了一对一的关系。 (当然,地址模型也有'且属于'#)。一切正常。

问题是,地址外键可以为空,因为帐户不需要地址。因此,如果我尝试访问Account-&gt;地址时,如果没有,我会尝试访问非对象的属性&#39;错误。

我想要做的是将帐户 - >地址设置为新的地址对象(所有字段为空),如果帐户记录没有一套。

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

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

或者,即时添加:

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

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

所以,我的问题是:
如果Account-&gt;地址为空/ null,我如何才能使用Account-&gt;地址返回新的地址()?

哦,我尝试覆盖这样的$属性:

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

但这会引发错误。

1 个答案:

答案 0 :(得分:3)

使用访问者:

编辑:由于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方法中保存新实例化的地址,或覆盖帐户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);
}

你可以在单一存取器中完成所有这些,但这是它应该&#39;的方式。看起来像。