Изменение статического массива в унаследованных классах PHP - PullRequest
2 голосов
/ 03 августа 2011

Мне интересно, существует ли простой или рекомендуемый способ изменения только части массива, определенной как статическая, при выполнении наследования в php. Я использую статический массив для настройки параметров определения в объектной модели для создания данных 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);
    }
}

Я добавил $ name к этой версии моего xmlAbstract, чтобы, когда несколько элементов данных использовали одну и ту же структуру, я мог просто передать имя ключа для этой структуры, чтобы создать соответствующий элемент DOM в XML на основе CodeDescriptionType. То, что я хотел бы сделать, это добавить параметры 'default' => "value" и 'valid' = array(1,2,3,4) под ключом кода. Если все остальное терпит неудачу, я могу добавить два дополнительных параметра в этот класс для передачи этих двух, но мне было бы интересно узнать, есть ли способ изменить содержимое статического массива при наследовании от родительского класса. (array_merge не будет работать в статическом контексте)

Ответы [ 2 ]

0 голосов
/ 10 ноября 2016

Я столкнулся с другой необходимостью создать новый набор определений для моей оболочки DOMDocument, упомянутой в этом посте. Я до сих пор не нашел каких-либо встроенных модулей для слияния элементов массива, но из-за природы этого конкретного приложения я действительно не хочу просто писать стандартные унаследованные свойства, потому что это может отчасти побороть цель написания оболочки вокруг DOMDocument на первом месте. (Если я в конечном итоге пойду по этому пути, я просто напишу что-нибудь, чтобы преобразовать свойства объекта PHP в элементы и атрибуты DOMDocument - что еще может произойти, если я найду способ легко создать defs из xsd автоматически)

Я забыл, что этот поток существует, но, по сути, в конечном итоге сделал то, что предлагали ответы, теперь, когда я несколько лучше справляюсь с областями в PHP, работая с ним. У новых определений, которые я создаю, есть ряд унаследованных (расширенных) типов в xsd для начала. Таким образом, определение определений в PHP для помощи в создании возможных элементов в DOMDocument, которые обертываются на нескольких уровнях в моделях, все равно требуется.

В абстрактный родительский базовый класс (тот, который на самом деле делает грязную работу по обертыванию DOMDocument и построению различных частей DOMElement sub-частей), я добавил следующую функцию:

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, но нашел более полезным передать имя класса, так как это позволяет мне также «импортировать» определения из класс вне структуры наследования PHP.

Так, например, если у меня есть одно определение для типа customerPaymentProfileType, в котором имена базовых элементов (класс customerPaymentProfileBaseType) делятся с парой других вариантов платежных профилей. Затем существует другой тип, который имеет дополнительный параметр, но в остальном идентичен customerPaymentProfileType.

Одна из вещей, которые я делаю с этими определениями, заключается в том, что я назначаю «имя элемента», которое будет отображаться в окончательном xml-выводе элемента DOMElement, созданного в любой дочерней ветви конечного xml в главном конструкторе базы. абстрактный класс. Большинство «базовых» определений в XML эквивалентны абстрактному классу в PHP, и они не используются напрямую для определения типа элемента, а служат только как расширение для других типов. Однако customerPaymentProfile используется непосредственно как тип XML в одном определении. У меня также есть проблема, заключающаяся в том, что при использовании определения типа Extended (Ex) имя элемента XML отличается, и обычно я передаю его имя на первом неабстрактном уровне. Таким образом, вместо того, чтобы наследовать от простого типа, я могу наследовать от baseType (который расширяет основную обертку и включает определения базового элемента), добавить уникальный для расширенного определения, определить имя элемента [Different], а затем импортировать дополнительные параметры в базовой версии.

// 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__));
0 голосов
/ 03 августа 2011

Сначала вы спросите:

Мне интересно, существует ли простой или рекомендуемый способ изменения только части массива, определенной как статический, при выполнении наследования в 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 );

Вы можете получить доступ к статическим свойствам суперкласса в PHP, используя ключевое слово self; Сама операция может быть выполнена путем простого присвоения новых значений с использованием соответствующей нотации доступа к массиву PHP.

Это правда, что вы не можете выполнять какие-либо операции, кроме присваивания, когда объявляете статические (или любые другие) переменные, но вы, безусловно, можете изменить их так, как захотите после объявления.

Это то, что вы ищете? Этот код правильно добавит ключи default и valid к статическому массиву, определенному в вашем родительском классе, согласно вашему описанию в вопросе.

Вы также спрашиваете:

Мне было бы любопытно узнать, есть ли способ изменить содержимое статического массива при наследовании от родительского класса. (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 );
    }
}

Это будет печатать точно так, как ожидается: parent и super будут выплевывать массив, определенный в суперклассе, в то время как self будет выплевывать массив, определенный в подклассе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...