Передача параметров в php-функцию

Рубрика: MaxSite CMS -> PHP
Суббота, 5 января 2008 г.
Просмотров: 4373
Подписаться на комментарии по RSS
]]>
]]>

PHP-функция может принимать параметры, например так:

  1.  function f1( $arg1, $arg2 )

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

  1.  function f1( $arg1, $arg2, $arg3 = '', $arg4 = '' )

То есть теперь, если при вызове функции не указывать последние два аргумента, то им будут присвоены дефолтные значения: в нашем случае - пустая строка.

Проходит еще какое-то время и мы решаем добавить в нашу функцию еще и параметры для форматирования. Например html-элементы «до» и «после», class, шаблон форматирования и т.д. Получается, что параметров у нашей функии становится довольно много и пользоваться ей уже не совсем удобно. Тем более может возникнуть ситуация, когда указать нужно не все параметры, а скажем только 5-й и 8-й.

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

  1.  function f1( $args = '' )
  2.  {
  3.   parse_str($args, $r);
  4.  ...

Пример вызова:

  1.  f1('b=555&a=777');

В результате в массиве $r окажется структура:

  1.  Array
  2.  (
  3.   [a] => 777
  4.   [b] => 555
  5.  )

Казалось бы, что проблема решена: мы можем не изменяя объявления функции, менять её функционал. Но есть один нюанс. Связан он с тем, что строчка параметров должна передаваться по правилам URL-строки, где необходимо заменять служебные символы (кавычки, пробелы и т.д.) на их коды. Таким образом, перед тем, как выполнить parse_str, нужно выполнить парсинг строки.

Всё это не совсем удобно, но мы видим, что в результате нам всё равно нужно получить массив параметров. Так что нам мешает сразу передавать в параметре готовый массив?

Вот пример:

  1.  function f1( $args = array() )
  2.   {
  3.   if ( is_array($args) ) $r = $args;
  4.   else parse_str($args, $r);
  5.   # контроль
  6.   echo '<pre>';
  7.   print_r( $r );
  8.   echo '</pre>';
  9.   }
  10.   # примеры вызова
  11.   f1( array ('a' => '888') );
  12.   f1( 'b=555&a=777' );

Обратите внимание, что функция сама проверяет тип параметра (is_array). Если это не массив, то выполняется parse_str. Получается универсальный подход.

Однако это еще не всё. Как быть в случае, если в параметрах переданы не все значения? Тут есть два подхода.

Первый - это явно прописать проверку на существование значения и если его нет, то взять дефолтное:

  1.  if ( !isset($r['a']) ) $r['a'] = '1';
  2.   if ( !isset($r['b']) ) $r['b'] = '2';

Второй способ - это задать массив дефолтных значений, который мы просто объединяем с входящим:

  1.  $default = array(
  2.   'a' => '1',
  3.   'b' => '2',
  4.   'c' => '3',
  5.   );
  6.   $r = array_merge($default, $r);

Теперь, при вызове:

  1.  f1( array ('a' => '888', 'c' => '999') );

Получим в $r:

  1.  Array
  2.  (
  3.   [a] => 888
  4.   [b] => 2
  5.   [c] => 999
  6.  )

Как видите, все довольно просто и элегантно. smile

]]>twitter.com Google Buzz google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru]]>
РЕКЛАМАВставки в ванную Реставрация ванн Качественно и недорого

Комментариев: 16

Вы можете получать новые комментарии к этой записи по RSS или оформить подписку на все комментарии сайта. Или даже на все новые записи сайта. Не знаете, как это сделать?
  1. 2008-01-05 в 16:15:02 | LitoX

    все эти кода мучают :smile:

  2. 2008-01-05 в 16:34:58 | FX Poster

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

  3. 2008-01-05 в 16:48:07 | CTapbIu

    зачем xml, просто сериализированный массив ,)

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

  4. 2008-01-05 в 16:50:50 | FX Poster

    А нахрена тогда у функции несколько параметров было делать. smile Если есть один универсальный. smile

  5. 2008-01-05 в 17:27:12 | Максим

    Так оно всегда вначале кажется, что хватит пары параметров, а уже после вдруг понимаешь, что нужно еще парочка. Я приведу на примере WordPress'а. Есть функции вывода рубрик/ссылок/т.п. Если бы в них можно было бы передать параметры через массив, но не было бы ни проблемы совместимости, ни сложностей с оформлением. А сейчас же классы, элементы до/после жестко вбиты в функции. ИМХО - неудобно - первое же обновление и все заново приходится менять. Многие на этом накололись. :sad:

  6. 2008-01-05 в 17:33:48 | FX Poster

    Ну, если честно - по проектированию Wordpress отнюдь не идеал. ;)

    А вот появление таких функций - это просто плохо с точки зрения проектирования.

    Кстати, если вывод ссылок оформить ввиде обьектов/классов - получилось бы гораздо удобнее.

  7. 2008-01-05 в 21:00:28 | Tapac

    В целом полезно, но позабавил вот это текст:

    перед тем, как выполнить parse_str, нужно выполнить парсинг строки.

    Учитывая, что parse_str можно перевести как парсинг_строки )))

    Просто каламбур, так сказать)

  8. 2008-01-05 в 21:03:51 | Артём Курапов

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

  9. 2008-01-06 в 01:37:48 | Коля Дубр

    Такой подход действительно полезен и удобен для всяких "настроечных" методов. В остальных случаях - надо думать. Что проще запоминать: порядок передачи аргументов (если больше 3 - уже фигово), ключи массива (+что там по умолчанию), или несколько разных методов (хорошо, если получается ясный логичный интерфейс, хотя часто найти таковой не удается).

  10. 2008-01-06 в 05:39:00 | cryonyx

    :shock:

    Макс, а чем тебя не устраивает func_get_args() и родственные ей функции?

  11. 2008-01-06 в 11:25:46 | Максим

    2cryonyx: Тем, что в таких случаях нужно перебирать входящие параметры по номерам. Как определить, что переданный параметр это «элемент "до"», а не «элемент "после"»?

  12. 2008-01-06 в 12:27:04 | Anton

    Огромный пардон, что не очень по месту задаю вопрос - но уж очень припекло! Несколько часов мучался, искал способ, как убрать из сайдбара вордпресса какой-либо блок (скажем, dtree), на основании юзер-левела читающего. Ничего не нашёл((. Т.к. если в dtree указать, что пустые категории должны скрываться, и при этом применить disclose-secret плагин, то dtree сходит с ума, и показывает или только те папки, где нет скрываемых disclose-ом постов, или показывает сразу все, вне зависимости от уровня юзера. Так что выход один - просто убирать dtree целиком из сайдбара, если уровень пользователя меньше, скажем, второго. Но только как это сделать?((( Подозреваю, что нужно добавить в код что-то типа "иф юзер левел блаблабла...", но не кодер я((. Так что в целом типа прошу помощи, граждане посетители!!)

  13. 2008-01-06 в 21:49:44 | CTapbIu

    Anton

    if (current_user_can('level_?')) {
    ....
    }

    вместо level_?:

    level_0 == subscriber

    level_1 == contributor

    level_2-level_4 == author

    level_5-level_7 == editor

    level_8-level_10 == administrator

    ну или

    if (current_user_can('%role%')) {
    ....
    }

    где %role% что нибудь из: subscriber, contributor, author, editor или administrator

  14. 2008-01-08 в 15:01:19 | Dmitry Yashin
    Тем более может возникнуть ситуация, когда указать нужно не все параметры, а скажем только 5-й и 8-й.

    function f1( $arg1, $arg2, $arg3 = '', $arg4 = '')

    Укажем четвертый, неуказывая третий:

    f1('arg1', 'arg2', null, 'arg4')

    Все просто и не стоит заморачиваться ;)

  15. 2008-03-13 в 13:56:23 | Severus

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

    $application->Func1(
    "some_arg",
    "some_arg_2",
    Array(
    здоровый массив с настройками и параметрами
    )
    );
  16. 2008-06-23 в 05:01:21 | Lektor

    Сенк за статью .. как раз то что искал ... правда ответ н свой вопрос нашел в коментах: сенкс Dmitry Yashin.

Оставьте комментарий!

Не регистрировать/аноним

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email.
(При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д.)



grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

(обязательно)