base08 11

Функции

Чтобы писать на языке PHP программы, представляющие из себя нечто большее, чем просто пара страниц кода, и при этом достаточно удобно организованные, понадобится освоить понятие функции. Функции избавят вас от многократного повторения одних и тех же фрагментов кода в программах. Чтобы получить функцию, нужно назначить фрагменту кода имя, называемое именем функции. После этого данный фрагмент можно исполнять, обращаясь к нему по этому имени.

Основная синтаксическая структура, обеспечивающая использование (или вызов) функции, показана ниже:

function_name(expression_1, expression_2, ... ,expression_n)

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

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

В PHP есть сотни встроенных функций. Все приведенные ниже примеры представляют собой допустимые вызовы встроенных функций PHP:

Вызов встроенных функций PHP
sqrt(9);	// Вызов функции вычисления квадратного корня, который
			// приводит к получению значения 3 
			
rand(10, 10 + 10);		// Возвращает случайное число от 10 до 20

strlen("В этой строке 24 символа");		// Возвращает значение 24

pi();		// Возвращает приближенное значение числа "пи"

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

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

Код PHP
$my_pi = pi();

Еще один вариант состоит в том, что полученный результат может вкладываться в более сложные выражения, как в следующем примере:

Код PHP
$approx = sqrt($approx) * sqrt($approx);

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

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

Определение собственных функций

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

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

Определения функций имеют следующую форму:

function function-name ($argument-1, $argument-2, ..)
{
    statement-1; 
    statement-2;
    ...
}

Это означает, что определения функций состоят из перечисленных ниже четырех частей:

  • Ключевое слово function.

  • Имя, которое должно быть присвоено функции.

  • Список параметров функции — имена переменных с префиксом в виде знака доллара, разделенные запятыми (параметры могут отсутствовать).

  • Тело функции — набор операторов, заключенный в фигурные скобки.

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

Ниже кратко описаны действия, происходящие при вызове определяемой пользователем функции:

  1. Интерпретатор PHP выполняет поиск функции по имени (если функция еще не была определена, то активизируется ошибка).

  2. Интерпретатор PHP подставляет значения параметров вызова (или фактических параметров) вместо переменных в списке параметров определения (или формальных параметров).

  3. Выполняются операторы из тела функции. Если какой-либо из выполняемых операторов представляет собой оператор return, функция останавливается и возвращает требуемое значение. В противном случае функция завершает свою работу после выполнения последнего оператора, не возвращая какого-либо значения.

Пример определения функции

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

Код PHP
$liters_1 = 1.0;
$price_1 = 1.59;
$liters_2 = 1.5;
$price_2 = 2.09;

$per_liter_1 = $price_1 / $liters_1; 
$per_liter_2 = $price_2 / $liters_2; 

if ($per_liter_1 < $per_liter_2)
	print("Первая сделка лучше!<br>");
else
	print ("Вторая сделка лучше!<br>")

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

Код PHP
// Определение функции
function better_deal ($amount_1, $amount_2, $price_1, $price_2)
{
	$per_amount_1 = $price_1 / $amount_1;
	$per_amount_2 = $price_2 / $amount_2;
	
	// Возврат какого-то значения из функции
	return ($per_amount_1 < $per_amount_2);
}

$liters_1 = 1.0;
$price_1 = 1.59;
$liters_2 = 1.5;
$price_2 = 2.09;

// Вызов функции в условном операторе
if (better_deal($liters_1, $liters_2, $price_1, $price_2))
	print("Первая сделка лучше!<br>");
else
	print ("Вторая сделка лучше!<br>")

Функция better_deal представляет в общем виде три строки предыдущего кода, в котором выполняются арифметические операции и операции сравнения. Эта функция принимает в качестве фактических параметров четыре числа и возвращает логическое выражение. Как и в случае любого логического значения, полученное значение можно вложить в ту часть оператора if, в которой выполняется сравнение.

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

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

Код PHP
// Определение функции
function better_deal ($amount_1, $amount_2, $price_1, $price_2)
{
	$per_amount_1 = $price_1 / $amount_1;
	$per_amount_2 = $price_2 / $amount_2;
	
	// Возврат значения из функции не происходит, 
	// но выполняются какие-то действия
	if ($per_amount_1 < $per_amount_2)
		print("Первая сделка лучше!<br>");
	else
		print ("Вторая сделка лучше!<br>");
}

// Вызов функции
better_deal(1.0, 1.5, 1.59, 2.09);

В первой функции используется оператор return для возврата логического результата, применяемого в дальнейшем в проверке оператора if. Во второй функции оператор return отсутствует, поскольку эта функция используется для получения побочного эффекта, который сводится к выводу текста в браузер пользователя. После выполнения последнего оператора данной функции интерпретатор PHP просто переходит к выполнению следующего оператора, который следует за вызовом функции.

Использование меньшего количества параметров

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

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

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

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

  • На время изменить значение степени серьезности ошибок, применительно к которым активизируются сообщения об ошибках в сценарии, с помощью такого оператора:

    Код PHP
    error_reporting(E_ALL - (E_NOTICE + E_WARNING));

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

  • Подавлять ошибки, возникающие при выполнении любого отдельно взятого выражения с помощью операции управления выводом сообщений об ошибках — @. Знак этой операции можно помещать перед любым выражением для подавления сообщений об ошибках, возникающих только при выполнении этого выражения. Например, если во время вызова функции my_function() вырабатывается предупреждающее сообщение, то при вызове @my_function() этого не происходит. Следует отметить, что и данный вариант является опасным, поскольку подавляются сообщения об ошибках всех типов за исключением ошибок интерпретации.

    Код PHP
    ...
    
    // Вызов функции с 2мя параметрами вместо 4
    @better_deal(1.0, 1.5);

Функции и область определения переменных

Про область определения переменных и описание локальных, глобальных, суперглобальных и статических переменных мы говорили в статье "Переменные и константы" ранее. Напомню, любая переменная объявленная внутри функции является локальной, ее можно сделать глобальной за счет использования ключевого слова global. Статические переменные используются внутри функции и сохраняют свое значение между вызовами этой функции. Суперглобальные переменные, представленные в виде массивов, доступны повсеместно.

Область определения функции

Безусловно, правила, касающиеся области определения имен переменных, довольно просты, а правила формирования области определения имен функций еще проще. В версии PHP5 предусмотрено только одно правило: функция должна быть определена один (и только один) раз в том сценарии, в котором она используется. Область определения имен функций неявно рассматривается как глобальная, поэтому функция, определенная в сценарии, доступна в любом месте этого сценария. Но для упрощения изучения кода часто рекомендуется определять функции еще до того, как они будут вызываться в коде.

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

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

Код PHP
// Вызываем функцию sum() до ее определения
echo sum(15, 26);

function sum($a, $b)
{
	return $a + $b;
}

Рекурсия

Некоторые компилируемые языки, такие как C и C++, налагают довольно сложные ограничения по упорядочению кода, касающиеся того, как должны быть заданы определения функций. Дело в том, что для получения информации о том, как компилировать функцию, компилятор должен знать обо всех функциях, вызываемых в данной функции, а это означает, что вызываемые функции должны быть определены в первую очередь. Так что же делать, если две функции вызывают друг друга или одна функция вызывает саму себя?

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

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

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

Код PHP
function countdown($count)
{
	if ($count > 0)
	{
		echo "Число $count<br>";
		
		// Рекурсия
		countdown(--$count);
	}
}

countdown(10);

В результате в окне браузера отображается следующий вывод:

Пример использования рекурсии в PHP

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

В случае приведенной выше функции известно, что выполнение рано или поздно пойдет по базовому пути, поскольку при каждом вызове функции в рекурсивном пути величина обратного подсчета (countdown — отсюда происходит имя самой функции) уменьшается и в конечном итоге должна стать нулевой. Безусловно, при этом предполагается, что входным параметром функции должно быть положительное целое число, а не отрицательное целое число или число с плавающей точкой двойной точности. Следует отметить, что предусмотренная в определении функции проверка условия "больше нуля" служит гарантией от бесконечной рекурсии даже в этих случаях, а проверка условия "не равно нулю" этого не обеспечивает.

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

Код PHP
function countdown_first($count)
{
	if ($count > 0)
	{
		echo "Вызов функции countdown_first: $count<br>";
		
		// Рекурсия на другую функцию
		countdown_second(--$count);
	}
}

function countdown_second($count)
{
	if ($count > 0)
	{
		echo "Вызов функции countdown_second: $count<br>";
		
		// Рекурсия на другую функцию
		countdown_first(--$count);
	}
}

countdown_first(5);

приводит к получению в окне браузера такого вывода:

Взаимно рекурсивные функции

Переменное количество параметров

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

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

  • Использовать параметр в виде массива для хранения значений. За заполнение массива отвечает вызывающий код, а в теле функции должно быть предусмотрено правильное извлечение параметров из массива.

  • Использовать функции с переменным количеством параметров (func_num_args(), func_get_arg() и func_get_args()).

В следующих разделах каждая из этих возможностей рассматривается отдельно.

Параметры, заданные по умолчанию

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

Например, в следующей функции все параметры определены со значениями, заданными по умолчанию:

Код PHP
function tour_guide($city = "Москва", $desc = "большой мегаполис", $how_many = "14 млн.")
{
	print("<b>$city</b> это $desc в котором проживает $how_many человек.<br><br>");
}

tour_guide(); 
tour_guide("Комарово");
tour_guide("Комарово", "маленькая деревня"); 
tour_guide("Комарово", "маленькая деревня", "40");

В окне браузера формируется примерно такой вывод, как показано ниже:

Переменное количество параметров при вызове функции

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

Использование массивов для замены многочисленных параметров

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

Пример применения данного метода представлен в следующем фрагменте кода; кроме того, в нем используется несколько других удобных конструкций, таких как трехместная операция и ассоциативный массив (если вы еще не знакомы с массивами, то рекомендую пока пропустить этот пример):

Код PHP
function tour_brochure($arr) 
{
	$city = isset($arr['city']) ? $arr['city'] : "Москва";
	$desc = isset($arr['desc']) ? $arr['desc'] : "большой мегаполис";
	$how_many = isset($arr['how_many']) ? $arr['how_many'] : "14 млн."; 
	
	print("<b>$city</b> это $desc в котором проживает $how_many человек.<br><br>");
}

// Пустой массив
tour_brochure(array());

// Массив со значениями
$tour = array('city' => 'Комарово', 'desc' => 'маленькая деревня', 'how_many' => 40);
tour_brochure($tour);

В этой функции проверяется наличие в одном входном параметре, представленном в виде массива, трех различных значений, связанных с конкретными строками. С использованием трехместной условной операции (?:) локальным переменным присваивается либо входящее значение (если оно записано в массив), либо заданные по умолчанию фрагменты текста. В этом примере функция tour_brochure вначале вызывается с пустым массивом (который соответствует ситуации с отсутствием фактических параметров), а затем с массивом, в котором хранятся три значения элементов ассоциативного массива.

Использование многочисленных параметров

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

Функция func_num_args()

He принимает параметров и возвращает данные о количестве параметров, переданных в функцию, из которой она вызвана.

Функция func_get_arg()

Принимает целочисленный параметр n и возвращает n-й параметр в функцию, из которой она вызвана. Нумерация параметров начинается с нуля.

Функция func_get_args()

Не принимает параметров и возвращает массив, содержащий все параметры функции, из которой она вызвана, индексы этого массива начинаются с нуля.

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

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

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

Код PHP
function Sum()
{
	$sum = 0;
	for ($i = 0; $i < func_num_args(); $i++)
	{
		$sum += func_get_arg($i);
	}
	return $sum;
}

echo "5 + 120 + 8 = ".Sum(5, 120, 8);
echo "<br>10 - 18 + 104 + 2 = ".Sum(10, -18, 104, 2);

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

Вызов по значению

По умолчанию определяемые пользователем функции в языке PHP действуют на основе вызова по значению. Под этим подразумевается, что при передаче параметров в вызов функции интерпретатор PHP создает копию значений этих параметров для последующей передачи в функцию. Поэтому любые действия, выполняемые в функции, не позволяют изменить значения фактических параметров, присутствующих в вызове функции.

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

Одно из наиболее важных различий между версией PHP5 и предшествующими ей версиями состоит в том, что в ней экземпляры объектов фактически всегда передаются по ссылке, даже при том, что любые параметры другого типа передаются по значению. Это связано с тем, что в версии PHP5 переменные типа "объект" хранят дескрипторы объектов, а не сами объекты, поэтому в режиме передачи параметров по значению фактически копируются сами дескрипторы, а не основополагающие объекты (более подробное обсуждение этого вопроса будет дано в разделе по объектно-ориентированному программированию в PHP).

Ниже приведен пример очень простой функции, увеличивающей переданное ей в параметре число на 10:

Код PHP
$number = 20;
echo "Изначально <b>\$number</b> = $number<br>";
	
function add10($a)
{
	$a += 10;
	echo "Вызов функции add10() ... , результат: $a<br>";
	return $a;
}

add10($number);
echo "Значение <b>\$number</b> после вызова функции add10(): $number";

Как видно из показанного ниже скриншота, вызов функции не повлиял на значение самой переменной $number и она осталась равна 20:

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

Вызов по ссылке

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

Если необходимо определить функцию, действие которой непосредственно распространяется на переданный параметр, достаточно поместить символ амперсанда перед формальным параметром в определении функции, как показано ниже:

Код PHP
$number = 20;
echo "Изначально <b>\$number</b> = $number<br>";
	
function add10(&$a)
{
	$a += 10;
	echo "Вызов функции add10() ... , результат: $a<br>";
	return $a;
}

add10($number);
echo "Значение <b>\$number</b> после вызова функции add10(): $number";

Теперь, после выполнения точно такого же вызова функции переменная $number изменяется и будет равна 30:

Передача параметров функции по ссылке

Дело в том, что в данном случае формальный параметр $a ссылается на переменную $number, поэтому его модификация в функции приводит к изменению переменной $number.

Начиная с версии PHP4 ссылки на переменные могут также использоваться вне вызовов функции. Вообще говоря, в результате присваивания переменной ссылки на переменную (например, &$varname) имена этих двух переменных становятся псевдонимами по отношению друг к другу, а не отдельными переменными с тем же значением. Рассмотрим пример:

Код PHP
$name_1 = "Александр";
$name_2 = "Игорь";

// Передача переменной по значению
$alias_1 = $name_1;

// Передача переменной по ссылке
$alias_2 = &$name_2;

// Изменение переменной $alias_1 не приводит к изменению $name_1
$alias_1 = "Дмитрий";
echo "\$alias_1 = $alias_1, \$name_1 = $name_1<br><br>";

// Изменение переменной $alias_2 приводит к изменению $name_2
// т.к. они взаимосвязаны через ссылку
$alias_2 = "Петр";
echo "\$alias_2 = $alias_2, \$name_2 = $name_2<br><br>";

который приводит к получению в окне браузера следующего вывода:

Передача переменной по ссылке

Переменные в качестве функций

Один из еще более утонченных приемов, которые могут использоваться в языке PHP, состоит в применении переменных в позиции имен функций, определяемых пользователем. Это означает, что вместо ввода в коде литерального имени функции можно ввести переменную со знаком доллара. В таком случае то, какая функция будет фактически вызвана на этапе прогона, зависит от содержимого строки, присвоенной данной переменной.

В определенном смысле это позволяет использовать функции в качестве данных. Подобный прием должен быть знаком квалифицированным программистам, работающим на языке C, и даже начинающим пользователям, которые применяют какую-либо разновидность языка Lisp (например, Scheme или Common Lisp). В частности, два приведенных ниже вызова функции полностью эквивалентны:

Код PHP
function sum($a, $b)
{
	return $a + $b;
}
echo sum(10, 15)."<br>";

// Передаем переменной функцию и вызываем ее
$var = 'sum';
echo $var(12, 14);

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

Циклы
Обработка строк

Комментарии (0)

Результаты поиска по запросу

Система Orphus