Laravel:每当我返回一个模型时,总是返回与它的关系
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25674143/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel: Whenever I return a model always return a relationship with it
提问by Mathius17
I have 2 tables:
我有2张桌子:
User | Doctor
---------- | ----------
id | id
email | user_id
name | signature
last_name | photo
password | description
date_birth |
Every Doctor
is related to a User
, but every User
may not be related to a Doctor
. I did it this way because I didn't want to use Single Table Inheritance and end up with a bunch of NULL
fields.
EveryDoctor
与 a 相关User
,但 everyUser
可能不与 a 相关Doctor
。我这样做是因为我不想使用单表继承并最终得到一堆NULL
字段。
Is there a way to make, something like this?
有没有办法制作,像这样?
// Instead of
$doctor = Doctor::with('User')->find(1);
$doctor->user->name;
// This
$doctor = Doctor::find(1);
$doctor->name;
P.S: Didn't know what to put in the title, what should I put instead so it is more relevant to the question?
PS:不知道在标题中放什么,我应该放什么,以便与问题更相关?
采纳答案by Mathius17
I ended up using Accessors
and $appends
and it worked as intended. It even appears in the docs Appends + Accessors (at the end). Thanks to Cyrode, whom showed me the Accessors (didn't know they exised).
我最终使用了Accessors
并且$appends
它按预期工作。它甚至出现在文档 Appends + Accessors(最后)中。感谢 Cyrode,他向我展示了 Accessors(不知道它们存在)。
I could've not use the $appends
array, but you need it if you're returning the model in JSON.
我不能使用该$appends
数组,但如果您以 JSON 形式返回模型,则需要它。
As Jarek Tkaczyk deczosuggested, you should use with
property when you go with this approach, otherwise whenever you load multiple Doctor
models and call anything User
related, you end up with a db query (per each Doctor
instance) -> n+1 issue
正如 Jarek Tkaczyk deczo 所建议的,with
当你采用这种方法时应该使用属性,否则每当你加载多个Doctor
模型并调用任何User
相关的东西时,你最终会得到一个 db 查询(每个Doctor
实例)-> n+1 问题
Doctor class ended up looking like this:
博士班最终看起来像这样:
<?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;
}
}
I had to put user
inside the $hidden
array or it would show up whenever I retireved Doctor
(Besides I only needed some things of User
, not everything)
我只好把user
里面$hidden
阵列或者它会显示,每当我retireved Doctor
(除了我只需要对一些事情的User
,不是一切)
回答by Aken Roberts
You can specify default eager loaded relationships using the $with
property on the model.
您可以使用$with
模型上的属性指定默认的预加载关系。
class Doctor extends Eloquent {
protected $with = ['user'];
// ...
}
(The property might need to be public, I forget. Laravel will yell at you if it does.)
(该属性可能需要公开,我忘记了。如果公开,Laravel 会冲你大喊大叫。)
You will still need to use $doctor->user->name
, but the relationship will be automatically loaded without you needing to explicitly call it. If you reallywant to use the $doctor->name
syntax, you could create Accessorsfor those column names, which would then fetch and pass the appropriate User relationship columns.
您仍然需要使用$doctor->user->name
,但关系将自动加载而无需您显式调用它。如果你真的想使用的$doctor->name
语法,你可以创建访问者的那些列名,那么这将获取,并通过适当的用户关系的列。
回答by Jarek Tkaczyk
Yes, there is a way. Is it good design? Maybe, maybe not. Hard to say from your short description.
是的,有办法。这是好的设计吗?也许,也许不是。从你的简短描述很难说。
// 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);
}
This way you can do this:
这样你就可以做到这一点:
$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();
Mind that this is pretty simple example, for brevity. There is a chance, that existing attribute of Doctor
model is null
, so $this->user->__get()
should not be called, for example. So to make it fully reliable, you need to check hasGetMutator()
, relations
and so on. Check Model
s __get
and __set
for details.
请注意,为简洁起见,这是一个非常简单的示例。例如,Doctor
模型的现有属性有可能是null
,因此$this->user->__get()
不应调用。因此,要使其完全可靠,您需要检查hasGetMutator()
,relations
等等。检查Model
s__get
和__set
详细信息。