9 полезных функций PHP и особенностей, которые нужно знать

php функции

От Автора:

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

1. Функции с произвольным количеством параметров

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

Для начала, вот пример исключительно с необязательными параметрами:

// function with 2 optional arguments
function foo($arg1 = '', $arg2 = '') {

	echo "arg1: $arg1\n";
	echo "arg2: $arg2\n";

}

foo('hello','world');
/* prints:
arg1: hello
arg2: world
*/

foo();
/* prints:
arg1:
arg2:
*/

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

// yes, the argument list can be empty
function foo() {

	// returns an array of all passed arguments
	$args = func_get_args();

	foreach ($args as $k => $v) {
		echo "arg".($k+1).": $v\n";
	}

}

foo();
/* prints nothing */

foo('hello');
/* prints
arg1: hello
*/

foo('hello', 'world', 'again');
/* prints
arg1: hello
arg2: world
arg3: again
*/

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

У многих функций PHP длинные и содержательные имена. Однако будет трудно сказать, что делает функция с именем glob(), если вы уже откуда-то не знакомы с этим термином.

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

// get all php files
$files = glob('*.php');

print_r($files);
/* output looks like:
Array
(
    [0] => phptest.php
    [1] => pi.php
    [2] => post_output.php
    [3] => test.php
)
*/

Вы можете задавать несколько видов файлов, как здесь:

// get all php files AND txt files
$files = glob('*.{php,txt}', GLOB_BRACE);

print_r($files);
/* output looks like:
Array
(
    [0] => phptest.php
    [1] => pi.php
    [2] => post_output.php
    [3] => test.php
    [4] => log.txt
    [5] => test.txt
)
*/

Обратите внимание, что файлы в действительности будут возвращаться с путями, зависящими от вашего запроса:

$files = glob('../images/a*.jpg');

print_r($files);
/* output looks like:
Array
(
    [0] => ../images/apple.jpg
    [1] => ../images/art.jpg
)
*/

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

$files = glob('../images/a*.jpg');

// applies the function to each array element
$files = array_map('realpath',$files);

print_r($files);
/* output looks like:
Array
(
    [0] => C:\wamp\www\images\apple.jpg
    [1] => C:\wamp\www\images\art.jpg
)
*/

3. Сведения об использовании памяти

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

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

echo "Initial: ".memory_get_usage()." bytes \n";
/* prints
Initial: 361400 bytes
*/

// let's use up some memory
for ($i = 0; $i < 100000; $i++) {
	$array []= md5($i);
}

// let's remove half of the array
for ($i = 0; $i < 100000; $i++) {
	unset($array[$i]);
}

echo "Final: ".memory_get_usage()." bytes \n";
/* prints
Final: 885912 bytes
*/

echo "Peak: ".memory_get_peak_usage()." bytes \n";
/* prints
Peak: 13687072 bytes
*/

4. Сведения об использовании CPU

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

print_r(getrusage());
/* prints
Array
(
    [ru_oublock] => 0
    [ru_inblock] => 0
    [ru_msgsnd] => 2
    [ru_msgrcv] => 3
    [ru_maxrss] => 12692
    [ru_ixrss] => 764
    [ru_idrss] => 3864
    [ru_minflt] => 94
    [ru_majflt] => 0
    [ru_nsignals] => 1
    [ru_nvcsw] => 67
    [ru_nivcsw] => 4
    [ru_nswap] => 0
    [ru_utime.tv_usec] => 0
    [ru_utime.tv_sec] => 0
    [ru_stime.tv_usec] => 6269
    [ru_stime.tv_sec] => 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: время работы в привилегированном режиме (секунды)

Чтобы узнать, какие ресурсы CPU потребляет скрипт, нам нужно посмотреть на значения ‘user time’ (время работы в пользовательском режиме) и ‘system time’ (время работы в привилегированном режиме). По умолчанию величины секунд и миллисекунд представляются раздельно. Таким образом, вы можете разделить значение микросекунд на 1 миллион и добавить к значению секунд, чтобы вычислить общее количество секунд как десятичное число.

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

// sleep for 3 seconds (non-busy)
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);

/* prints
User time: 0.011552
System time: 0
*/

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

Вот другой пример:

// loop 10 million times (busy)
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);

/* prints
User time: 1.424592
System time: 0.004204
*/

Этот скрипт использовал примерно 1,4 секунды времени CPU, и почти все время в пользовательском режиме, так как системных вызовов не было.

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

$start = microtime(true);
// keep calling microtime for about 3 seconds
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);

/* prints
User time: 1.088171
System time: 1.675315
*/

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

Еще вы можете заметить, что цифры соответствуют 3 секундам неточно. Это потому что на сервере также, возможно, выполнялись и другие процессы, так что скрипт не использовал 100% CPU в течение всех 3 секунд.

5. Предопределенные, или «волшебные» константы

PHP предусматривает полезные «волшебные» константы для выборки текущего номера строки (__LINE__), пути файла (__FILE__), пути каталога (__DIR__), имени функции (__FUNCTION__), имени класса (__CLASS__), имени метода (__METHOD__) и пространства имен (__NAMESPACE__).

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

Когда в дело включаются другие скрипты, хорошая идея — использование константы __FILE__ (или __DIR__ в версии PHP 5.3):

// этот код зависит от пути загруженного скрипт
// и может вызвать проблемы при использовании из других каталогов
require_once('config/database.php');

// а этот код всегда относителен к пути текущего файла
// в независимости откуда он был включен
require_once(dirname(__FILE__) . '/config/database.php');

Использование __LINE__ облегчает отладку программы. Можно отследить номера строк:

// some code
// ...
my_debug("some debug message", __LINE__);
/* prints
Line 4: some debug message
*/

// some more code
// ...
my_debug("another debug message", __LINE__);
/* prints
Line 11: another debug message
*/

function my_debug($msg, $line) {
	echo "Line $line: $msg\n";
}

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

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

// generate unique string
echo md5(time() . mt_rand(1,1000000));

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

// generate unique string
echo uniqid();
/* prints
4bd67c947233e
*/

// generate another unique string
echo uniqid();
/* prints
4bd67c9472340
*/

Можно заметить, что, хотя строки уникальны, они кажутся подобными из-за нескольких первых символов. Это оттого, что сгенерированная строка связана со временем сервера. Прекрасный побочный эффект, так как каждый заново сгенерированный id в дальнейшем следует в алфавитном порядке, так что их можно сортировать.

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

// with prefix
echo uniqid('foo_');
/* prints
foo_4bd67d6cd8b8f
*/

// with more entropy
echo uniqid('',true);
/* prints
4bd67d6cd8b926.12135106
*/

// both
echo uniqid('bar_',true);
/* prints
bar_4bd67da367b650.43684647
*/

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

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

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

Есть два популярных метода сериализации переменных. В этом примере употребляются serialize() и unserialize():

// a complex array
$myvar = array(
	'hello',
	42,
	array(1,'two'),
	'apple'
);

// convert to a string
$string = serialize($myvar);

echo $string;
/* prints
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";}
*/

// you can reproduce the original variable
$newvar = unserialize($string);

print_r($newvar);
/* prints
Array
(
    [0] => hello
    [1] => 42
    [2] => Array
        (
            [0] => 1
            [1] => two
        )

    [3] => apple
)
*/

Это стандартный метод сериализации PHP. Однако с тех пор, как в последние годы стал так популярен JSON, в PHP 5.2 решили добавить поддержку и для него. Теперь, кроме прочего, можно использовать функции json_encode() и json_decode():

// a complex array
$myvar = array(
	'hello',
	42,
	array(1,'two'),
	'apple'
);

// convert to a string
$string = json_encode($myvar);

echo $string;
/* prints
["hello",42,[1,"two"],"apple"]
*/

// you can reproduce the original variable
$newvar = json_decode($string);

print_r($newvar);
/* prints
Array
(
    [0] => hello
    [1] => 42
    [2] => Array
        (
            [0] => 1
            [1] => two
        )

    [3] => 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";
/* prints
Original size: 800
*/

echo "Compressed size: ". strlen($compressed)."\n";
/* prints
Compressed size: 418
*/

// getting it back
$original = gzuncompress($compressed);

Мы в состоянии достичь уменьшения размера почти на 50%. Функции gzencode() и gzdecode() выдают схожие результаты, используя другим алгоритмом сжатия.

9. Функция Register Shutdown

Функция с названием register_shutdown_function() позволит вам выполнить какой-нибудь код прямо перед окончанием работы скрипта.

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

// capture the start time
$start_time = microtime(true);

// do some stuff
// ...

// display how long the script took
echo "execution took: ".
		(microtime(true) - $start_time).
		" seconds.";

Сначала это может показаться тривиальным. Вы просто добавляете код в самый конец скрипта, и он выполняется до окончания работы скрипта. Однако, если вы вызовете функцию exit(), этот код никогда не выполнится. Также, если возникнет фатальная ошибка (fatal error) или если скрипт будет завершен пользователем (нажатием клавиши Stop в браузере), он снова может не выполниться.

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

$start_time = microtime(true);

register_shutdown_function('my_shutdown');

// do some stuff
// ...

function my_shutdown() {
	global $start_time;

	echo "execution took: ".
			(microtime(true) - $start_time).
			" seconds.";
}

Заключение

Вы знаете другие особенности PHP, которые широко не известны, но могут быть очень полезны? Пожалуйста, поделитесь с нами в комментариях. И спасибо за прочтение!

Автор: Burak Guzel

Перевод и редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.

Источник: http://net.tutsplus.com

E-mail: contact@webformyself.com

Проект webformyself.com — Как создать свой сайт. Основы самостоятельного сайтостроения

P.S. Хотите опубликовать интересный тематический материал и заработать? Если ответ «Да», то жмите сюда.

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки: , ,

Комментарии Вконтакте:

Комментарии Facebook:

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

  1. Алексей Павлов

    Вопрос по поводу функции getrusage().
    Как соотносится с приведенными данными ограничение на выполнение скрипта set_time_limit()?
    Если установлено ограничение, скажем, 30 сек, то по какому значению будет отсчитываться это время — по UserTime, по SystemTime или по microtime(true) — $start_time?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree