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

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

Создаем свою первую php функцию

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

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

Вот как выглядит объявление функции myCompanyName:

Примечание : Название функции может начинаться со знака «_», но не с цифры!
Это лишь каркас нашей функции, а внутри него мы можем поместить любой код, который захотим. При вызове функции он будет выполняться. Видите в фигурных скобках в приведенном выше примере «{}»? Эти скобки определяют, где должен быть наш код функции. Открывающая фигурная скобка «{» говорит PHP, что код функции начинается, а закрывающая фигурная «}» говорит PHP, что наша функция окончена!

Давайте добавим в нее что-то простенькое, например .

Вот и все, довольно просто, правда? Теперь научимся вызывать нашу функцию.

Вызов готовой функции php

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

!
"; myCompanyName(); echo "Рад вас видеть!
";

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

  • Всегда начинайте ваши функции с ключевым словом function.
  • Помните, что ваш код функции должны быть между «{» и «}».
  • Когда вы вызываете функцию, убедитесь, что пишете ее имя правильно.

Функции с параметрами

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

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

"; } ?>

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

Возвращение значения функцией php

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

Как она возвращает значение? Лучше всего разобраться на примере. Объявим функцию с параметрами, а затем присвоим результат некоторой переменной, вот так:

"; $myNumber = mySum(3, 4); // Сохраняем результат вызова функции mySum в переменную $myNumber echo "После вызова функции, myNumber = " . $myNumber ."
"; ?>

Чтобы присвоить функции значение — в нее добавляется оператор return, видите его? Результат сложения двух чисел хранится в переменной $total, а с помощью return $total это значение передается самой функции. Затем мы просто присваиваем его переменной $myNumber после вызова функции mySum с двумя параметрами 3 и 4 (это числа которые следует сложить).

Практикуйтесь, разбирайтесь и у вас все получится!

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

Синтаксис функций в php

В каждом языке программирования работа с функциями имеет свои «тонкости ». Рассмотрим их особенности в php :

  • Определение функции выглядит следующим образом:

function имя_функции (параметры) { //тело функции }

Параметры могут быть пустыми. Имя указывается после обязательного слова function . При этом имена функций являются независимыми от регистра.

Это значит, что при объявлении function Main() и function main() подразумевается одна и та же функция. А при вызове одной из них интерпретатор выдаст сообщение об ошибке:

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

function MyFunc () { $a=1; return $a; } echo MyFunc ();

В результате будет возвращена 1.

Множественную передачу значений можно осуществить при использовании в php массива в функции.
Пример:

function asq($a){ $x=$a*$a; $y=$a*$a*$a; return array($x,$y); } list($kvd,$kub)=$asq(15);

В теле функции задаются значения переменным x и y . Затем с помощью встроенной функции array() они записываются в массив.

Значение элементам массива задается при вызове функции с помощь list() .

  • Вызов функции php имеет синтаксис:

имя_функции(аргумент 1, аргумент 2…аргумент n);

function MyFunc ($a,$b,$c=0){ $a=$b+$c; return $a; } echo MyFunc (0,1,2);

Функция вернет 3.

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

Анонимные функции в php

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

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


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

Рассмотрим на примерах:

$func1 = function(){ return 1; }; $x = $func1(); echo $x();

$input = array(1, 2, 3, 4, 5); $output = array_filter($input, function ($v) { return $v > 2; });

В примере автономная функция function ($v) { return $v > 2; } вызывается напрямую в месте определения. Она передается в качестве второго аргумента стандартной функции array_filter() .

Функция mail()

Набор стандартных (встроенных ) функций в php довольно широк. Многие из них реализуют основные возможности веб-сферы.

Одной из таких является функция mail() . Она отправляет сообщение на указанный почтовый ящик. Ее синтаксис:

Описание принимаемых параметров:

  • to –адрес получателя письма. Должен соответствовать стандарту [email protected] ;
  • subject – тема письма;
  • message – отправляемое сообщение. При этом каждая строка сообщения должна вмещать в себя не более 70 символов. Строки разделяются символом перевода строки (n ).

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

$text = str_replace("n.", "n..", $text);

Необязательные параметры функции mail() :

  • additional_headers – вставляется в конце заголовков отправляемого письма. Используется для добавления заголовков.

Пример отправки простого письма:

$message = "Line 1nLine 2nLine 3"; $message = wordwrap($message, 70); mail("[email protected]", "My Subject", $message);

А вот пример полностью рабочей формы для отправки сообщений:

Вот ее код php :

"; $message .= "E-mail пользователя: " . $_POST["user_email"] . "
"; $message .= "Текст письма: " . $_POST["text_comment"]; send_mail($message); // отправим письмо // выведем сообщение об успехе $msg_box = "Сообщение успешно отправлено!"; }else{ // если были ошибки, то выводим их $msg_box = ""; foreach($errors as $one_error){ $msg_box .= "$one_error
"; } } } // функция отправки письма function send_mail($message){ // почта, на которую придет письмо $mail_to = "[email protected]"; // тема письма $subject = "Письмо с обратной связи"; // заголовок письма $headers= "MIME-Version: 1.0rn"; $headers .= "Content-type: text/html; charset=utf-8rn"; // кодировка письма $headers .= "From: Тестовое письмо rn"; // от кого письмо // отправляем письмо mail($mail_to, $subject, $message, $headers); }

Код html :

Обратная связь

" method="post" name="frm_feedback">
" />

" />


Несколько основных причин, почему письмо не отправляется:

  • Письмо не содержит дополнительного заголовка From . Он устанавливается с помощью необязательного параметра additional_headers . Также он может быть выключен по умолчанию в конфигурационном файле php.ini . Если заголовок отсутствует в коде, то интерпретатор выдаст следующее сообщение:

Warning: mail(): "sendmail_from" not set in php.ini or custom "From:" header missing

  • Используйте только LF (n) . Некоторые агенты на основе Unix автоматические заменяют LF на CRLF (rn) ;
  • При реализации функции mail() на Windows адрес получателя не должен быть такого вида: Something [email protected]

Может произойти неправильная интерпретация параметра при передаче его почтовому агенту для отправки.

  • Сбои в отправке писем могут возникнуть при размещении вызова mail() в теле цикла. Функция открывает и закрывает соединение с SMTP -сервером после отправки каждого письма.

Обзор стандартных функций php

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

  • 1) substr() – возвращает часть строки. Синтаксис: string substr(string string, int start[, int length]) , где:
  • string string – заданная строка.
  • int start – задает начало подстроки.
  • int length – количество символов в возвращаемой подстроке.

$string = substr("Hello, world!", 6); echo ($string);

  • 2) strpos() – возвращает позицию подстроки в заданной строке. С помощью необязательного параметра можно задать точку отсчета для поиска. Синтаксис: string strpos(string haystack, string needle[, int offset])

$string = strpos("Hello, world!", "world"); echo($string);

3) strstr() – возвращает подстроку из строки, начиная с указанного символа. Синтаксис: string
strstr(string haystack, string needle)

$url = "http://www.mail.ru"; $www = strstr($url,"m"); echo ($www);


Функции работы с массивами:

1. count() – возвращает количество элементов в массиве. Синтаксис: int count(mixed var)

$a=array("Volvo","Kia","Ford"); echo count($a);

2. reset() – устанавливает указатель массива на первый элемент, возвращает его значение.
Синтаксис: reset(array array)
Пример:

$b=array("1","2","3"); echo reset($b)."
";

3. sort() – сортирует массив по возрастанию. Функция воспринимает любой массив как список. Синтаксис: void sort(array array [, int sort_flags])

$fruits = array("lemon", "orange", "banana", "apple"); sort($fruits); foreach ($fruits as $key => $val) { echo "fruits[" . $key . "] = " . $val . "n"; }

В языке PHP существует много функций для работы с датой и временем. Но функция date () в php является основной. Она возвращает строку, отформатированную согласно установленному шаблону format . Временная метка устанавливается аргументом timestamp . Ее синтаксис: string date (string $format [, int $timestamp = time() ])

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

Давайте с Вами напишем пример элементарной функции, которая просто печатает "Hello World ":

function printHello() {
echo "Hello World";
}
printHello();
?>

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

function printHello($str) {
echo $str;
}
printHello("Hello World!!!");
?>

Здесь мы создали функцию, но уже с параметром. И дальше значение этого параметра мы и выводим через echo . За пределами функции printHello() мы её вызываем и передаём строку "Hello World!!! ". Как видите, и тут всё просто.

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

function printArray ($arr, $bool = false) {
$str = "";
for ($i = 0; $i < count($arr); $i++)
$str .= "Элемент $i = $arr[$i]
";
if ($bool) return $str;
echo $str;
}
$a = array(15, 12, 13, 14);
printArray($a);
$str = printArray($a, true);
echo $str;
?>

Здесь смысл следующий: задача функции - формировать из массива строку, то есть просто превратить массив в строковый тип. В данном примере, самое интересное - это параметр bool , который имеет значение по умолчанию. Если она false (как по умолчанию, то есть если не указывали иного значения), то строка сразу печатается в браузере, а если передали true (как при втором вызове функции), то строка возвращается (return $str ) функцией. Вот такой простой пример на создание функций с параметрами по умолчанию .

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

1. Создание функций с переменным числом аргументов

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

Но для начала, вспомним как мы создаём функции обычным образом:

// функция с двумя необязательными параметрами function foo($arg1 = "", $arg2 = "") { echo "arg1: $arg1\n"; echo "arg2: $arg2\n"; } foo("hello","world"); /* выведет: arg1: hello arg2: world */ foo(); /* выведет: arg1: arg2: */

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

// не указываем аргументы function foo() { // возвращает массив, переданных аргументов $args = func_get_args(); foreach ($args as $k => $v) { echo "arg".($k+1).": $v\n"; } } foo(); /* ничего не выведет */ foo("hello"); /* выведет arg1: hello */ foo("hello", "world", "again"); /* выведет arg1: hello arg2: world arg3: again */

2. Используем Glob() для поиска файлов

Часто названия функций говорят сами за себя. Такого нельзя сказать о функции glob() .

Если не вдаваться в подробности, её функциональность схожа с методом scandir() . Она позволяет найти необходимый файл по шаблону:

// найти все php файлы $files = glob("*.php"); print_r($files); /* выведет: Array ( => phptest.php => pi.php => post_output.php => test.php) */

Для нахождения файлов нескольких типов надо писать так:

// найти все php и txt файлы $files = glob("*.{php,txt}", GLOB_BRACE); print_r($files); /* на выходе: Array ( => phptest.php => pi.php => post_output.php => test.php => log.txt => test.txt) */

Так же можно в шаблоне указать путь:

$files = glob("../images/a*.jpg"); print_r($files); /* на выходе: Array ( => ../images/apple.jpg => ../images/art.jpg) */

Для того чтобы получить полный путь к документу используйте метод realpath() :

$files = glob("../images/a*.jpg"); // Применить функцию "realpath" к каждому элементу массива $files = array_map("realpath",$files); print_r($files); /* выведет: Array ( => C:\wamp\www\images\apple.jpg => C:\wamp\www\images\art.jpg) */

3. Информация об используемой памяти

Если вы будете отслеживать количество памяти, которое съедается на работу ваших скриптов то, наверное, чаще будете их оптимизировать.

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

Echo "Initial: ".memory_get_usage()." bytes \n"; /* Initial: 361400 bytes */ // дадим небольшую нагрузку for ($i = 0; $i < 100000; $i++) { $array = md5($i); } // и ещё for ($i = 0; $i < 100000; $i++) { unset($array[$i]); } echo "Final: ".memory_get_usage()." bytes \n"; /* Final: 885912 bytes */ echo "Peak: ".memory_get_peak_usage()." bytes \n"; /* Peak: 13687072 bytes */

4. Информация о процессоре

Для этого необходимо использовать метод getrusage() . Но учтите, что на Windows эта функция работать не будет.

Print_r(getrusage()); /* prints Array ( => 0 => 0 => 2 => 3 => 12692 => 764 => 3864 => 94 => 0 => 1 => 67 => 4 => 0 => 0 => 0 => 6269 => 0) */

Картина, изложенная выше, будет понятно тем, у кого есть опыт в системном администрировании. Для всех остальных предлагаем расшифровку:

  • ru_oublock: количество операций блочной записи
  • ru_inblock: количество операций блочного чтения
  • ru_msgsnd: количество отправленных сообщений
  • ru_msgrcv: количество принятых сообщений
  • ru_maxrss: максимальный размер невыгружаемого набора
  • ru_ixrss: общий объем разделяемой памяти
  • ru_idrss: общий объем неразделяемых данных
  • ru_minflt: количество используемых страниц памяти
  • ru_majflt: количество ошибок отсутствия страниц
  • ru_nsignals: количество принятых сигналов
  • ru_nvcsw: количество переключений контекста процессом
  • ru_nivcsw: количество принудительных переключений контекста
  • ru_nswap: количество обращений к диску при подкачке страниц
  • ru_utime.tv_usec: время работы в пользовательском режиме (микросекунды)
  • ru_utime.tv_sec: время работы в пользовательском режиме (секунды)
  • ru_stime.tv_usec: время работы в привилегированном режиме (микросекунды)
  • ru_stime.tv_sec: время работы в привилегированном режиме (секунды)

Для того чтобы узнать какие ресурсы вашего процессора используются скриптом, вам необходимо значение ‘user time’ (время работы в пользовательском режиме) и ’system time’ (время работы в привилегированном режиме). Вы можете получить результат как в секундах, так и в микросекундах. Для того чтобы превратить общее количество секунд в десятичное число, вам необходимо разделить значение микросекунд на 1 миллион и добавить к значению секунд.

Запутанно как-то. Вот пример:

// отдыхаем 3 секунды sleep(3); $data = getrusage(); echo "User time: ". ($data["ru_utime.tv_sec"] + $data["ru_utime.tv_usec"] / 1000000); echo "System time: ". ($data["ru_stime.tv_sec"] + $data["ru_stime.tv_usec"] / 1000000); /* выводит User time: 0.011552 System time: 0 */

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

Вот ещё пример:

// пройтись 10 миллионов раз for($i=0;$i<10000000;$i++) { } $data = getrusage(); echo "User time: ". ($data["ru_utime.tv_sec"] + $data["ru_utime.tv_usec"] / 1000000); echo "System time: ". ($data["ru_stime.tv_sec"] + $data["ru_stime.tv_usec"] / 1000000); /* выводит User time: 1.424592 System time: 0.004204 */

Работа скрипта заняла 1.4 секунды процессорного времени. В данном случае, время системных вызовов вообще низкое.

Время работы в привилегированном режиме (System Time) - это время, которое процессор затрачивает на выполнение системных запросов к ядру от имени программы. Пример:

$start = microtime(true); // вызываем microtime каждые 3 секунды while(microtime(true) - $start < 3) { } $data = getrusage(); echo "User time: ". ($data["ru_utime.tv_sec"] + $data["ru_utime.tv_usec"] / 1000000); echo "System time: ". ($data["ru_stime.tv_sec"] + $data["ru_stime.tv_usec"] / 1000000); /* выводит User time: 1.088171 System time: 1.675315 */

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

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

5. Магические константы

В PHP существует множество магических констант, таких как номер текущей строки (__LINE__), путь к файлу (__FILE__), путь к каталогу (__DIR__), имя функции (__FUNCTION__), имя класса (__CLASS__), имя метода (__METHOD__) и пространства имён (__NAMESPACE__).

Все мы их рассматривать не будем. Посмотрим только лишь парочку:

// этот скрипт зависит от текущего расположения файла и // может вызвать проблемы, если его использовать из разных дирректорий require_once("config/database.php"); // этот скрипт не вызовет проблем require_once(dirname(__FILE__) . "/config/database.php");

Используйте __LINE__ при отладке скриптов:

// код // ... my_debug("some debug message", __LINE__); /* выведет Line 4: some debug message */ // ещё код // ... my_debug("another debug message", __LINE__); /* выведет Line 11: another debug message */ function my_debug($msg, $line) { echo "Line $line: $msg\n"; }

6. Генерирование уникальных ID

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

// генерируем случайную строку echo md5(time() . mt_rand(1,1000000));

Но на самом деле для этих целей в PHP есть специальная функция uniqid()

// генерируем случайную строку echo uniqid(); /* выведет 4bd67c947233e */ // ещё разок echo uniqid(); /* выведет 4bd67c9472340 */

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

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

// с префиксом echo uniqid("foo_"); /* выведет foo_4bd67d6cd8b8f */ // со вторым параметром echo uniqid("",true); /* выведет 4bd67d6cd8b926.12135106 */ // оба echo uniqid("bar_",true); /* выведет bar_4bd67da367b650.43684647 */

Этот метод генерирует строки размером меньше, чем md5, тем самым вы сможете сэкономить место.

7. Сериализация

Вам когда-нибудь приходилось хранить комплексные данные в базе или в файле? Для того чтобы сконвертировать объект в строку в PHP предусмотрена специальная функция.

Вообще говоря, этих методов 2: serialize() и unserialize()

// сложный массив $myvar = array("hello", 42, array(1,"two"), "apple"); // конвертируем в строку $string = serialize($myvar); echo $string; /* выведет a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";} */ // получаем исходное значение $newvar = unserialize($string); print_r($newvar); /* выведет Array ( => hello => 42 => Array ( => 1 => two) => apple) */

Вот так вот работают эти функции. Однако из-за бурного роста популярности JSON, в PHP 5.2 были добавлены 2 метода json_encode() и json_decode(). Их работа схожа с serialize():

// сложные массив $myvar = array("hello", 42, array(1,"two"), "apple"); // конвертируем в строку $string = json_encode($myvar); echo $string; /* выведет ["hello",42,,"apple"] */ // восстанавливаем исходное значение $newvar = json_decode($string); print_r($newvar); /* prints Array ( => hello => 42 => Array ( => 1 => two) => apple) */

Этот вариант более компактный и совместимый с другими языками, такими как JavaScript. Однако при работе с очень навороченными объектами может возникнуть потеря данных.

8. Сжатие строк

Кода мы говорим о сжатии, то на ум сразу же приходят архивные файлы в формате ZIP. PHP предоставляет возможность сжатия длинных строк без всяких файлов.

В следующем примере продемонстрируем работу функций gzcompress() и gzuncompress() :

$string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut elit id mi ultricies adipiscing. Nulla facilisi. Praesent pulvinar, sapien vel feugiat vestibulum, nulla dui pretium orci, non ultricies elit lacus quis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam pretium ullamcorper urna quis iaculis. Etiam ac massa sed turpis tempor luctus. Curabitur sed nibh eu elit mollis congue. Praesent ipsum diam, consectetur vitae ornare a, aliquam a nunc. In id magna pellentesque tellus posuere adipiscing. Sed non mi metus, at lacinia augue. Sed magna nisi, ornare in mollis in, mollis sed nunc. Etiam at justo in leo congue mollis. Nullam in neque eget metus hendrerit scelerisque eu non enim. Ut malesuada lacus eu nulla bibendum id euismod urna sodales. "; $compressed = gzcompress($string); echo "Original size: ". strlen($string)."\n"; /* выведет Original size: 800 */ echo "Compressed size: ". strlen($compressed)."\n"; /* выведет Compressed size: 418 */ // возвращаем $original = gzuncompress($compressed);

В наших силах уменьшить объём текста на 50%. В этих же целях можно использовать методы gzencode() и gzdecode(), которые используют другой алгоритм сжатия.

9. Выполнить перед завершением

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

Допустим, вы хотите узнать какую-то информацию… Время работы скрипта:

// получаем время начала $start_time = microtime(true); // какие-то операции // ... // выводим время работы echo "execution took: ". (microtime(true) - $start_time). " seconds.";

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

При использовании метода register_shutdown_function() код выполнится в любом случае:

$start_time = microtime(true); register_shutdown_function("my_shutdown"); function my_shutdown() { global $start_time; echo "execution took: ". (microtime(true) - $start_time). " seconds."; }

Вывод

PHP это целая планета, которая не перестаёт нас удивлять своим содержимым. А что думаете вы о данных функциях?

Чтобы писать на языке 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, поэтому регистр букв в именах функций не учитывается.

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

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

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

    Выполняются операторы из тела функции. Если какой-либо из выполняемых операторов представляет собой оператор 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("Первая сделка лучше!

")

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

Код 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("Первая сделка лучше!
"); else print ("Вторая сделка лучше!
")

Функция 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("Первая сделка лучше!
"); else print ("Вторая сделка лучше!
"); } // Вызов функции 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
"; // Рекурсия countdown(--$count); } } countdown(10);

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

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

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

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

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

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

"); } 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("$city это $desc в котором проживает $how_many человек.

"); } // Пустой массив 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 "
10 - 18 + 104 + 2 = ".Sum(10, -18, 104, 2);

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

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

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

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

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

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

Код PHP \$number = $number
"; function add10($a) { $a += 10; echo "Вызов функции add10() ... , результат: $a
\$number

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


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

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

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

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

Код PHP $number = 20; echo "Изначально \$number = $number
"; function add10(&$a ) { $a += 10; echo "Вызов функции add10() ... , результат: $a
"; return $a; } add10($number); echo "Значение \$number после вызова функции 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

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

";

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


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

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

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

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

Код PHP function sum($a, $b) { return $a + $b; } echo sum(10, 15)."
"; // Передаем переменной функцию и вызываем ее $var = "sum"; echo $var(12, 14);

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

Циклы Обработка строк 1 2 3 4 5 6 7 8 9 10