无法访问 Twig 上的 Eloquent 个属性
Cannot access Eloquent attributes on Twig
我试图在 Slim 中使用 Twig 访问 Eloquent 属性,但出现错误。
我有一个Field对象和一个Type对象,关系如下
class Field extends \Illuminate\Database\Eloquent\Model {
protected $table = 'fields';
public function type()
{
return $this->belongsTo('models\Type');
}
做{{ f }}
时(作为一个字段),输出是这样的:
{"field_id":"1","field_name":"Your name","form_id":"2","type_id":"1","placeholder":"Please give us your name"}
当做{{ f.type }}
时,结果是:
Message: An exception has been thrown during the rendering of a template ("Object of class Illuminate\Database\Eloquent\Relations\BelongsTo could not be converted to string") in "pages/editform.html" at line 97.
如果我尝试 {{ f.type.name }}
,不会抛出异常,但也不会打印任何内容。
如果我在 PHP
$fields = $form->fields;
var_dump($fields[0]->type->name);
正确输出值。
有什么想法吗?
谢谢
我遇到了同样的问题,偶然发现了这个问题。自己解决后,我想我会尽力帮助你。
尝试对模型执行预加载:
Field::with('type')->get()
这应该允许您执行以下操作而不会出现其他问题。
{{ f.type }}
在此处查看更多信息:http://laravel.com/docs/4.2/eloquent#eager-loading
如果您不想进行预先加载,您可以在 Field
class 中覆盖神奇的 __isset
方法return true
type
关系 属性:
public function __isset($name)
{
if (in_array($name, [
'type'
])) {
return true;
} else {
return parent::__isset($name);
}
}
说明
问题在于 Eloquent 如何为关系实现 "dynamic property"(在你的例子中,f.type
)和 Twig 用于访问 "attributes" 个变量。
来自 Twig 文档:
For convenience's sake foo.bar
does the following things on the PHP layer:
- check if
foo
is an array and bar
a valid element;
- if not, and if
foo
is an object, check that bar
is a valid property;
- if not, and if
foo
is an object, check that bar
is a valid method (even if bar
is the constructor - use __construct()
instead);
- if not, and if
foo
is an object, check that getBar
is a valid method;
- if not, and if
foo
is an object, check that isBar
is a valid method;
- if not, return a null value.
foo['bar']
on the other hand only works with PHP arrays:
- check if
foo
is an array and bar
a valid element;
- if not, return a null value.
这里的关键是 "check that bar is a valid property" 的部分。这意味着在 PHP 级别上,Twig 正在 $f->type
上调用 isset
。 Eloquent implements the magic __isset
method in Model
,所以你可能认为这不是问题。
然而,看看它是如何实际实现模型关系的__isset
:
/**
* Determine if an attribute exists on the model.
*
* @param string $key
* @return bool
*/
public function __isset($key)
{
return (isset($this->attributes[$key]) || isset($this->relations[$key])) ||
($this->hasGetMutator($key) && ! is_null($this->getAttributeValue($key)));
}
它通过查看加载的关系数组 (isset($this->relations[$key])
) 来确定关系是否 "set"。问题是,如果 type
还没有加载,Eloquent 会说它不是 "set"。
因此当 Twig 查看 $f->type
时,它会认为 type
不是有效的 属性,然后继续下一条规则:
...if foo
is an object, check that bar
is a valid method
所以现在它将查找它找到的方法 type()
。唯一的问题? type()
(方法)return是一个 Relation
(具体来说,是一个 BelongsTo
),而不是一个 Type
对象。 BelongsTo
对象不是模型。
如果你想让 Twig 知道 属性 $f->type
确实存在,你有两个选择:
- 您可以预先加载相关的
Type
对象以及您的 Field
,正如@roger-collins 所建议的,或者;
- 您可以在
Field
中重载 __isset
魔术方法:
public function __isset($name)
{
if (in_array($name, [
'type'
])) {
return true;
} else {
return parent::__isset($name);
}
}
这将强制 Twig 识别 type
是 Field
的有效 属性,甚至在相关模型实际加载之前。
我试图在 Slim 中使用 Twig 访问 Eloquent 属性,但出现错误。
我有一个Field对象和一个Type对象,关系如下
class Field extends \Illuminate\Database\Eloquent\Model {
protected $table = 'fields';
public function type()
{
return $this->belongsTo('models\Type');
}
做{{ f }}
时(作为一个字段),输出是这样的:
{"field_id":"1","field_name":"Your name","form_id":"2","type_id":"1","placeholder":"Please give us your name"}
当做{{ f.type }}
时,结果是:
Message: An exception has been thrown during the rendering of a template ("Object of class Illuminate\Database\Eloquent\Relations\BelongsTo could not be converted to string") in "pages/editform.html" at line 97.
如果我尝试 {{ f.type.name }}
,不会抛出异常,但也不会打印任何内容。
如果我在 PHP
$fields = $form->fields;
var_dump($fields[0]->type->name);
正确输出值。
有什么想法吗? 谢谢
我遇到了同样的问题,偶然发现了这个问题。自己解决后,我想我会尽力帮助你。
尝试对模型执行预加载:
Field::with('type')->get()
这应该允许您执行以下操作而不会出现其他问题。
{{ f.type }}
在此处查看更多信息:http://laravel.com/docs/4.2/eloquent#eager-loading
如果您不想进行预先加载,您可以在 Field
class 中覆盖神奇的 __isset
方法return true
type
关系 属性:
public function __isset($name)
{
if (in_array($name, [
'type'
])) {
return true;
} else {
return parent::__isset($name);
}
}
说明
问题在于 Eloquent 如何为关系实现 "dynamic property"(在你的例子中,f.type
)和 Twig 用于访问 "attributes" 个变量。
来自 Twig 文档:
For convenience's sake
foo.bar
does the following things on the PHP layer:
- check if
foo
is an array andbar
a valid element;- if not, and if
foo
is an object, check thatbar
is a valid property;- if not, and if
foo
is an object, check thatbar
is a valid method (even ifbar
is the constructor - use__construct()
instead);- if not, and if
foo
is an object, check thatgetBar
is a valid method;- if not, and if
foo
is an object, check thatisBar
is a valid method;- if not, return a null value.
foo['bar']
on the other hand only works with PHP arrays:
- check if
foo
is an array andbar
a valid element;- if not, return a null value.
这里的关键是 "check that bar is a valid property" 的部分。这意味着在 PHP 级别上,Twig 正在 $f->type
上调用 isset
。 Eloquent implements the magic __isset
method in Model
,所以你可能认为这不是问题。
然而,看看它是如何实际实现模型关系的__isset
:
/**
* Determine if an attribute exists on the model.
*
* @param string $key
* @return bool
*/
public function __isset($key)
{
return (isset($this->attributes[$key]) || isset($this->relations[$key])) ||
($this->hasGetMutator($key) && ! is_null($this->getAttributeValue($key)));
}
它通过查看加载的关系数组 (isset($this->relations[$key])
) 来确定关系是否 "set"。问题是,如果 type
还没有加载,Eloquent 会说它不是 "set"。
因此当 Twig 查看 $f->type
时,它会认为 type
不是有效的 属性,然后继续下一条规则:
...if
foo
is an object, check thatbar
is a valid method
所以现在它将查找它找到的方法 type()
。唯一的问题? type()
(方法)return是一个 Relation
(具体来说,是一个 BelongsTo
),而不是一个 Type
对象。 BelongsTo
对象不是模型。
如果你想让 Twig 知道 属性 $f->type
确实存在,你有两个选择:
- 您可以预先加载相关的
Type
对象以及您的Field
,正如@roger-collins 所建议的,或者; - 您可以在
Field
中重载__isset
魔术方法:
public function __isset($name)
{
if (in_array($name, [
'type'
])) {
return true;
} else {
return parent::__isset($name);
}
}
这将强制 Twig 识别 type
是 Field
的有效 属性,甚至在相关模型实际加载之前。