Php 动态检索类属性值

Php 动态检索类属性值,php,Php,我来自.Net背景,我正试图将我的大脑围绕在一个编程模式上,我已经习惯了这个模式,但它是用PHP编写的 我有一个具有关联数组属性的类。我想将一些(但不是全部)关联数组键“提升”到类级属性。在C#中,我通常会这样做: /C#代码 类MyClass{ 私有字典属性=新字典(); //从私有存储获取/设置ID 公共字符串ID{ 获取{return(attributes.ContainsKey(“ID”)?attributes[“ID”]:“n/a”);} 设置{attributes.Add(“ID”,

我来自.Net背景,我正试图将我的大脑围绕在一个编程模式上,我已经习惯了这个模式,但它是用PHP编写的

我有一个具有关联数组属性的类。我想将一些(但不是全部)关联数组键“提升”到类级属性。在C#中,我通常会这样做:

/C#代码
类MyClass{
私有字典属性=新字典();
//从私有存储获取/设置ID
公共字符串ID{
获取{return(attributes.ContainsKey(“ID”)?attributes[“ID”]:“n/a”);}
设置{attributes.Add(“ID”,value);}
}
}
这允许我的对象控制缺少属性的默认值。在PHP中,我找不到任何直接实现这一点的方法。我的第一个解决方法是只使用函数:

//PHP代码
类MyClass{
private$attributes=array();
//拿到身份证
公共函数getID(){
返回(数组键存在('ID',$this->attributes)?$this->attributes['ID']:'n/a');
}
//设置ID
公共函数setID($value){
$this->attributes['ID']=$value;
}
}
尽管调用语法略有不同,而且每个属性有两个方法,但这是可行的。此外,使用这些对象的代码当前正在检查对象变量,因此无法找到函数

然后我开始沿着对象本身的
\uuu set
\uu get
的神奇方法路径,然后在传入的
$name
上切换case,设置/获取我的局部变量。不幸的是,如果您直接修改底层数组,这些方法就不会被调用


所以我的问题是,在PHP中有没有可能有一个类级的属性/变量在使用之前不会被计算?

PHP没有属性,因为C#程序员会理解这个概念,所以你必须使用方法作为getter和setter,但原理完全相同

class MyClass {
    private $attributes = array ();

    public function getSomeAttribute () {
        if (!array_key_exists ('SomeAttribute', $this -> attributes)) {
            // Do whatever you need to calculate the value of SomeAttribute here
            $this -> attributes ['SomeAttribute'] = 42;
        }
        return $this -> attributes ['SomeAttribute'];
    }
    // or if you just want a predictable result returned when the value isn't set yet
    public function getSomeAttribute () {
        return array_key_exists ('SomeAttribute', $this -> attributes)?
            $this -> attributes ['SomeAttribute']:
            'n/a';
    }

    public function setSomeAttribute ($value) {
        $this -> attributes ['SomeAttribute'] = $value;
    }
}

基本上,您在实现中获得了正确的基本思想,但这确实意味着有很多“样板”代码。理论上,你可以通过uuu get和uuu set避免很多这种情况,但我强烈建议不要这样做,因为它们会导致大量的混乱和令人讨厌的逻辑混乱,比如你遇到的“如果值是在类内部而不是从外部设置的,会发生什么?”问题

在PHP中,您可以执行以下操作:

<?php
class MyClassWithoutParams{
    function test(){
      return $this->greeting . " " . $this->subject;
    }
}

$class = new MyClassWithoutParams();
$class->greeting = "Hello";
$class->subject = "world";

echo $class->greeting . " " . $class->subject . "<br />"; //Hello World
echo $class->test(). "<br />"; //Hello World
?>

使用属性不需要定义任何属性、getter或setter。当然,这样做更好,因为它使代码更易于阅读,并允许eclipse(或任何IDE)的自动完成功能理解您正在寻找的内容——但如果您只是在寻找实现实体的最懒的方法,这也会起作用

更常见的方法是使用关联数组而不是类,但在数组上不能定义方法

<?php
$array = new array();

$array["greeting"] = "Hello";
$array["subject"] = "World";

echo $array["greeting"] . " " . $array["subject"]; //Output: Hello World
?>


没有。我也不知道为什么
\uuuu set/\uu get
不适合您。很简单,只需使用默认值为null的私有成员和检查成员值是否为null的公共getter即可。如果是,则计算其值并在返回之前将其存储在成员中,否则,仅返回它。相当标准的惰性评估模式。但是PHP没有属性的概念,所以您必须使用标准方法来获取和使用gettersetter@zerkms你得到的和得到的都是很讨厌的。与显式的getter和setter相比,它们使代码变得晦涩难懂,难以遵循。此外,与显式getter/setter相比,性能相当差。谢谢各位。性能不是什么大问题。getter和setter要求您永远不要直接修改数组(如果我理解正确的话)。我对另一种模式很满意,我只是想把我知道的和我能做的匹配起来。@GordonM:我没有问关于最佳实践和性能的观点-OP提到它不符合我所问的其他一些要求。PHP确实有属性,由于
$attribute
是对象的属性
MyClass
@Shamil,我指的是OP在C#中使用的属性,这些属性对于类的外部用户基本上是不可见的。“如果在类内而不是从外部设置值,会发生什么情况?”——没有。这两条路径都是相同的,但是您依赖对象的使用者来相应地处理缺少的值,而不是对象本身,对吗?是的。如果希望在类内处理该问题,则需要有getter/setter对(或者在使用基于参数的泛型getter/setter时,需要有一个将(内部)数组解析为属性的函数)。在这两种情况下,您都无法通过“相同”的访问调用实现它(需要前缀为get或set)