Функции в PHP: что это такое и как они работают
В обычную переменную можно записать число, строку или массив, а затем получить его обратно, обратившись к значению по имени переменной. Функции устроены похожим образом, только вместо строки или числа в ней хранится блок кода, который вызывается при использовании этой «переменной».
Функции помогают повторно использовать код, который нужен во многих местах программы. Если бы функций не существовало, пришлось бы копировать и вставлять фрагмент кода каждый раз, когда он понадобится. А так достаточно написать функцию один раз и вызывать её каждый раз, когда она нужна.
Функции нужны, чтобы не переписывать один и тот же код много раз.
Какие бывают функции
Функции бывают встроенные и пользовательские.
Встроенные функции за вас уже написали создатели языка, и вы можете просто брать их и использовать. В PHP существуют тысячи готовых функций на все случаи жизни — например, sort() для сортировки массивов, print() для вывода строк на экран или функции для работы с базами данных.
С ними программировать будет проще
Пользовательские функции программисты пишут сами — например, чтобы проверить данные пассажира по номеру авиабилета или определить, високосный ли сейчас год. Эти функции, как правило, используются только внутри одного проекта, но бывают исключения — и такие функции выносят в библиотеки.
Аргументы функции и область видимости
Функция — это как бы программа в программе. Это значит, что внутри неё не будут доступны переменные, которые определялись за её пределами. Чтобы передать внутрь функции информацию извне, нужно использовать аргументы функции.
Аргументы функции — это переменные, которые мы передаём в функцию для обработки. Аргументов может быть несколько.
Пример. Мы хотим показывать на сайте, является ли выбранный пользователем год високосным. Напишем функцию, в которую будем передавать год. В результате работы функции мы должны получить true , если год високосный, и false — если нет.
В такой функции нам нужен только один аргумент — номер выбранного года $year .
Функция «не видит» переменные, которые мы создали за её границами. Поэтому переменные в функцию нужно передавать явно — то есть, через аргументы.
Верно и обратное — переменные, определённые внутри функции, не будут доступны извне. Такие переменные называются локальными, потому что они локальны по отношению к функции.
В отличие от аргументов, которых может быть несколько, вернуть во внешний код функция может только одно значение — с помощью инструкции «return» (возврат). Возвращаемое значение называют результатом работы функции.
Как использовать функции
Функция состоит из нескольких частей:
- имени функции,
- аргументов, которые передаются в функцию,
- тела функции,
- оператора return, который отвечает за возврат результата в сценарий.
Аргументов в функции может и не быть — тогда она называется подпрограммой.
То есть объявление функции выглядит примерно так:
Давайте напишем настоящую функцию, которая по номеру года вычисляет, високосный ли он. Так будет проще понять, как устроены функции.
- Функция — это кусочек кода, которому дали имя.
- Функции нужны, чтобы не переписывать один и тот же код много раз.
- В функцию можно передать много переменных, но вернуть только что-то одно.
- Переменные внутри функции недоступны снаружи, внешние переменные нужно передавать через аргументы.
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Функции управления функциями
I’ve developed an easy-to-use hack using these functions to emulate overloaded functions. It’s especially handy for constructors and/or C++ style templating.
Here’s a little example to get you going. This does the trick for most circumstances, and if you need more intelligent parsing, it’s not too hard to implement with regex or a more suitable classification scheme.
N.B. Note the lack of whitespace between variable types in case strings.
function Matrix() $args = func_get_args();
$argmatch = implode(«,», array_map(‘gettype’, $args));
switch( $argmatch ) case ‘integer,integer’:
//initialize m x n matrix
break;
case ‘integer,integer,integer’:
//initialize m x n matrix with constant c
break;
case ‘integer,integer,float’:
//initialize m x n matrix with constant c
break;
case ‘array’:
//initialize from array (2D. )
break;
case ‘array,integer’:
//intialize from array (1D packed with m rows)
break;
default:
//(void) overload?
//error handling?
break;
>
>
PHP is great in how it allows you to send a variable-length argument list to a function by using the func_* functions. However, unfortunately (and this has been brought up numerous time in PHP bug reports/feature requests), it doesn’t support passing arguments by reference which would have greatly simplified processing multiple variables at once by simply doing: somefunction($a, $b, $c) and having them processed, without having to do any additional assignment.
However, I’ve discovered a way to leverage several features of PHP and created a very good example that shows how you can process multiple variables in one fell swoop!
The usage is (with my example function/class):
«list($a, $b, $c, $d, $e) = TextEscape::escape_multi($a, $b, $c, $d, $e);»
If PHP had ACTUALLY been capable of passing variables by reference when using variable-length argument lists, that could have been reduced to:
«TextEscape::escape_multi($a, $b, $c, $d, $e);»
It’s extremely close though, both in simplicity and speed. Just be VERY sure to ALWAYS have the SAME NUMBER AND ORDER of arguments on both sides of that statement.
The use of a static class was just to make the code cleaner and easier to look at. This can be applied to any functions!
Now, onto the code, enjoy the sheer brilliance and enjoy modifying multiple variables at once in just ONE statement! 😉
class TextEscape
public static function escape_string ( $sString )
/* can be anything, using htmlspecialchars() in this example */
return htmlspecialchars ( $sString );
>
public static function escape_multi ()
/* get all variables passed to the function */
$aVariables = func_get_args ();
/* loop through the array, escaping each variable */
foreach ( $aVariables as $iKey => $sValue )
$aVariables [ $iKey ] = TextEscape :: escape_string ( $sValue );
>
/* return the escaped values */
return $aVariables ;
>
>
// Create test variables
$a = «A $b = «B>bar» ;
$c = «C $d = «D>bar» ;
$e = «E
// Process every variable at once,
// we’re exploiting both how list() and
// variable-length argument lists work
// to make the usage this smooth! 😉
list( $a , $b , $c , $d , $e ) = TextEscape :: escape_multi ( $a , $b , $c , $d , $e );
?>
That’s the CLEAN LOOKING version of the code, which illustrates exactly what is HAPPENING.
I also made a speedfreak edition of the function, but didn’t want to post it as the main example since it’s harder to read.
But it’s faster, much faster! It passes by reference where it can and loops in a more efficient way.
Just replace the above function with this one, the outcome is the same but the speed is better:
public static function escape_multi ()
/* get all variables passed to the function */
$aVariables = func_get_args ();
/* loop through the array, escaping each variable */
for ( $i =( count ( $aVariables )- 1 ); $i >= 0 ; $i —) // CHANGED: a more efficient for-loop is used instead of a foreach; and for anyone wondering about the counter declaration, this is a common optimization trick which makes it so that the size of the array only has to be checked ONCE, by initializing the counter to the index of the last element (which is size of array minus 1) and then iterating downwards until we reach 0 (the first element)
TextEscape :: escape_string ( $aVariables [ $i ]); // CHANGED: this has been changed to modify the variable by reference instead
>
/* return the escaped values */
return $aVariables ;
>
>
Xavier’s example is rather complicated, and his task would be much more simply accomplished by using classes. Define a base class to do the basic functions open, dump, and close, and create extension classes to override whatever behavior.
class foo function open() // Default functionality for open()
>
function dump() // Default functionality for dump()
>
function close() // Default functionality for close()
>
>
class bar extends foo function open() // Override functionality of open()
>
// dump() and close() remain as in class foo
>
An interesting way to use functions is by putting other things than PHP in them, i.e. HTML CSS. This can be useful if you will be using a format for many pages. Yes, the include function can be used also, but by defining them in functions can make them more portable in a way and keep you from having to make many include files. You could use include() when one will be putting big portions of PHP, HTML, and/or CSS and will be using them in many pages. Then you could use PHP, HTML, and/or CSS in a function when it is smaller portions of code and only want it to be on a few pages.
I have been using include() for HTML and CSS in my early days of PHP coding, but I will be using functions for that a lot more now.
?>
Now doing:
will return all of the CSS just as if you had wrote it on the actual page, or used include() . The same thing goes for HTML code inside a function. The possibilities are endless.
You can do some kind of overloading functions in PHP using «function_exists».
Let’s suppose you want a script to call plugins that are php files and you want the plugins to «override» behaviours that if not overriden are used by default.
You might for example write a «mySQL table viewer» which displays a table and it «opens a table», «dumps the header», «dumps row-by-row» and then «closes the table».
Let’s suppose you want a plugin for «Stocks» which prints negative stocks in red, so you want to override the «dumping row-by-row» to do that behaviour. Instead you do not want to have all the «default behaviour» repeated in the plugin.
You may then do the following:
1) Define a default plugin (ex: «default.php»
2) Write all your functions in default.php to open, dump and close, but add them a suffix:
3) Call your functions with a wrapper: Insetad of this:
open_table() or open_table_default() write this:
4) Then write a function called plugincall which uses function_exists() to see if you call one or the other function:
if( function_exists( $desired_function_name))
//Call the plugin
//Note the $ before the name
$desired_function_name()
>
else
$desired_function_name = $desired_function_name . «_default»;
if( function_exists($desired_function_name))
//Call the default
//Note the $ before the name
$desired_function_name()
>
else
// Nor the plugin nor the default were defined
>
>
So, now, if the require_once(plugin.php) contains a function called «open_table()», it will be used. Instaed, «open_table_default()» will be used.
It’s not like overloading functions, but it is very useful to write scripts ampliable by other programmers: If they write a function, it is used, if not, the default is used.