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


Calling protected variable from parent class with getters in php

我是PHP中OOP的新手。我有以下问题:我有 1 个名为"用户"的父类和 2 个子类"业务"和"标准"。

我的父类看起来像这样:

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

谢谢!!

问题是__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 将正确转发到这些方法。

这是因为

在 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 方法不会调用它的父方法。但即使你这样做了,它也会失败,因为你如何使用开关大小写和不同的属性名称实现你的魔术方法。

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

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

乔恩有一个很好的例子来说明它是如何工作的!

哦,还有对你喊道:Welkom bij stack-overflow! ;)