PHP isset ($this) и использование того же метода объекта в статическом и контексте объекта

Я работаю над классом, который должен быть доступным через статические вызовы функции, а также методы объекта. Одна вещь, которую я нашел, состоит в том, что я копирую логику через несколько функций.

Упрощенный пример:

class Configurable{

    protected $configurations = array();

    protected static $static_configurations = array();

    public function configure($name, $value){

        // ...lots of validation logic...

        $this->configurations[$name] = $value;

        }

     public static function static_configure($name, $value){

        // ...lots of validation logic (repeated)...

        self::$static_configurations[$name] = $value;

        }

    }

Я нашел решение этого, но это чувствует себя действительно грязным:

class Configurable{

    protected $configurations = array();

    protected static $static_configurations = array();

    public function configure($name, $value){

        // ...lots of validation logic...

        if (isset($this)){
            $this->configurations[$name] = $value;
            }
        else{
            self::$static_configurations[$name] = $value;
            }

        }

    }

Мне нужна статическая функция также так, чтобы я мог установить конфигурации всюду по приложению. Кроме того, хорошая вещь с этой техникой состоит в том, что я могу использовать те же имена методов в обоих объемах.

Есть ли какие-либо проблемы с тестированием объема как это? Проблемы производительности, проблемы прямой совместимости, и т.д. Все это работает на меня на PHP 5.2, и я не должен поддерживать <5.

5
задан Rowan 27 February 2010 в 13:30
поделиться

2 ответа

Проблема со вторым методом заключается в том, что он приведет к ошибке, если для отчета об ошибках установлено значение E_STRICT . Например:

Строгие стандарты: нестатический метод Foo :: bar () не должен вызываться статически в /home/yacoby/dev/php/test.php в строке 10

Суть PHP6 заключается в том, что Ошибки E_STRICT перемещены в E_ALL. Другими словами, E_ALL покроет все ошибки, включая запрет на статический вызов нестатических методов.

Альтернативным методом может быть перемещение логики проверки в статическую функцию. Таким образом, нестатическая функция и статическая функция могут вызывать логику проверки.

2
ответ дан 14 December 2019 в 19:11
поделиться

Статические методы потребуют другого количества аргументов, чем их объективный аналог - дополнительные аргумент будет контекстом выполнения. Если контекста исполнения нет, то только имеет смысл вызывать его статически.

Мой предпочтительный подход, учитывая, что я создаю библиотеку с несколькими подобными интерфейсами, - это создание статического и динамического классов. Пусть один будет передавать вызовы другому. Например:

class DynamicClass {
    protected $foo;
    protected $bar;
    public function baz($arg1) {
        return StaticClass::bar($this->foo, $arg1);
    }
    public function zop($arg1, $arg2) {
        return StaticClass::zop($this->foo, $this->bar, $arg1, $arg2);
    }
    // Context-less helper function
    public function womp($arg1) {
        return StaticClass::womp($arg1);
    }
}

class StaticClass {
    public static function baz(&$fooContext, $arg1) { ... }
    public static function zop(&$fooContext, &$barContext, $arg1, $arg2) { ... }
    public static function womp($arg1) { ... }
}

Вы сами решаете, как передать контекст статическому классу - вам придется делать все, что имеет для вас смысл. Работа, выполняемая в большинстве функций, должна быть довольно незначительной (если вы делаете много, то, вероятно, вам, как правило, следует разбить работу на более мелкие функции), поэтому для этого потребуется лишь несколько аргументов контекста. Или вы можете создать полный массив контекста и передавать его повсюду (либо заполняя его в DynamicClass непосредственно перед каждым вызовом, либо отслеживать все свойства DynamicClass в этом массиве, чтобы вы могли быстро & легко передать его.


Хотя на самом деле кажется, что вы могли бы извлечь выгоду из шаблона проектирования Singleton. Насколько я могу судить, вы пытаетесь создать глобальный Configurable , а также имеете возможность создать индивидуальные локальные конфигурируемые ы.С помощью шаблона проектирования singleton вы создаете глобально доступную версию класса, из которой вы можете гарантировать, что у вас есть только один из них (без нарушения принципов проектирования ООП и необходимости полагаться на $ _GLOBALS и т. Д.). Например:

class DynamicClass {
    protected $foo;
    protected $bar;

    public function baz($arg1) { ... }
    public function zop($arg1, $arg2) { ... }

    public static function getSingleton() {
        static $instance = null;
        if ($instance === null) $instance = new DynamicClass();
        return $instance;
    }
}

Независимо от того, где вы находитесь в коде, вы можете получить доступ к одному и тому же экземпляру с помощью DynamicClass :: getSingleton () . У вас также есть возможность создавать одноразовые, не одноэлементные версии. По сути, вы получаете лучшее из обоих миров, при этом вам нужно писать все свои методы исключительно с учетом динамического доступа.

2
ответ дан 14 December 2019 в 19:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: