在 Eloquent 模型的构造函数中创建一个闭包作为 class 变量

Creation of a closure as class variable in constructor of Eloquent Model

我正在尝试在 Eloquent 模型的构造函数中创建一个 lambda 样式的闭包作为动态命名的 class 变量。

实例化对象时工作正常,创建模型时除外(也就是说,读取、更新和删除工作正常)。

我可以通过在实例化对象之前显式声明 class 变量来解决这个问题,但是,这只是一个 hack,我需要能够创建 class 变量(如闭包)动态。

以下代码有效,但如果我删除声明 $public foo;

public $foo;
public function __construct() {
    $foo = 'foo';
    $this->{$foo} = function ($args) { return 'foo';};
}

我收到以下错误:

exception 'ErrorException' with message 'Object of class Closure could not be converted to string' in /Users/Sites/.../vendor/laravel/framework/src/Illuminate/Support/helpers.php:900

就像我提到的,这只发生在 creating/inserting 一个对象时(对不起,如果这听起来很模糊,但熟悉 Laravel 的人应该知道我的意思)......在其他情况下实例化模型(read/update/delete) 工作得很好。任何关于可能导致问题的想法将不胜感激!

在您的模型上覆盖 setAttributegetAttribute

protected $closures = [];

public function setAttribute($key, $value)
{
    if ($value instanceof \Closure)
    {
        $this->setClosureProperty($key, $value);
    }

    parent::setAttribute($key, $value);
}

public function getAttribute($key)
{
    if (array_key_exists($key, $this->closures)
    {
        return $this->closures[$key];
    }

    return parent::getAttribute($key);
}

public function setClosureProperty($key, \Closure $value)
{
    $this->closures[$key] = $value;
}

这样,cloures 将不会保存在 attributes 数组中,因此不会被保存并转换为字符串。