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

5 января 2008 г. Просмотров: 12695 RSS 18
Дневник » PHP

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

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

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

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

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

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

function f1( $args = '' )
{
    parse_str($args, $r);
...

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

f1('b=555&a=777');
В результате в массиве $r окажется структура:

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

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

Вот пример:

function f1( $args = array() )
    {
        if ( is_array($args) ) $r = $args;
            else parse_str($args, $r);
        # контроль
        echo '
';
        print_r( $r );
        echo '
'; } # примеры вызова f1( array ('a' => '888') ); f1( 'b=555&a=777' );

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

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

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

if ( !isset($r['a']) ) $r['a'] = '1';
    if ( !isset($r['b']) ) $r['b'] = '2';
Второй способ - это задать массив дефолтных значений, который мы просто объединяем с входящим:

$default = array(
        'a' => '1',
        'b' => '2',
        'c' => '3',
    );
    $r = array_merge($default, $r);
Теперь, при вызове:

f1( array ('a' => '888', 'c' => '999') );
Получим в $r:

Array
(
    [a] => 888
    [b] => 2
    [c] => 999
)
Как видите, все довольно просто и элегантно. smile


twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru friendfeed.com google.com yandex.ru
Комментариев: 18
  1. все эти кода мучают :smile:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  10. :shock:

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

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

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

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

  13. 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#14
    Тем более может возникнуть ситуация, когда указать нужно не все параметры, а скажем только 5-й и 8-й.

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

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

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

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

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

    $application->Func1(
    "some_arg",
    "some_arg_2",
    Array(
    здоровый массив с настройками и параметрами
    )
    );
  16. Сенк за статью .. как раз то что искал ... правда ответ н свой вопрос нашел в коментах: сенкс Dmitry Yashin.

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

    null-то всё равно надо писать. а если он там не один?

    в общем, если бы всё было так просто, Максим не стал бы заморачиваться ;)

  18. 2011-04-20 в 14:21:04 | Жутик#18

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

    Пятёрка за нестандартность мышления.

    В MaxSite CMS это где-то применяется/будет применяться?

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

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

Используйте нормальные имена

Имя и сайт используются только при регистрации

Зарегистрируйтесь, чтобы получать уведомления о новых комментариях по email.

Авторизация Войти через loginza

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

РЕКЛАМА Установка смесителей смесители сантехника раковины. копии швейцарских часов