修改继承的PHP类中的静态数组

时间:2011-08-03 17:54:21

标签: php inheritance static

我想知道在php中进行继承时,是否有一种简单或推荐的修改数组的一部分定义为静态的方法。我正在使用静态数组在对象模型中设置定义参数,以便为Web服务创建XML查询数据。此特定服务对单个数据类型使用单个数据类型,其中包含“代码”的两个值(键)和与代码相关的“描述”。

我的模型允许我指定“默认”和我的代码在创建DOMElement时可以检查的“有效”值数组。当然,这个特殊用法只包含两个值,因此定义类似于CodeDescriptionType的特定类来处理这些类并不是非常困难,但我知道为特定类创建其他类似继承的类可能是有价值的。请求类型和一些数据结构比仅仅两个键/值对更长。以下是代码的示例:

class CodeDescriptionType extends Shipping_xmlAbstract {
    public static $_elementDefs = array(
        'Code' =>
            array(
                'type' => 'string',
                'min'  => 1,
                'max'  => 1
            ),
        'Description' =>
            array(
                'type' => 'string',
                'min'  => 0,
                'max'  => 1
            )
    );
    public function __construct($name,$elem=null) {
        parent::__construct($name,null,$elem);
    }
}

我在这个版本的xmlAbstract中添加了$ name,这样当多个数据元素使用相同的结构时,我可以传入该结构的键名来在XML中创建适当的DOM元素基于CodeDescriptionType。我希望能够在“代码”键下添加'default' => "value"'valid' = array(1,2,3,4)参数。如果所有其他方法都失败了,我可以在这个类中添加另外两个参数来传递这两个参数但是我很想知道是否有一种方法可以在从父类继承时修改静态数组的内容。 (array_merge在静态上下文中不起作用)

2 个答案:

答案 0 :(得分:0)

首先,你问:

  

我想知道在php中进行继承时,是否有一种简单或推荐的方法来修改定义为静态的数组的一部分。

我不太确定您是否正在为您的确切用例或一般答案寻找特定于域的答案,但这里有一种方法可以在某些子类中添加这些属性:

class Sub extends CodeDescriptionType {
    public function __construct( $name, $elem = null ) {
        parent::__construct( $name, null, $elem );

        self::$_elementDefs['Code']['default'] = 'value';
        self::$_elementDefs['Code']['valid'] = array( 1, 2, 3, 4 );
    }
}

$c = new Sub( 'test', 'elem' );
print_r( Sub::$_elementDefs );

您可以使用self关键字访问PHP中超类的静态属性;可以通过使用适当的PHP数组访问表示法简单地分配新值来执行操作本身。

当您声明静态(或任何成员)变量时,您无法执行除赋值之外的任何操作,但您可以在声明之后以任何方式修改它。

这是你要找的吗?此代码将根据问题中的描述将defaultvalid键正确添加到父类中定义的静态数组中。

你也问:

  

我很想知道在从父类继承时是否有办法修改静态数组的内容。 (array_merge在静态上下文中不起作用)

class Super {
    public static $array1 = array( 1, 2 );
}

class Sub extends Super {
    public static $array2 = array( 3, 4 );

    public function __construct() {
        self::$array2 = array_merge( super::$array1, self::$array2 );
    }
}

$s = new Sub;
print_r( Sub::$array2 );

这很好用;数组被合并。当然,只有在实例化类时才会发生合并;你也可以把它放在静态方法中。但是,由于PHP中没有静态构造函数,执行实际合并需要成员是公共的(因此您可以在类外部自己执行合并)或将合并代码放入构造函数或静态您手动调用的方法。

更多信息/测试代码揭示了PHP中的静态继承:

class Super {
    public static $array1 = array( 1, 2 );
}

class Sub extends Super {
    public static $array1 = array( 3, 4 );

    public function __construct() {
        print_r( self::$array1 );
        print_r( parent::$array1 );
        print_r( super::$array1 );
    }
}

这将完全按预期打印:parentsuper将吐出超类中定义的数组,而self将吐出子类中定义的数组。

答案 1 :(得分:0)

我遇到了另一个需要为本文中提到的DOMDocument包装器创建一组新的定义。我仍然没有发现任何内置函数来合并数组元素,但由于这个特定应用程序的性质,我真的不想写标准的继承属性,因为这会破坏写作的目的首先是DOMDocument的包装器。 (如果我最终走这条路线,我只会写一些东西将PHP对象属性转换为DOMDocument元素和属性 - 如果我能找到一种方法从xsd自动构建defs,这可能会发生)

我忘了这个帖子已经存在,但基本上最终做了答案,现在我在使用它几年后对PHP的范围有了更好的处理。我创建的新定义在xsd中有许多继承(扩展)类型。因此,无论如何都需要在PHP中定义定义以帮助构建DOMDocument中的最终元素,这些元素包含在模型中的多个级别。

在抽象父基类(实际执行包装DOMDocument和构建各种子DOMElement部件的脏工作的类)中,我添加了以下函数:

public static function cascadeDefs($layer) {
    if(!class_exists($layer)) {
        $layerNS =  __NAMESPACE__ . '\\DataTypes\\' . $layer;
        if(class_exists($layerNS))
            $layer = $layerNS;
    }
    if(class_exists($layer))
        foreach($layer::$_elementDefs as $k => $v)
            if(!isset(static::$_elementDefs[$k]))
                static::$_elementDefs[$k] = $v;
}

我考虑让它回溯以找出调用类是什么而不是传递$ layer变量,但发现传递类名更有用,因为它允许我也导入' import& #39;来自PHP继承结构之外的类的定义。

因此,例如,如果我对“customerPaymentProfileType”有一个定义'与其他几种支付配置文件共享基本元素(customerPaymentProfileBaseType类)名称的类型。然后是另一种类型,它有一个额外的参数,但在其他方面与customerPaymentProfileType相同。

我对这些定义所做的一件事就是分配'元素名称'这是显示在基本抽象类的主构造函数中最终xml的任何子分支中创建的DOME元素的最终xml输出中。大多数'基地' XML中的定义相当于PHP中的抽象类,不是直接用于定义元素类型,而是仅用作其他类型的扩展。但是,customerPaymentProfile在一个定义中直接用作XML类型。 我还有一个问题,当使用Extended(Ex)类型定义时,XML元素名称是不同的,通常我在第一个非抽象级别传递它的名称。 因此,我可以继承baseType(扩展主包装并包含核心元素定义),添加一个唯一的扩展定义,定义[不同]元素名称,然后导入其他参数,而不是从简单类型继承。在基本版本中。

// technically extends customerPaymentProfileType but that is not an abstract and has different naming
class customerPaymentProfileExType extends customerPaymentProfileBaseType
{
    //public static $_attrNames = array();
    public static $_elementDefs = array(
        'customerPaymentProfileId' => array(
            'type' => 'string', // numeric string
            'min' => 0
        )
    );

    /**
     * inherited child of the xmlAbstract::__construct to build a request XML data element
     * @param null|array $elem
     */
    public function __construct($elem=null) {
        parent::__construct('paymentProfile',null,$elem);
        self::cascadeDefs(get_parent_class(__CLASS__));
        // add types from customerPaymentProfileType also
        self::cascadeDefs('customerPaymentProfileType');
    }
}

在正常情况下,只需调用:

,就可以从父项导入继承的数组元素
self::cascadeDefs(get_parent_class(__CLASS__));