Функции в PHP: урок с примерами

Функции в PHP

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

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

Например, нам нужен косинус числа 3.14. Легко! Для этого в PHP есть функция cos.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Есть очень много функций для работы со строками. Например, можно в строке заменить одни символы другими, для этого есть функция str_replace. Например, давайте в строке “abracadabra” заменим все буквы “a” на “o”.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Документация по стандартной библиотеке функций (SPL) доступна на официальном сайте - http://php.net/manual/ru/funcref.php. Большинство из них имеет описание на русском языке. Разумеется, все их запомнить невозможно, однако нужно уметь их находить. И это, как правило, не составляет труда. Например, если вбить в google “заменить символы в строке php” то в выдаче будет ссылка на официальную документацию, там и смотрите.

Поиск функций в PHP

Вообще, гуглить и брать уже готовый код – это хороший подход, который экономит ваше время. В этом нет ничего плохого – скорее всего вы найдёте лучшее решение задачи, чем то, которое бы написали сами. Научитесь на готовых примерах, а со временем запомните наиболее частые подходы для разных случаев. Здесь главное – постоянная практика.

Пользовательские функции: пишем свою первую функцию

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

Код доступен только после покупки курса PHP для начинающих.

У функции обязательно должно быть имя. У всех функций должны быть разные имена и имя вашей функции не может называться так же, как и встроенная в PHP функция. Аргументов может быть сколько угодно, в том числе и 0. Функция может что-то возвращать, для этого перед результатом пишется слово return. После него функция завершает свою работу. А может и не возвращать, а, например, изменять свои аргументы, или выводить информацию на экран. Именуются функции так же, как и переменные - camelCase`ом. Подробнее об этом я писал тут - https://webshake.ru/post/726. Именовать их нужно так же осмысленно – то что функция делает, то и нужно писать в имени.

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

Код доступен только после покупки курса PHP для начинающих.

Окей, функцию написали, теперь можно её вызвать и посмотреть на результат её работы.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

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

Области видимости

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

Код доступен только после покупки курса PHP для начинающих.

Данный код абсолютно рабочий. Здесь переменные $x и $y внутри функции getSum живут сами по себе, а переменные с такими же именами за пределами функции – отдельно, и они ничего друг о друге не знают. При вызове функции значение передаваемого аргумента будет скопировано в локальную переменную, а после выхода из функции это значение будет удалено. То есть здесь при вызове getSum мы просто копируем значения 3 и 5 в локальные переменные $x и $y. С этого момента внутри функции внешние переменные перестают существовать, и она знает только о своих переменных.

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

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

Передача параметров по ссылке

Однако можно передать аргумент по ссылке. Делается это при помощи знака & перед именем аргумента.

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

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

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

Код доступен только после покупки курса PHP для начинающих.

Будет выведено:

Код доступен только после покупки курса PHP для начинающих.

Здесь при вызове функции значение переменной $a было просто скопировано в локальную переменную $x. Внутри функции мы изменили $x, прибавив к нему число 5, а затем работа функции была завершена. Локальная переменная $x перестала существовать, а мы никак не повлияли на переменную $a.

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

Начинаем использовать тайп-хинтинг (type hinting) в PHP 7

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

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

После выполнения мы увидим следующее:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

В этом курсе мы всегда будем использовать указание типов. Это помогает писать более строгий код и позволяет допускать меньше ошибок. Посудите сами – если мы работаем с конкретным типом, мы более уверены в том, как будет работать тот или иной код.

Строгая типизация

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

Код доступен только после покупки курса PHP для начинающих.

Она указывается в начале PHP-файла. Наш код примет следующий вид:

Код доступен только после покупки курса PHP для начинающих.

При этом, если его сейчас запустить, то произойдёт ошибка с типом TypeError.
Ошибка при передаче некорректного типа

Как тут написано, первый аргумент, переданный в getSum() обязан быть типа integer, а передан с типом float. Это и есть строгая типизация в PHP. Использовать её в рамках данного курса мы не будем, да и в профессиональной разработке на PHP этот функционал пока не используют. Но не рассказать о ней я не мог, вполне возможно, что это могут спросить при собеседовании на работу. А сейчас убираем строку _declare(stricttypes=1); из нашего кода и идём дальше.

Функции без аргументов

Как я говорил, функция может вообще не иметь аргументов. Таковой, например, является стандартная функция rand() – она просто возвращает случайное число.

Давайте её попробуем в действии:

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Давайте запустим ещё раз этот же самый код:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Функция внутри функции

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

Код доступен только после покупки курса PHP для начинающих.

Здесь мы использовали функцию cos() из стандартной библиотеки внутри нашей собственной функции. А можно ли вызывать свои же функции из других своих функций? Да легко!

Код доступен только после покупки курса PHP для начинающих.

Здесь мы определили 2 разные функции, и во второй начали использовать первую. Разумеется, эти примеры довольно искусственны. И вы можете подумать, что использовать здесь функции излишне. Ведь можно же просто заменить этот код следующим выражением:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Код данной функции можно упростить, так как если $x не больше $y, то мы в любом случае вернём $y. Поэтому можно убрать блок else:

Код доступен только после покупки курса PHP для начинающих.

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

Давайте передадим первым аргументом большее число:

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Выполнилось первое условие и вызвался return $x. Всё, до return $y дело не дошло.
Упрощение заключается в том, что чем меньше уровней вложенности в коде, тем проще его читать и понимать. Видите, как плотно пересекается весь изученный материал? В данном случае с темой условий в PHP.

Рекурсивные функции

Рекурсия в картинках

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

Например, нам нужно возвести число в степень. Предположим, у нас для этого есть определённая функция. Назовём её power. И пусть она принимает 2 аргумента:

  • число, которое нужно возвести;
  • степень, в которую нужно возвести.

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

Код доступен только после покупки курса PHP для начинающих.

Согласитесь, что power(2, 3) равносильно 2 * power(2, 3 - 1). То есть мы можем умножить число, возводимое в степень, на вызов этой функции, и уменьшить при этом степень на единицу.

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

Получаем, что

Код доступен только после покупки курса PHP для начинающих.

Тогда для возведения 2 в степень 3 получим:

  1. power(2, 3) = 2 * power(2, 2)
  2. power(2, 2) = 2 * power(2, 1)
  3. power(2, 1) = 2

Число в первой степени равно самому этому числу. Здесь нам нужно остановиться.

Давайте реализуем это с помощью кода:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Вывод получится следующим:

Код доступен только после покупки курса PHP для начинающих.

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

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

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

Код доступен только после покупки курса PHP для начинающих.

Как можно догадаться, этот вызов можно представить как

Код доступен только после покупки курса PHP для начинающих.

Или в общем случае

Код доступен только после покупки курса PHP для начинающих.

И так до тех пор, пока $n не станет равен 1.

Давайте реализуем это с помощью рекурсивной функции:

Код доступен только после покупки курса PHP для начинающих.

Запускаем:

Код доступен только после покупки курса PHP для начинающих.

Всё верно! Ну, хватит рекурсии, а то я уже слышу, как у вас закипают мозги.
Очень надеюсь, что вам понравился урок. Если это так – буду рад, если вы поделитесь им в социальных сетях или расскажете друзьям. Это лучшая поддержка проекта. Спасибо тем, кто это делает. Если у вас возникли какие-то вопросы или замечания – напишите об этом в комментариях. А сейчас – делаем домашнее задание, варианты ваших решений можете писать в комментариях, я их проверю и скажу, всё ли правильно. Всем пока!