2014-10-10 4 views
2

У меня есть таблица счетов:Laravel - Установить значение по умолчанию для Relation модели

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

Как вы можете видеть, у меня есть мои настройки отношения один-к-одному здесь. (Конечно, у модели Address также есть «принадлежит»). Все это работает.

Дело в том, что адрес внешнего ключа является нулевым, поскольку учетные записи не требуют адресов. Поэтому, если я попытаюсь получить доступ к адресу Account->, когда он его не имеет, я получу «попытку доступа к свойствам не-объекта».

То, что я хотел бы сделать, - установить адрес Account-> на новый объект Address (все поля пустые), если в записи учетной записи нет одного набора.

То, что я был в состоянии сделать это либо создать второй метод в модели:

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

Или добавить его на лету:

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

Первое решение действительно близко , но я действительно хотел бы сохранить функциональность доступа к адресу как свойству вместо метода.

Итак, мой вопрос:
Как я могу иметь счет-> адрес возврата новый адрес(), если счет-> адрес пуст/нуль?

О, и я попытался перекрывая $ атрибуты, как так:

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

Но выдает ошибку.

ответ

3

Использование сбруя:

Edit: Так как это belongsTo не 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->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); 
} 

Вы могли бы сделать все это в одном аксессоре, но это так, как это «должен» выглядеть.

+0

Это делает то, что мне нужно, чтобы вернуть новый объект Address, но когда я создаю объект с $ account-> address() -> save (new Address ($ params)), он не работает , Он создает как учетную запись, так и адрес, но учетная запись.act_id получает значение address.add_id. – Troncoso

+0

Показать код и в чем проблема. Он не имеет никакого отношения к вызову метода '$ account-> address()', поэтому он не может вмешиваться в его метод 'save'. Btw Я изменил 'getNewAddress', чтобы избежать явного вызова' new Address'. –

+0

И, вы уверены, что отношения в порядке? 'hasOne' означает, что таблица' Address' содержит внешний ключ, относящийся к первичному ключу таблицы 'Account'. Ваши таблицы трудно читать, но кажется, что вы ошибаетесь. –