无法访问 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 识别 typeField 的有效 属性,甚至在相关模型实际加载之前。