объединение членов класса в PHP - PullRequest
4 голосов
/ 22 июня 2010

Недавно я наткнулся на статью Мэтью Вейера О'Финни (руководитель проекта ZF), в которой содержится пример кода, подобный следующему:

class User
{
    protected $_data = array(
        'username' => null,
        'email'    => null,
        'fullname' => '',
        'role'     => 'guest',
    );

    /* ... */
}

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

Одна альтернатива, о которой я могу подумать, - этоиспользуйте магические методы, чтобы иметь конструктор с одним параметром и четырьмя членами.

class User
{
    protected $_username = null;
    protected $_email = null;
    protected $_fullname = '';
    protected $_role = 'guest';

    public function __construct($data)
    {
        foreach ($data as $key => $value) {
            $this->$key = $value;
        }
    }

    public function __set($name, $value) {
        $member = "_$name";
        $this->$member = $value;
    }
}

Второй блок кода кажется лучше ... однако я сомневаюсьЯ могу написать лучший код, чем мистер О'Финни.Каков наилучший способ обработки членов класса при сохранении чистого интерфейса с конструктором?

Ответы [ 2 ]

2 голосов
/ 22 июня 2010

Основная цель метода «все в массиве», как показано в статье, заключается в том, чтобы метод __set мог контролировать, что устанавливается, а что нет, проверяя массив в первую очередь.Ваш текущий __set этого не делает, но это простое дополнение:

public function __set($name, $value) {
    $member = "_$name";
    if(property_exists($member, $this)) // <- New magic.
        $this->$member = $value;
}

Вы бы хотели сделать то же самое в вашем конструкторе.

Однако вывсе еще будут проблемы с автозаполнением.Современные IDE, которые знают достаточно, чтобы показывать методы и переменные экземпляра, также достаточно умны, чтобы показывать или скрывать объекты в списке на основе того, являются ли они общедоступными, защищенными или частными.Объявление всего защищенного в основном будет иметь тот же эффект, что и скрытие их в массиве, что касается среды IDE.Это серьезный недостаток использования защищенных переменных экземпляра и __set.

1 голос
/ 22 июня 2010

Это все компромисс.Код MO'P действительно вызывает проблемы, если вы хотите полагаться на автозаполнение IDE.Положительным моментом является то, что у вас есть удобный удобный внутренний массив, который может очень легко реализовать такие функции, как реализация функции __toArray ().

Компромисс, который вы предлагаете, кажется мне глупым.Ваша IDE по-прежнему не сможет помочь вам при построении аргументов, а ваша магия __set () в основном просто делает ваши защищенные свойства эффективно открытыми.Вы можете добавить магию так же, как в ответе Чарльза, с теми же оговорками, которые упоминаются (а именно, что у вас все еще будут проблемы с автозаполнением).

Я также многому научился из сообщений MO'P, нов общем, не стоит реализовывать вещи так, как он.Большая часть его примера кода предназначена для демонстрации концепции, а не для практического практического подхода.

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

Тем не менее, если вы хотите полагаться на автозаполнение и не хотитеявный набор псевдосвойств для таких вещей, как __toArray (), вам лучше просто создавать публичные свойства или методы set, добавлять phpDocs и не иметь конструктор, устанавливающий какие-либо из них.Просто заставьте потребляющий код явно настраивать объект с помощью присваивания или вызова метода.

...