PHP避免魔术方法中的递归

时间:2012-12-29 12:02:34

标签: php magic-methods

我没有找到我在这里发布的问题的完全重复,所以这里是:

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中有什么变化或者这是默认行为吗?可以采取哪些措施以优雅的方式实现此设计的目标?

2 个答案:

答案 0 :(得分:2)

我不知道你的意思,但没有第二次电话。当您在课堂外访问该媒体资源时,__get()只会被调用一次。 <{1}}方法中的$this->$property不会触发另一个电话。

从PHP文档:

  

在与属性交互时调用重载方法   或者尚未声明或在其中不可见的方法   目前的范围。

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

答案 1 :(得分:2)

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

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