使用php中的getter从父类调用受保护的变量

时间:2013-02-01 09:38:31

标签: php oop variables getter

我是PHP的OOP新手。我有以下问题: 我有一个名为'User'的父类和2个子类'Business'和'Standaard'。

我的父类看起来像这样:

class User {    
protected $m_iId;
protected $m_iFoto;
protected $m_sEmail;

/*Constructor*/
public function __construct(){
    $this->Id = -1;
    $this->Foto = "";
    $this->Email = "";
} 

/*Setter*/                    
public function __set($p_sProperty, $p_sValue){
    switch($p_sProperty){
        case "Id":
            if(is_numeric($p_sValue) && $p_sValue !== -1){
                $iNumber = intVal($p_sValue);
                if($iNumber >= -1){
                    $this->m_iId = $p_sValue;
                }
                else{
                    echo("Not a valid id: ".$p_sValue);
                }
            }
            break;
        case "Foto":
            if(is_numeric($p_sValue) && $p_sValue !== -1){
                $iNumber = intVal($p_sValue);
                if($iNumber >= -1){
                    $this->m_iFoto = $p_sValue;
                }
                else{
                    echo("Not a valid Foto_id: ".$p_sValue);
                }
            }
            break;
        case "Email":
            $this->m_sEmail = $p_sValue;
            break;  
        default: echo("Unknown property: ".$p_sProperty);
    }
}

/*Getter*/
public function __get($p_sProperty){
    $vResult = null;
    switch($p_sProperty){
        case "Id";
            $vResult = $this->m_iId; 
            break;
        case "Foto";
            $vResult = $this->m_iFoto; 
            break;
        case "Email";
            $vResult = $this->m_sEmail; 
            break;
        default: echo("Unknown property: ".$p_sProperty);
    }
    return $vResult;
}

}

小孩看起来像这样:

class UserStandaard extends User {

    //velden die bereikbaar zijn
    protected $m_sName;

    /*Constructor*/
    public function __construct(){
        parent::__construct();
        $this->Name = "";
    } 

    /*Setter*/                    
    public function __set($p_sProperty, $p_sValue){
        switch($p_sProperty){
            case "Name":
                $this->m_sName = $p_sValue;
                break;
            default: echo("Unknown property: ".$p_sProperty);
        }
    }

    /*Getter*/
    public function __get($p_sProperty){
        $vResult = null;
        switch($p_sProperty){
            case "Name";
                $vResult = $this->m_sName; 
                break;
            default: echo("Unknown property: ".$p_sProperty);
        }
        return $vResult;
        }
}

我的问题如下: 我如何申请ID? 我想做点什么:

$oUser = new UserStandaard();
echo $oUser->Id;

但这不起作用......它不断回响

Unknown property: Id

谢谢!

2 个答案:

答案 0 :(得分:2)

问题是__get__set的派生类实现不会调用基类实现。这不会自动发生,您需要明确地执行此操作:

class UserStandaard extends User {

    /*Setter*/                    
    public function __set($p_sProperty, $p_sValue){
        parent::__set($p_sProperty, $p_sValue);
        // your current code follows
    }
}

但是,这仍然无效,因为现在您的父实现只会识别它知道的三个属性。似乎没有直接的方法来处理这个问题,这意味着您的设计存在问题,需要进行修改。

可能的解决方案

结构__get__set更具可插性(示例待处理)。我的意思是他们认识到的属性集不应该是硬编码的,因为这使得扩展它们非常困难。理想情况下,您需要为每个属性使用不同的getter和setter:

class User {
    public function getName() { ... }
    public function setName($name) { ... }
}

这样可以让代码保持良好,干净和分离。然后,您可以将__get__set联系起来转发这些方法:

public function __get($name)
{
    $getter = 'get'.ucfirst($name);
    if (!method_exists($this, $getter)) {
        die("This object does not have a $name property or a $getter method.");
    }

    return $this->$getter();
}

public function __set($name, $value)
{
    $setter = 'set'.ucfirst($name);
    if (!method_exists($this, $setter)) {
        die("This object does not have a $name property or a $setter method.");
    }

    $this->$setter($value);
}

通过这种方式,您可以将每个属性分解为上面的getter和setter方法,并且绝对不需要在派生类中覆盖__get__set。只需为您感兴趣的属性声明其他getter和setter,基类__get / __set将正确转发到这些方法。

答案 1 :(得分:1)

这是因为您在UserStandaard类中的覆盖__get()方法中没有Id。

 /*Getter*/
    public function __get($p_sProperty){
        $vResult = null;
        switch($p_sProperty){
            case "Name";
                $vResult = $this->m_sName; 
                break;
            default: echo("Unknown property: ".$p_sProperty);
        }
        return $vResult;
    }

但是你可能会认为这是在他的父母那里。

不,因为你已经覆盖了父方法。

您正在尝试使用__get和__set在User类中使用魔术方法重载属性,但是您在UserStandaaard类中覆盖这些函数。这两个函数只知道自己类中的属性,因为Userstandaard的__get方法不会调用它的父方法。但即使你这样做,也会失败,因为你使用switch-cases和不同的属性名称来实现你的魔术方法的方式。

因此,使用UserStandaard中的魔术方法只会知道1个属性,如果从User调用父方法,它只会知道父属性(如Jon所提到的)。

我会说改变你的设计,这是行不通的。

Jon有一个很好的例子说明它是如何运作的!

哦,对你说:Welkom bij stack-overflow! ;)