Каковы наилучшие методы передачи нескольких переменных функции с помощью PHP

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

Мне было интересно, лучше ли передавать такие параметры или использовать массив?

Я предпочитаю, чтобы это было так

fun(array( 'par1' => 'x', 'par2' => 'y', ..... ) ) 

Установлено

 func($par1, $par2, $par3, ...); 

Как вы думаете?

Очень зависит от варианта использования.

Но вот некоторые решения этой проблемы.


Фиксированный заказ

Если заказ несколько фиксирован, и вам никогда не нужно его менять, тогда:

 <?php function fn($a1, $a2, $a3, $a4, $a5, $a6 = null, $a7 = "foo", $a8 = "bar", array $a9 = array()) {} 

Pros

  • Самодокументирование
  • Тип подсказки
  • Значения по умолчанию

Cons

  • Фиксированный порядок

массив

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

 <?php function fn($a1, $a2, $a3, $a4, $a5, array $optional = array()) {} fn("", "", "", "", "", array("arg9" => false)); 

Pros

  • Легко использовать
  • Нет фиксированного заказа

Cons

  • Не самостоятельно документирование
  • Дорогостоящее подтверждение

Объект параметров

Объект параметра, конечно же, является правильным решением, но непрактичным для обработки:

 <?php class Args { public $arg5 = "foo"; public $arg6 = "bar"; public $arg7 = null; public $arg8 = array(); public $arg9 = true; } function fn($arg1, $arg2, $arg3, $arg4, $arg5, \Args $optional = null) {} // Now comes the impractical part. $optional = new Args(); $optional->arg9 = false; fn("", "", "", "", "", $optional); 

Pros

  • Самодокументирование
  • Нет фиксированного заказа

Cons

  • Очень непрактичный
  • Дорогостоящее подтверждение

Массив к объекту параметров

Вы можете использовать два подхода:

 <?php class Args { public $arg5 = "foo"; public $arg6 = "bar"; public $arg7 = null; public $arg8 = array(); public $arg9 = true; public __construct($args) { foreach ($args as $property => $value) { $this->"set{$property}"($value); } } public function setArg5($value) { if (is_string($value) === false) { throw new \InvalidArgumentException; } $this->arg5 = $value; } // and so on ... } function fn($arg1, $arg2, $arg3, $arg4, $arg5, array $optional = null) { if (isset($optional)) { $optional = new Args($optional); } // ... } fn("", "", "", "", "", array("arg9" => false)); 

Pros

  • Простая проверка
  • Разделение озабоченности
  • Легко пройти
  • Прост в обращении
  • Возможность документировать API

Cons

  • Все еще невозможно документировать его так же хорошо, как фиксированный подход args
  • Дорогостоящее подтверждение

Variadics

В PHP 5.6 есть новая функция, которую вы можете найти полезной, variadics :

 <?php function fn($a1, $a2, $a3, $a4, $a5, ...$optional) {} 

Pros

  • Очень быстро
  • Позволяет создавать специальные API-интерфейсы (например, привязку к базе данных, подготовленную к публикации)

Cons

  • Нелегко задокументировать
  • Дорогостоящее подтверждение

Именованные параметры

И мы могли бы увидеть именованные параметры в будущем.

Вы атакуете неправильную проблему.

Передача 9 параметров функции – это чистый запах кода :

Слишком много параметров : длинный список параметров в процедуре или функции делает читабельность и качество кода хуже.

Благодаря такому множеству параметров есть и хорошие шансы, что вы нарушите:

Длинный метод : метод, функция или процедура, которые стали слишком большими.

Создание произвольного array который объединяет эти параметры, не решит реальной проблемы. Это может сделать ваш код несколько более читабельным и менее уязвимым для небольших проблем, таких как отказ от параметра ( $arg1, $arg2, $arg4 ), но не реальное решение.

Вместо этого вы должны:

Выясните, почему функция нуждается в множестве параметров, а затем исправить эту проблему.

  • Если у единственной функции слишком много ответов, разделите ее. Вы можете сделать одно последовательное разделение: одна задача за другой.
  • Если несколько параметров могут быть объединены в единый объект, создайте для него объект (например: координаты x и y могут быть объединены с точкой, прямоугольник может быть описан двумя противоположными угловыми точками). Попробуйте создать что-то многоразовое, поэтому единственной целью является не просто передать аргументы этой единственной функции.

Существует много методов, чтение хорошей статьи / книги о (оо) рефакторинг кода может дать вам несколько советов.