найкраща практика для ініціалізації членів класу в php


10

У мене в конструкторах дуже багато такого коду: -

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

Чи краще це зробити, а не вказувати значення за замовчуванням у визначенні властивості? тобто public $property = default_val? Іноді існує значення логіки для значення за замовчуванням, а деякі значення за замовчуванням беруться з інших властивостей, саме тому я робив це в конструкторі.

Чи повинен я використовувати сектори, щоб вся логіка значень за замовчуванням була розділена?

Відповіді:


8

Я раніше мав подібні філософські дискусії із собою. Ось де я стою більшу частину часу, хоча розумію, що це відповідь, заснована на думці:

Я думаю, що може допомогти відповісти на питання - це передача $ params, яка може мати, а може і не мати встановлені атрибути / члени масиву.

За ці роки я прийшов до такого висновку:

Уникайте проходження масивів.

Чому? Ну, немає ніякого способу встановити або встановити дозорні значення для необов'язково переданих аргументів.

Іншими словами, із вказаним вами кодом ви не можете зробити щось подібне:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 та $ arg2 - необов'язкові аргументи - якщо вони не передані, вони мають відповідно NULL та DEFAULT_VAL - не потрібно чітко перевіряти.

Можливо, це видається довільним.

Я думаю, що я розумію те, що ви намагаєтеся зробити - проходження єдиної довідки на відміну від тонни аргументів. Це приводить мене до мого наступного ухилення:

Якщо не передаються "атомні" змінні (рядки, цілі числа, букви), то передаються об'єкти.

Тут є переваги від продуктивності, оскільки передача об'єктів здійснюється за посиланням (хоча масиви, на мою думку, приблизно однакові всередині PHP).

Тож ви можете зробити щось на кшталт:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

Аргумент переданого об'єкта гарантовано матиме "властивість1", "властивість2", хоча можливо, і самі значення за замовчуванням.

Крім того, сюди ви можете ввести підказку, і хороший IDE також буде автоматично пропонувати кодування.

Але ми швидко усвідомлюємо, що у нас відбувається курятина та яйця: ви створюєте об'єкт із переданими аргументами об'єкта, які самі потребують побудови в якийсь момент.

То де це залишає нас? Ну, я прийшов до висновку, що врешті-решт усі класи перенаправляються на відсутність кращого терміна до "атомних" змінних (рядки, плаваючі, парні, ints, ресурси, ви отримуєте мою думку), і що я, як правило, намагаюся побудувати всі класи з тими змінними типами або об'єктами, але не масивами.

То я відповів на ваше запитання? певно, не зовсім. Але я сподіваюся, що я проілюстрував щось корисне, хоч і дещо стилістичне. Я думаю, що код трохи чистіший, читабельніший і менш затратний.

Тепер це не означає, що ви не повинні санітувати свої дані. Це вже інша дискусія.

Сподіваюсь, це допомагає.


1
Це хороший момент і дуже зручний для підказок IDE, але є занадто багато властивостей об'єкта, щоб передавати їх усім параметрам. Якщо у вас є 7 аргументів, скажімо, 5 з яких є необов'язковими, ви закінчуєте такі речі, як, new object($param1,-some default value so I can specify the next parameter-, $param3);і тому у вас є різні значення за замовчуванням, кодовані в декількох різних місцях
rgvcorley

3

Хоча я схильний уникати передачі масивів конструктору, іноді мені здається необхідним обробити вхідне значення масиву (наприклад, для класу, який зчитує значення з файлу конфігурації).

У такому випадку я скористаюсь функціями масиву PHP, щоб переконатися, що я працюю саме з тим, що, на мою думку, працюю:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

Цей останній рядок використовує array_merge()для перезапису будь-яких значень $defaultsіз відповідними їм значеннями $incoming. Я також використовую array_intersect_key()для того, щоб результуючий масив не містив зайвих ключів, які клас / метод не міг би обробити.


Привіт, Яка поведінка, якщо $ defaults містить масив замість простих змінних?
Pol Dellaiera

@PolDellaiera Подивіться array_merge_recursive.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.