2014-09-04 38 views
2

的关系我有2个表:Laravel:每当我回模型总是返回它

User  | Doctor 
---------- | ---------- 
id   | id 
email  | user_id 
name  | signature 
last_name | photo 
password | description 
date_birth | 

Doctor关系到一个User,但每User可能不会涉及到Doctor。我这样做是因为我不想使用单表继承,并最终得到一堆NULL字段。

有没有一种方法可以做到,像这样?

// Instead of 
$doctor = Doctor::with('User')->find(1); 
$doctor->user->name; 
// This 
$doctor = Doctor::find(1); 
$doctor->name; 

P.S:不知道放什么题目,我应该把代替它更相关的问题吗?

+0

如果医生没有用户,你想在结果中看到那个医生吗? – user3158900 2014-09-04 20:16:28

+0

医生总是与用户有关(至少在这种情况下)。请阅读“Matthew Rath”所做回答的评论。 – Mathius17 2014-09-04 20:22:54

回答

5

我结束了使用Accessors$appends,它按预期工作。它甚至出现在文档Appends + Accessors中(最后)。感谢Cyrode,他向我展示了访问者(不知道他们的存在)。

我本可以不使用$appends数组,但如果您使用JSON返回模型,则需要它。

由于亚雷克Tkaczyk deczo建议,当你用这种方法去,你应该使用with财产,否则无论何时加载多个Doctor模型,并调用相关的任何User,你结束了一个DB查询(每个Doctor实例) - > N + 1问题

医生下课这样看:

<?php 

class Doctor extends Eloquent { 

    protected $table = 'doctors'; 

    protected $with = ['user']; 

    protected $appends = ['first_name','last_name','email','date_of_birth']; 

    protected $hidden = ['signature','user']; 

    public function user(){ 

     return $this->belongsTo('User'); 

    } 

    public function getFirstNameAttribute() { 

     return $this->user->first_name; 

    } 

    public function getLastNameAttribute() { 

     return $this->user->last_name; 

    } 

    public function getEmailAttribute() { 

     return $this->user->email; 

    } 

} 

我不得不把user$hidden阵列内部或它会显示每当我退休Doctor(除了我只需要User的一些东西,不是所有的东西)

+1

当你使用这种方法时,你应该使用'with'属性,否则当你加载多个'Doctor'模型并且调用任何'User'相关的时候,你最终会得到一个db查询(每个Doctor实例) - > n + 1问题 – 2014-09-05 09:43:56

+0

谢谢Jarek,很好的建议。将相应地更新答案。 – Mathius17 2014-09-05 14:10:15

7

您可以使用模型上的$with属性指定默认加载关系。

class Doctor extends Eloquent { 

    protected $with = ['user']; 

    // ... 
} 

(属性可能需要是公共的,我忘记了。Laravel会骂你,如果它。)

您仍然需要使用$doctor->user->name,但这种关系将没有你自动加载需要明确地调用它。如果确实想要使用$doctor->name语法,那么可以为那些列名创建Accessors,然后这些列名将获取并传递适当的用户关系列。

+0

我结束了使用访问器和$追加,它按预期工作。它甚至出现在文档[Appends + Accessors(最后)](http://laravel.com/docs/eloquent#converting-to-arrays-or-json)中。 – Mathius17 2014-09-04 21:49:30

0

是的,有一种方法。这是好的设计吗?也许,也许不是。很难从你的简短描述中说出。

// Doctor model 
public function __get($key) 
{ 
    // check deafult behaviour 
    if (is_null($value = parent::__get($key))) return $value; 

    // if null, let's try related user 
    return $this->user->__get($key); 
} 

public function __set($key, $value) 
{ 
    $user = $this->user; 

    // first try user 
    if (array_key_exists($key, $user->getAttributes()) || $user->hasSetMutator($key)) 
    { 
     return $user->__set($key, $value); 
    } 

    // then default 
    parent::__set($key, $value); 
} 

这样,你可以这样做:

$doctor->name; // returns $doctor->user->name; unless you have accessors for name 

$doctor->name = 'Some Name'; 
// then 
$doctor->user->name; // 'Some Name'; 

// so finally push instead of save, in order to save related user too 
$doctor->push(); 

记住,这是很简单的例子,为了简洁。有一个机会,Doctor模型的现有属性是null,因此不应该调用$this->user->__get(),例如。所以为了使它完全可靠,你需要检查hasGetMutator(),relations等等。有关详细信息,请参阅Model s __get__set

相关问题