9 PHP функций, которые нужно знать всем

Источник: ruseller
Станислав Протасевич

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

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

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

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

01  // функция с двумя необязательными параметрами 
02  function foo($arg1 ''$arg2 '') { 
03      echo "arg1: $arg1\n"; 
04      echo "arg2: $arg2\n"; 
05   
06  } 
07   
08  foo('hello','world'); 
09  /* выведет: 
10  arg1: hello 
11  arg2: world 
12  */ 
13   
14  foo(); 
15  /* выведет: 
16  arg1: 
17  arg2: 
18  */ 

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

01  // не указываем аргументы 
02  function foo() { 
03   
04      // возвращает массив, переданных аргументов 
05      $args = func_get_args(); 
06   
07      foreach ($args as $k => $v) { 
08          echo "arg".($k+1).": $v\n"; 
09      } 
10   
11  } 
12   
13  foo(); 
14  /* ничего не выведет */ 
15   
16  foo('hello'); 
17  /* выведет 
18  arg1: hello 
19  */ 
20   
21  foo('hello''world''again'); 
22  /* выведет 
23  arg1: hello 
24  arg2: world 
25  arg3: again 
26  */ 

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

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

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

01  // найти все php файлы 
02  $files glob('*.php'); 
03   
04  print_r($files); 
05  /* выведет: 
06  Array 
07  ( 
08      [0] => phptest.php 
09      [1] => pi.php 
10      [2] => post_output.php 
11      [3] => test.php 
12  ) 
13  */ 

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

01  // найти все php и txt файлы 
02  $files glob('*.{php,txt}', GLOB_BRACE); 
03   
04  print_r($files); 
05  /* на выходе: 
06  Array 
07  ( 
08      [0] => phptest.php 
09      [1] => pi.php 
10      [2] => post_output.php 
11      [3] => test.php 
12      [4] => log.txt 
13      [5] => test.txt 
14  ) 
15  */ 

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

01  $files glob('../images/a*.jpg'); 
02   
03  print_r($files); 
04  /* на выходе: 
05  Array 
06  ( 
07      [0] => ../images/apple.jpg 
08      [1] => ../images/art.jpg 
09  ) 
10  */ 

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

01  $files glob('../images/a*.jpg'); 
02   
03  // Применить функцию 'realpath' к каждому элементу массива 
04  $files array_map('realpath',$files); 
05   
06  print_r($files); 
07  /* выведет: 
08  Array 
09  ( 
10      [0] => C:\wamp\www\images\apple.jpg 
11      [1] => C:\wamp\www\images\art.jpg 
12  ) 
13  */ 

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

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

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

01  echo "Initial: ".memory_get_usage()." bytes \n"; 
02  /* 
03  Initial: 361400 bytes 
04  */ 
05   
06  // дадим небольшую нагрузку 
07  for ($i = 0; $i < 100000; $i++) { 
08      $array []= md5($i); 
09  } 
10   
11  // и ещё 
12  for ($i = 0; $i < 100000; $i++) { 
13      unset($array[$i]); 
14  } 
15   
16  echo "Final: ".memory_get_usage()." bytes \n"; 
17  /* 
18  Final: 885912 bytes 
19  */ 
20   
21  echo "Peak: ".memory_get_peak_usage()." bytes \n"; 
22  /* 
23  Peak: 13687072 bytes 
24  */ 

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

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

01  print_r(getrusage()); 
02  /* prints 
03  Array 
04  ( 
05      [ru_oublock] => 0 
06      [ru_inblock] => 0 
07      [ru_msgsnd] => 2 
08      [ru_msgrcv] => 3 
09      [ru_maxrss] => 12692 
10      [ru_ixrss] => 764 
11      [ru_idrss] => 3864 
12      [ru_minflt] => 94 
13      [ru_majflt] => 0 
14      [ru_nsignals] => 1 
15      [ru_nvcsw] => 67 
16      [ru_nivcsw] => 4 
17      [ru_nswap] => 0 
18      [ru_utime.tv_usec] => 0 
19      [ru_utime.tv_sec] => 0 
20      [ru_stime.tv_usec] => 6269 
21      [ru_stime.tv_sec] => 0 
22  ) 
23  */ 

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

  • 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 миллион и добавить к значению секунд.

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

01  // отдыхаем 3 секунды 
02  sleep(3); 
03   
04  $data getrusage(); 
05  echo "User time: ". 
06      ($data['ru_utime.tv_sec'] + 
07      $data['ru_utime.tv_usec'] / 1000000); 
08  echo "System time: ". 
09      ($data['ru_stime.tv_sec'] + 
10      $data['ru_stime.tv_usec'] / 1000000); 
11   
12  /* выводит 
13  User time: 0.011552 
14  System time: 0 
15  */ 

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

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

01  // пройтись  10 миллионов раз 
02  for($i=0;$i<10000000;$i++) { 
03   
04  } 
05   
06  $data getrusage(); 
07  echo "User time: ". 
08      ($data['ru_utime.tv_sec'] + 
09      $data['ru_utime.tv_usec'] / 1000000); 
10  echo "System time: ". 
11      ($data['ru_stime.tv_sec'] + 
12      $data['ru_stime.tv_usec'] / 1000000); 
13   
14  /* выводит 
15  User time: 1.424592 
16  System time: 0.004204 
17  */ 

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

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

01  $start = microtime(true); 
02  // вызываем microtime каждые 3 секунды 
03  while(microtime(true) - $start < 3) { 
04   
05  } 
06   
07  $data getrusage(); 
08  echo "User time: ". 
09      ($data['ru_utime.tv_sec'] + 
10      $data['ru_utime.tv_usec'] / 1000000); 
11  echo "System time: ". 
12      ($data['ru_stime.tv_sec'] + 
13      $data['ru_stime.tv_usec'] / 1000000); 
14   
15  /* выводит 
16  User time: 1.088171 
17  System time: 1.675315 
18  */ 

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

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

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

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

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

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

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

01  // код 
02  // ... 
03  my_debug("some debug message"__LINE__); 
04  /* выведет 
05  Line 4: some debug message 
06  */ 
07   
08  // ещё код 
09  // ... 
10  my_debug("another debug message"__LINE__); 
11  /* выведет 
12  Line 11: another debug message 
13  */ 
14   
15  function my_debug($msg$line) { 
16      echo "Line $line: $msg\n"; 
17  } 

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

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

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

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

01  // генерируем случайную строку 
02  echo uniqid(); 
03  /* выведет 
04  4bd67c947233e 
05  */ 
06   
07  // ещё разок 
08  echo uniqid(); 
09  /* выведет 
10  4bd67c9472340 
11  */ 

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

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

01  // с префиксом 
02  echo uniqid('foo_'); 
03  /* выведет 
04  foo_4bd67d6cd8b8f 
05  */ 
06   
07  // со вторым параметром 
08  echo uniqid('',true); 
09  /* выведет 
10  4bd67d6cd8b926.12135106 
11  */ 
12   
13  // оба 
14  echo uniqid('bar_',true); 
15  /* выведет 
16  bar_4bd67da367b650.43684647 
17  */ 

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

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

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

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

01  // сложный массив 
02  $myvar array( 
03      'hello', 
04      42, 
05      array(1,'two'), 
06      'apple' 
07  ); 
08   
09  // конвертируем в строку 
10  $string = serialize($myvar); 
11   
12  echo $string; 
13  /* выведет 
14  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";} 
15  */ 
16   
17  // получаем исходное значение 
18  $newvar = unserialize($string); 
19   
20  print_r($newvar); 
21  /* выведет 
22  Array 
23  ( 
24      [0] => hello 
25      [1] => 42 
26      [2] => Array 
27          ( 
28              [0] => 1 
29              [1] => two 
30          ) 
31   
32      [3] => apple 
33  ) 
34  */ 

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

01  // сложные массив 
02  $myvar array( 
03      'hello', 
04      42, 
05      array(1,'two'), 
06      'apple' 
07  ); 
08   
09  // конвертируем в строку 
10  $string = json_encode($myvar); 
11   
12  echo $string; 
13  /* выведет 
14  ["hello",42,[1,"two"],"apple"] 
15  */ 
16   
17  // восстанавливаем исходное значение 
18  $newvar = json_decode($string); 
19   
20  print_r($newvar); 
21  /* prints 
22  Array 
23  ( 
24      [0] => hello 
25      [1] => 42 
26      [2] => Array 
27          ( 
28              [0] => 1 
29              [1] => two 
30          ) 
31   
32      [3] => apple 
33  ) 
34  */ 

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

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

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

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

01  $string = 
02  "Lorem ipsum dolor sit amet, consectetur 
03  adipiscing elit. Nunc ut elit id mi ultricies 
04  adipiscing. Nulla facilisi. Praesent pulvinar, 
05  sapien vel feugiat vestibulum, nulla dui pretium orci, 
06  non ultricies elit lacus quis ante. Lorem ipsum dolor 
07  sit amet, consectetur adipiscing elit. Aliquam 
08  pretium ullamcorper urna quis iaculis. Etiam ac massa 
09  sed turpis tempor luctus. Curabitur sed nibh eu elit 
10  mollis congue. Praesent ipsum diam, consectetur vitae 
11  ornare a, aliquam a nunc. In id magna pellentesque 
12  tellus posuere adipiscing. Sed non mi metus, at lacinia 
13  augue. Sed magna nisi, ornare in mollis in, mollis 
14  sed nunc. Etiam at justo in leo congue mollis. 
15  Nullam in neque eget metus hendrerit scelerisque 
16  eu non enim. Ut malesuada lacus eu nulla bibendum 
17  id euismod urna sodales. "; 
18   
19  $compressed = gzcompress($string); 
20   
21  echo "Original size: "strlen($string)."\n"; 
22  /* выведет 
23  Original size: 800 
24  */ 
25   
26  echo "Compressed size: "strlen($compressed)."\n"; 
27  /* выведет 
28  Compressed size: 418 
29  */ 
30   
31  // возвращаем 
32  $original = gzuncompress($compressed); 

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

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

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

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

01  // получаем время начала 
02  $start_time = microtime(true); 
03   
04  // какие-то операции 
05  // ... 
06   
07  // выводим время работы 
08  echo "execution took: ". 
09          (microtime(true) - $start_time). 
10          " seconds."; 

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

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

01  $start_time = microtime(true); 
02   
03  register_shutdown_function('my_shutdown'); 
04   
05  function my_shutdown() { 
06      global $start_time; 
07   
08      echo "execution took: ". 
09              (microtime(true) - $start_time). 
10              " seconds."; 
11  } 

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=29351