$this类中的闭包数组中


$this in Array of Closures in Class

假设有一个对象的类,让我们以用户为例。User 类包含它自己的规则,用于在提交之前验证其数据。在保存到数据库之前,将检查规则并返回任何错误。否则,更新将运行。

class User extends DBTable // contains $Rules, $Data, $Updates, and other stuff
{
    public __construct($ID)
    {
        parent::__construct($ID);
        // I'll only list a couple rules here...
        $this->Rules['Email'] = array(
            'Empty' => 'ValidateEmpty', // pre-written functions, somewhere else
            'Invalid' => 'ValidateBadEmail', // they return TRUE on error
            'Duplicate' => function($val) { return existInDatabase('user_table', 'ID_USER', '`Email`="'. $val .'" AND `ID_USER`!='. $this->ID);}
        );
        $this->Rules['Password'] = array(
            'Empty' => 'ValidateEmpty',
            'Short' => function($val) { return strlen($val) < 8; }
        );
        this->Rules['PasswordConfirm'] = array(
            'Empty' => 'ValidateEmpty',
            'Wrong' => function($val) { return $val != $this->Updates['Password']; }
        );
    }
    public function Save(&$Errors = NULL)
    {
        $Data = array_merge($this->Data, $this->Updates);
        foreach($this->Rules as $Fields => $Checks)
        {
            foreach($Checks as $Error => $Check)
            {
                if($Check($Data[$Field])) // TRUE means the data was bad
                {
                    $Errors[$Field] = $Error; // Say what error it was for this field
                    break; // don't check any others
                }
            }
        }
        if(!empty($Errors))
            return FALSE;
        /* Run the save... */
        return TRUE; // the save was successful
    }
}

希望我在这里发布了足够的内容。因此,您会注意到,在"电子邮件的重复"错误中,我想检查他们的新电子邮件对于除他们自己以外的任何其他用户都不存在。此外,PasswordConfirm 会尝试使用 $this->Updates["密码"] 来确保它们两次输入相同的内容。

运行"保存"时,它会循环浏览规则并设置存在的任何错误。

这是我的问题:

Fatal error: Using $this when not in object context in /home/run/its/ze/germans/Class.User.php on line 19
我想

使用$this的所有关闭都会出现此错误。

似乎数组中的闭包和类中的数组的组合导致了问题。这个规则数组的东西在类之外工作得很好(通常涉及"使用"),AFAIK 闭包应该能够在类中使用$this。

那么,解决方案呢?变通办法?

谢谢。

问题出在Wrong验证器上。验证方法从这里调用:

if($Check($Data[$Field])) // TRUE means the data was bad

此调用不是在对象上下文中进行的(lambda 不是类方法)。因此,lambda 主体内部的$this会导致错误,因为它仅在对象上下文中存在。

对于 PHP>= 5.4.0,您可以通过捕获$this来解决问题:

function($val) { return $val != $this->Updates['Password']; }

在这种情况下,无论其可见性如何,您都可以访问Updates

对于 PHP>= 5.3.0,您需要复制对象引用并捕获它:

$self = $this;
function($val) use($self) { return $val != $self->Updates['Password']; }

但是,在这种情况下,您只能访问Updates public .