Внимание! Данная запись отмечена как устаревшая и/или потерявшая актуальность! Возможно автор уже передумал и теперь придерживается другой точки зрения, нежели изложенная в тексте ниже.

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

Дневник / PHPПросмотров: 31647 (279)

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

Комментариев: 18 RSS

2FX Poster05-01-2008 14:34

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

3CTapbIu05-01-2008 14:48

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

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

4FX Poster05-01-2008 14:50

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

5Максим05-01-2008 15:27

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

6FX Poster05-01-2008 15:33

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

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

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

7Tapac05-01-2008 19:00

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

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

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

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

8Артём Курапов05-01-2008 19:03

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

9Коля Дубр05-01-2008 23:37

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

10cryonyx06-01-2008 03:39

:shock:

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

11Максим06-01-2008 09:25

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

12Anton06-01-2008 10:27

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

13CTapbIu06-01-2008 19:49

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

14Dmitry Yashin08-01-2008 13:01

Тем более может возникнуть ситуация, когда указать нужно не все параметры, а скажем только 5-й и 8-й.

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

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

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

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

15Severus13-03-2008 11:56

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

$application->Func1( "some_arg", "some_arg_2", Array( здоровый массив с настройками и параметрами ) );

16Lektor23-06-2008 03:01

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

17Vlad06-05-2010 20:29

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

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

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

18Жутик20-04-2011 12:21

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

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

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

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

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

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

О сайте

Здесь вы получите самую полную информацию о создании сайтов на MaxSite CMS.

Рейтинг@Mail.ru