PHP: Определение и вызов функции. Функции в PHP Пример написания функции в php

PHP: Определение и вызов функции. Функции в PHP Пример написания функции в php

Итак, что такое функция (function)на PHP ?

Функция (function)- это мини-программа, которая выполняет какие-то полезные действия и выдает готовый результат.
Давайте посмотрим на схемку:

Попробуем по готовому шаблону функции написать мини программу.
Готовый шаблон функции:

Припустим, нам нужно написать функцию, которая сможет подсчитать сумму чисел 5 и 2 . Смотрим на шаблон и пишем:

Разберем код .
function suma() - это функция с именем suma ;
echo 5 + 2; - в теле функции мы указали, что числа 5 и 2 нужно сложить вместе (5 + 2) ;
suma(); - вызываем функцию. Вызов функции означает ее выполнение. То есть, задачка 5 + 2 должна быть выполнена и дать результат 7 .

Теперь попробуем рассмотреть функции поэтапно.

Этапы создания функции на PHP

Этап I . Создание функции
Вспомните готовый шаблон функции:

Вот таким способом создается функция на PHP.
Давайте в теле функции напишем текст «Я рад видеть вас на блоге сайт ».
Только не забудьте: текст пишем через .

"; } ?>

Теперь нужно вызвать функцию «сайт() ».

Этап II . Вызов готовой функции на PHP
Функция создана и теперь она должна быть выполнена. Для выполнения и вывода функции достаточно указать «имя функции(); »

сайт();

Это будет выглядеть вот так:

функции PHP - сайт "; } сайт(); ?>

Можно это сделать и так:

функции PHP - сайт "; } ?> Куча текста….. Куча текста…..

Введите в браузере адрес:

Результат:

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

Все примеры с функциями выше были без аргументов. Что такое аргумент я вам объясню на коде:

Итак, я создал функцию с именем «сайт ». В параметрах (там, где скобки) прописал через запятую две переменные $a и $b .

Function сайт ($a , $b )

$a и $b – это и есть два аргумента.
echo "$a + $b = "; – здесь я вывел на монитор текст. Результат: 5 + 5 =
echo $a + $b; – здесь я указал функции, что переменную $a и $b нужно сложить вместе.
сайт (15, 5); – вызвал функцию. Внимание: в скобках я указал два аргумента (15, 5) , которые ждет переменная $a и $b . Переменная $a получит первый аргумент – 15 , $b – второй 5 .

Для тех, кто не понял, куда подставляется аргумент и в какой очередности, вот схема:

Итак, готовый код:

Сохраните как «function.php » в папку «test-1 » локального сервера (см. урок 1).

Введите в браузере адрес:

https://localhost/test-1/function.php

Результат:

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

Функция под именем «сайт » получит в переменную $link аргумент https://сайт/ , а переменная $title получит текст ссылки – «Блог сайт – создание сайта! »

Готовый код:

Сохраните как «function.php » в папку «test-1 » локального сервера (см. урок 1).

Введите в браузере адрес.

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

Пример #1 Работа с функциями посредством переменных

function foo () {
echo "В foo()
\n" ;
}

function bar ($arg = "" )
{
echo "В bar(); аргумент был " $arg ".
\n" ;
}

// Функция-обертка для echo
function echoit ($string )
{
echo $string ;
}

$func = "foo" ;
$func (); // Вызывает функцию foo()

$func = "bar" ;
$func ("test" ); // Вызывает функцию bar()

$func = "echoit" ;
$func ("test" ); // Вызывает функцию echoit()
?>

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

Пример #2 Обращение к методам класса посредством переменных

class Foo
{
function Variable ()
{
$name = "Bar" ;
$this -> $name (); // Вызываем метод Bar()
}

Function Bar ()
{
echo "Это Bar" ;
}
}

$foo = new Foo ();
$funcname = "Variable" ;
$foo -> $funcname (); // Обращаемся к $foo->Variable()

?>

При вызове статических методов вызов функции "сильнее", чем оператор доступа к статическому свойству:

Пример #3 Пример вызова переменного метода со статическим свойством

class Foo
{
static $variable = "статическое свойство" ;
static function Variable ()
{
echo "Вызов метода Variable" ;
}
}

echo Foo :: $variable ; // Это выведет "статическое свойство". Переменная $variable будет разрешена в нужной области видимости.
$variable = "Variable" ;
Foo :: $variable (); // Это вызовет $foo->Variable(), прочитав $variable из этой области видимости.

?>

С версии PHP 5.4.0, можно вызывать callable -функцию, помещенную в переменную.

Пример #4 Сallable-фукнции

class Foo
{
static function bar ()
{
echo "bar\n" ;
}
function baz ()
{
echo "baz\n" ;
}
}

$func = array("Foo" , "bar" );
$func (); // выведет "bar"
$func = array(new Foo , "baz" );
$func (); // выведет "baz"
$func = "Foo::bar" ;
$func (); // выведет "bar" в PHP 7.0.0 и выше; в предыдущих версиях это приведет к фатальной ошибке
?>

Смотрите также is_callable() , call_user_func() , Переменные переменные и function_exists() .

Список изменений

8 years ago

$ wget
$ grep -l "\$\.\.\." php-chunked-xhtml/function.*.html

List of functions that accept variable arguments.
array_diff_assoc ()
array_diff_key ()
array_diff_uassoc ()
array()
array_intersect_ukey ()
array_map ()
array_merge ()
array_merge_recursive ()
array_multisort ()
array_push ()
array_replace ()
array_replace_recursive ()
array_unshift ()
call_user_func ()
call_user_method ()
compact ()
dba_open ()
dba_popen ()
echo()
forward_static_call ()
fprintf ()
fscanf ()
httprequestpool_construct ()
ibase_execute ()
ibase_set_event_handler ()
ibase_wait_event ()
isset()
list()
maxdb_stmt_bind_param ()
maxdb_stmt_bind_result ()
mb_convert_variables ()
newt_checkbox_tree_add_item ()
newt_grid_h_close_stacked ()
newt_grid_h_stacked ()
newt_grid_v_close_stacked ()
newt_grid_v_stacked ()
newt_win_choice ()
newt_win_entries ()
newt_win_menu ()
newt_win_message ()
newt_win_ternary ()
pack ()
printf ()
register_shutdown_function ()
register_tick_function ()
session_register ()
setlocale ()
sprintf ()
sscanf ()
unset()
var_dump ()
w32api_deftype ()
w32api_init_dtype ()
w32api_invoke_function ()
wddx_add_vars ()
wddx_serialize_vars ()
?>

3 years ago

A small, but helpful note. If you are trying to call a static function from a different namespace, you must use the fully qualified namespace, even if they have the same top level namespace(s). For example if you have the following class to call:

namespace Project \ TestClass ;
class Test {
static function funcToCall () {
return "test" ;
}
}
?>
You must call it as:
namespace Project \ OtherTestClass ;
class OtherTest {
$func = "\Project\TestClass::funcToCall" ;
$func ();
}
}
?>
and not:
class OtherTest {
static function callOtherFunc () {
$func = "TestClass::funcToCall" ;
$func ();
}
}
?>

9 months ago

While the documentation suggests that the use of a constant is similar to the use of a variable, there is an exception regarding variable functions. You cannot use a constant as the function name to call a variable function.

const DEBUGME ="func";
function func($s) { echo $s. "\n"; }

DEBUGME("abc"); // results in a syntax error

$call = DEBUGME;
$call("abc"); // does the job

But you can use a constant as an argument to a function. Here"s a simple workaround when you need to call a variable constant function:

function dynamic($what, $with)
{
$what($with);
}
dynamic(DEBUGME, "abc");

This makes sense to me to hide API"s and/or long (complicated) static calls.
Enjoy!

13 years ago

If you want to call a static function (PHP5) in a variable method:

Make an array of two entries where the 0th entry is the name of the class to be invoked ("self" and "parent" work as well) and the 1st entry is the name of the function. Basically, a "callback" variable is either a string (the name of the function) or an array (0 => "className", 1 => "functionName").

Then, to call that function, you can use either call_user_func() or call_user_func_array(). Examples:

class A {

Protected $a ;
protected $c ;

Function __construct () {
$this -> a = array("self" , "a" );
$this -> c = array("self" , "c" );
}

Static function a ($name , & $value ) {
echo $name , " => " , $value ++, "\n" ;
}

Function b ($name , & $value ) {
call_user_func_array ($this -> a , array($name , & $value ));
}

Static function c ($str ) {
echo $str , "\n" ;
}

Function d () {
call_user_func_array ($this -> c , func_get_args ());
}

Function e () {
call_user_func ($this -> c , func_get_arg (0 ));
}

class B extends A {

Function __construct () {
$this -> a = array("parent" , "a" );
$this -> c = array("self" , "c" );
}

Static function c () {
print_r (func_get_args ());
}

Function d () {
call_user_func_array ($this -> c , func_get_args ());
}

Function e () {
call_user_func ($this -> c , func_get_args ());
}

$a =& new A ;
$b =& new B ;
$i = 0 ;

A :: a ("index" , $i );
$a -> b ("index" , $i );

$a -> c ("string" );
$a -> d ("string" );
$a -> e ("string" );

# etc.
?>

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

Вы уже видели много функций, таких как fopen() и fread() и т. Д. Это встроенные функции, но PHP дает вам возможность создавать свои собственные.

Есть две части, которые должны быть понятны вам -

  • Создание функции PHP
  • Вызов функции PHP

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

Создание функции PHP

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

Обратите внимание, что при создании функции его имя должно начинаться с функции ключевого слова, и весь код PHP должен быть помещен внутри скобок {и}, как показано в следующем примере ниже -

Вы действительно хороший человек, хорошо проводите время!

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

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

На этом отобразится следующий результат -

Сумма двух чисел: 30

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

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

В следующем примере изображены оба случая.

На этом отобразится следующий результат -

Исходное значение - 10
Исходное значение - 16

Функции PHP, возвращающие значение

Функция может возвращать значение с помощью оператора return в сочетании со значением или объектом. return останавливает выполнение функции и отправляет значение обратно вызывающему коду.

Вы можете вернуть более одного значения из функции с использованием возвращаемого массива (1,2,3,4) .

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

На этом отобразится следующий результат -

Возвращаемое значение из функции: 30

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

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

Чтобы писать на языке 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

Последнее обновление: 1.11.2015

Функции представляют собой набор инструкций, выполняющих определенное действие.

Синтаксис определения функции:

Function имя_функции([параметр [, ...]]) { // Инструкции }

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

После имени функции в скобках идет перечисление параметров. Даже если параметров у функции нет, то просто идут пустые скобки. Затем в фигурных скобках идет тело функции, содержащее набор инструкций.

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

Function display() { echo "вызов функции display()"; }

Данная функция не имеет параметров и все, что она делает - это вывод на страницу некоторого сообщения.

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

Возвращение значения и оператор return

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

Функция get() возвращает число, представляющее сумму квадратов от 1 до 9. Это число хранится в переменной $result . Благодаря оператору return мы можем присвоить значение, возвращаемое функцией get, какой-нибудь переменной: $a = get(); .

Использование параметров

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

Так как теперь функция $get использует параметры, то мы должны передать при вызове этой функции на место параметров некоторые значения. Если при вызове мы укажем значения не для всех параметров, то это будет ошибка, например: $a = get(1); .

Но мы можем использовать значения по умолчанию для параметров. Например:

В этом случае, если мы не укажем значение для второго параметра, то по умолчанию он будет равен 10.

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

В примере выше мы передавали параметры по значению . Но в PHP есть и другая форма передачи параметров - по ссылке . Рассмотрим два этих способа передачи параметров и сравним. Стандартная передача параметра по значению:

\$number равно: $number"; function get($a) { $a*=$a; echo "Квадрат равен: $a"; } ?>

После вызова функции get() значение переменной $number не изменится, так как в эту функцию в качестве параметра мы передаем значение переменной.

\$number равно: $number"; function get(&$a) { $a*=$a; echo "Квадрат равен: $a"; } ?>

При передаче по ссылке перед параметром ставится знак амперсанда: function get(&$a) . Теперь интерпретатор будет передавать не значение переменной, а ссылку на эту переменную в памяти, в итоге, переменная $number после передачи на место параметра &$a также будет изменяться.

просмотров