1

我还没有找到我在这里发布的问题的完全相同的副本,所以这里是:

class CBaseEntity
{
    public function __construct()
    {

    }

    public function __get($property)
    {
        $property = "m_".$property;
        echo $property;
        if(property_exists($this, $property))
        {           
            $result = $this->$property;
            return $result;
        }
        else 
        {
            throw new Exception("Property not found $property");
        }
    }
}

class CCategoryEntity extends CBaseEntity
{
    private $m_id;
    private $m_name;
    private $m_description;

    public function __construct()
    {

    }

    public static function CreateFromParams($id,$name, $description)
    {
        $instance = new CCategoryEntity();
        $instance->m_id=$id;
        $instance->m_name=$name;
        $instance->m_description=$description;
        return $instance;
    }

    public static function CreateFromArray(array $catData)
    {
        $instance = new CCategoryEntity();
        $instance->m_id = $catData["id"];
        $instance->m_name = $catData["name"];
        $instance->m_description = $catData["description"];
        return $instance;
    }
}

    $categoryEntity = CCategoryEntity::CreateFromParams(3, "EntityA", "Entity");
    echo $categoryEntity->name;

Fatal error: Uncaught exception 'Exception' with message 'Property not found m_m_name'
 Exception: Property not found m_m_name in ***\models\BaseModel.php on line 33

似乎该name属性是通过get魔术方法解析的,但是这个 getter 主体中的返回将再次发出对自身的调用,而不是不知何故智能地停止,因为字符串$property与所寻找的属性的名称一致。我可以进行字符串比较并查看属性是否以 开头m_,但我不希望在这种情况下已经发出第二个调用。

还有其他涉及类似代码的 SO 问题不会产生不必要的递归。php有什么变化还是默认行为?可以做些什么来以优雅的方式达到此设计的目标?

4

2 回答 2

2

我不知道你的意思,但没有第二个电话。当您访问类之外的属性时,__get()只会调用一次。$this->$property方法内部__get()不会触发另一个调用。

来自 PHP 文档:

当与尚未声明或在当前范围内不可见的属性或方法交互时,将调用重载方法。

这意味着__get()只有在没有可用于该调用的属性时才调用该方法。

于 2012-12-29T12:06:15.330 回答
2

出现递归是因为您只检查属性是否存在,而不是是否可以从当前范围访问。由于它被声明为私有,因此无法从父类或子类访问它,只能在声明它的类中访问它,这就是为什么__get第二次调用它(第一次是不存在的属性,现在是不可访问的属性)。尝试get_object_vars以获取可访问的属性。

您可能希望对其进行保护,或为私有属性定义公共 getter 方法。

于 2012-12-29T12:42:13.180 回答