LOGO
    • d
    • n

PHP | PHP Tutorial

    error_reporting(-1); //  вывод предупреждений

Типы данных

  • boolean: true/false (TRUE/FALSE, True/False)
  • integer: целое чило
  • float: число с плавающей точуой
  • string
  • NULL

Типы данных: Строки

Строка - это набор символов, где символ - это то же самое, что и байт. Это значит, что PHP поддерживает ровно 256 различных символов, а также то, что в PHP нет встроенной поддержки Unicode. Смотрите также подробности реализации строкового типа.

Замечание: Строки (string) не могут быть размером более 2 Гб (2147483647 байт).

Синтаксис

Строка может быть определена четырьмя различными способами:

  • одинарными кавычками
  • двойными кавычками
  • heredoc-синтаксисом
  • nowdoc-синтаксисом (начиная с версии PHP 5.3.0)

Одинарные кавычки

Одинарные кавычки Простейший способ определить строку - это заключить ее в одинарные кавычки (символ ').

Чтобы использовать одинарную кавычку внутри строки, проэкранируйте ее обратной косой чертой (). Если необходимо написать саму обратную косую черту, продублируйте ее (\). Все остальные случаи применения обратной косой черты будут интерпретированы как обычные символы: это означает, что если вы попытаетесь использовать другие управляющие последовательности, такие как \r или \n, они будут выведены как есть вместо какого-либо особого поведения.

Замечание:

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

echo 'это простая строка';

echo 'Также вы можете вставлять в строки
символ новой строки вот так,
это нормально';

// Выводит: Однажды Арнольд сказал: "I'll be back"
echo 'Однажды Арнольд сказал: "I\'ll be back"';

// Выводит: Вы удалили C:\*.*?
echo 'Вы удалили C:\\*.*?';

// Выводит: Вы удалили C:\*.*?
echo 'Вы удалили C:\*.*?';

// Выводит: Это не будет развернуто: \n новая строка
echo 'Это не будет развернуто: \n новая строка';

// Выводит: Переменные $expand также $either не разворачиваются
echo 'Переменные $expand также $either не разворачиваются';

Двойные кавычки

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

Управляющие последовательности

ПоследовательностьЗначение
\nновая строка (LF или 0x0A (10) в ASCII)
\rвозврат каретки (CR или 0x0D (13) в ASCII)
\tгоризонтальная табуляция (HT или 0x09 (9) в ASCII)
\vвертикальная табуляция (VT или 0x0B (11) в ASCII) (с версии PHP 5.2.5)
\eescape-знак (ESC или 0x1B (27) в ASCII) (с версии PHP 5.4.4)
\fподача страницы (FF или 0x0C (12) в ASCII) (с версии PHP 5.2.5)
\\ обратная косая черта
\$знак доллара
\"двойная кавычка
[0-7]{1,3}последовательность символов, соответствующая регулярному выражению символа в восьмеричной системе счисления
\x[0-9A-Fa-f]{1,2}последовательность символов, соответствующая регулярному выражению символа в шестнадцатеричной системе счисления

Как и в строке, заключенной в одинарные кавычки, экранирование любого символа выведет также и саму обратную косую черту. До версии PHP 5.1.1, обратная косая черта в {$var} не печаталась.

Но самым важным свойством строк в двойных кавычках является обработка переменных. Смотрите более подробно: обработка строк

Heredoc

Третий способ определения строк - это использование heredoc-синтаксиса: <<<. После этого оператора необходимо указать идентификатор, затем перевод строки. После этого идет сама строка, а потом этот же идентификатор, закрывающий вставку.

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

Внимание

Очень важно отметить, что строка с закрывающим идентификатором не должна содержать других символов, за исключением точки с запятой (;). Это означает, что идентификатор не должен вводиться с отступом и что не может быть никаких пробелов или знаков табуляции до или после точки с запятой. Важно также понимать, что первым символом перед закрывающим идентификатором должен быть символ новой строки, определенный в вашей операционной системе. Например, в UNIX системах, включая Mac OS X, это \n. После закрывающего идентификатора также сразу должна начинаться новая строка.

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

Heredoc не может быть использован для инициализации полей класса. Начиная с версии PHP 5.3, это ограничение распространяется только на heredoc, содержащие внутри себя переменные.

Пример #1 Неверный пример

class foo {
    public $bar = <<<EOT
bar
    EOT;
}

Heredoc-текст ведет себя так же, как и строка в двойных кавычках, при этом их не имея. Это означает, что вам нет необходимости экранировать кавычки в heredoc, но вы по-прежнему можете использовать вышеперечисленные управляющие последовательности. Переменные обрабатываются, но с применением сложных переменных внутри heredoc нужно быть также внимательным, как и при работе со строками.

Пример #2 Пример определения heredoc-строки

$str = <<<EOD
Пример строки,
охватывающей несколько строчек,
с использованием heredoc-синтаксиса.
EOD;

/* Более сложный пример с переменными. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'МоеИмя';

echo <<<EOT
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я вывожу {$foo->bar[1]}.
Это должно вывести заглавную букву 'A': \x41
EOT;

Результат выполнения данного примера:

Меня зовут "МоеИмя". Я печатаю Foo.
Теперь, я вывожу Bar2.
Это должно вывести заглавную букву 'A': A

Также возможно использовать heredoc-синтаксис для передачи данных через аргументы функции:

Пример #3 Пример применения heredoc в аргументах

var_dump(array(<<<EOD
foobar!
EOD
));

Начиная с версии 5.3.0, стала возможной инциализация статических переменных и свойств/констант класса с помощью синтаксиса heredoc:

Пример #4 Использование heredoc для инциализации статических переменных

// Статические переменные
function foo()
{
    static $bar = <<<LABEL
Здесь ничего нет...
LABEL;
}

// Class properties/constants
class foo
{
    const BAR = <<<FOOBAR
Пример использования константы
FOOBAR;

    public $baz = <<<FOOBAR
Пример использования поля
FOOBAR;
}

Начиная с версии PHP 5.3.0 можно также окружать идентификатор Heredoc двойными кавычками:

Пример #5 Использование двойных кавычек в heredoc

echo <<<"FOOBAR"
Привет, мир!
FOOBAR;

Пример #6

// HEREDOC
$str3 =<<<HERE //любое слово. после него только перевод строки, иначе ошибка. Закрывать точно таким же слово.
This is "string". $var // переменные не обрабатываются
HERE; // После, обязательны перевод строки или 

Nowdoc

Nowdoc - это то же самое для строк в одинарных кавычках, что и heredoc для строк в двойных кавычках. Nowdoc похож на heredoc, но внутри него не осуществляется никаких подстановок. Эта конструкция идеальна для внедрения PHP-кода или других больших блоков текста без необходимости его экранирования. В этом он немного похож на SGML-конструкцию <![CDATA[ ]]> тем, что объявляет блок текста, не предназначенный для обработки.

Nowdoc указывается той же последовательностью <<<, что используется в heredoc, но последующий за ней идентификатор заключается в одинарные кавычки, например, <<<'EOT'. Все условия, действующие для heredoc идентификаторов также действительны и для nowdoc, особенно те, что относятся к закрывающему идентификатору.

Замечание

Поддержка nowdoc была добавлена в PHP 5.3.0.

Пример #1 Пример использования nowdoc

$str = <<<'EOD'
Пример текста,
занимающего несколько строк,
с помощью синтаксиса nowdoc.
EOD;

/* Более сложный пример с переменными. */
class foo
{
    public $foo;
    public $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'МоеИмя';

echo <<<'EOT'
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я печатаю {$foo->bar[1]}.
Это не должно вывести заглавную 'A': \x41
EOT;

Результат выполнения данного примера:

Меня зовут "$name". Я печатаю $foo->foo.
Теперь я печатаю {$foo->bar[1]}.
Это не должно вывести заглавную 'A': \x41

Замечание

В отличие от heredoc, nowdoc может быть использован в любом контексте со статическими данными. Типичный пример инициализации полей класса или констант:

Пример #2 Пример использования статичных данных

class foo {
    public $bar = <<<'EOT'
bar
EOT;
}

Пример #3

// NOWDOC

$str4 =<<<'HERE' //любое слово. после него только перевод строки, иначе ошибка. Закрывать точно таким же слово.
This is 'string'. $var // переменные не обрабатываются
HERE; // После, обязательны перевод строки или 

Обработка переменных

Если строка указывается в двойных кавычках, либо при помощи heredoc, переменные внутри нее обрабатываются.

Существует два типа синтаксиса: простой и сложный. Простой синтаксис более легок и удобен. Он дает возможность обработки переменной, значения массива (array) или свойства объекта (object) с минимумом усилий.

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

Простой синтаксис

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

$juice = "apple";

echo "He drank some $juice juice.".PHP_EOL;
// не работает, 's' - это верный символ для имени переменной,
// но наша переменная имеет имя $juice.
echo "He drank some juice made of $juices.";

Результат выполнения данного примера:

He drank some apple juice.
He drank some juice made of .

Аналогично могут быть обработаны элемент массива (array) или свойство объекта (object). В индексах массива закрывающая квадратная скобка (]) обозначает конец определения индекса. Для свойств объекта применяются те же правила, что и для простых переменных.

Пример #1 Пример простого синтаксиса

$juices = array("apple", "orange", "koolaid1" => "purple");

echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;

class people {
    public $john = "John Smith";
    public $jane = "Jane Smith";
    public $robert = "Robert Paulsen";
    
    public $smith = "Smith";
}

$people = new people();

echo "$people->john drank some $juices[0] juice.".PHP_EOL;
echo "$people->john then said hello to $people->jane.".PHP_EOL;
echo "$people->john's wife greeted $people->robert.".PHP_EOL;
echo "$people->robert greeted the two $people->smiths."; // Won't work

Результат выполнения данного примера:

He drank some apple juice.
He drank some orange juice.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

Для чего-либо более сложного, используйте сложный синтаксис.

Сложный (фигурный) синтаксис

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

Любая скалярная переменная, элемент массива или свойство объекта, отображаемое в строку, может быть представлена в строке этим синтаксисом. Просто запишите выражение так же, как и вне строки, а затем заключите его в { и }. Поскольку { не может быть экранирован, этот синтаксис будет распознаваться только когда $ следует непосредственно за {. Используйте {\$, чтобы напечатать {$. Несколько поясняющих примеров:

// Показываем все ошибки
error_reporting(E_ALL);

$great = 'здорово';

// Не работает, выводит: Это { здорово}
echo "Это { $great}";

// Работает, выводит: Это здорово
echo "Это {$great}";
echo "Это ${great}";

// Работает
echo "Этот квадрат шириной {$square->width}00 сантиметров.";

// Работает, ключи, заключенные в кавычки, работают только с синтаксисом фигурных скобок
echo "Это работает: {$arr['key']}";

// Работает
echo "Это работает: {$arr[4][3]}";

// Это неверно по той же причине, что и $foo[bar] вне
// строки. Другими словами, это по-прежнему будет работать,
// но поскольку PHP сначала ищет константу foo, это вызовет
// ошибку уровня E_NOTICE (неопределенная константа).
echo "Это неправильно: {$arr[foo][3]}";

// Работает. При использовании многомерных массивов внутри
// строк всегда используйте фигурные скобки
echo "Это работает: {$arr['foo'][3]}";

// Работает.
echo "Это работает: " . $arr['foo'][3];

echo "Это тоже работает: {$obj->values[3]->name}";

echo "Это значение переменной по имени $name: {${$name}}";

echo "Это значение переменной по имени, которое возвращает функция getName(): {${getName()}}";

echo "Это значение переменной по имени, которое возвращает \$object->getName(): {${$object->getName()}}";

// Не работает, выводит: Это то, что возвращает getName(): {getName()}
echo "Это то, что возвращает getName(): {getName()}";

С помощью этого синтаксиса также возможен доступ к свойствам объекта внутри строк.

class foo {
    var $bar = 'I am bar.';
}

$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}\n";
echo "{$foo->$baz[1]}\n";

Результат выполнения данного примера:

I am bar.
I am bar.

Замечание

Функции, вызовы методов, статические переменные классов, а также константы классов работает внутри {$}, начиная с версии PHP 5. Однако, указываемое значение будет обработано как имя переменной в том же контексте, что и строка, в которой она определяется. Использование одинарных фигурных скобок ({}) не будет работать для доступа к значениям функций, методов, констант классов или статических переменных класса.

// Показываем все ошибки
error_reporting(E_ALL);

class beers {
    const softdrink = 'rootbeer';
    public static $ale = 'ipa';
}

$rootbeer = 'A & W';
$ipa = 'Alexander Keith\'s';

// Это работает, выводит: Я бы хотел A & W
echo "Я бы хотел {${beers::softdrink}}\n";

// Это тоже работает, выводит: Я бы хотел Alexander Keith's
echo "Я бы хотел {${beers::$ale}}\n";

Доступ к символу в строке и его изменение

Символы в строках можно использовать и модифицировать, определив их смещение относительно начала строки, начиная с нуля, в квадратных скобках после строки, например, $str[42]. Думайте о строке для этой цели, как о массиве символов. Если нужно получить или заменить более 1 символа, можно использовать функции substr() и substr_replace().

Замечание

К символу в строке также можно обращаться с помощью фигурных скобок, например, $str{42}.

Внимание

Попытка записи в смещение за границами строки дополнит строку пробелами до этого смещения. Нецелые типы будет преобразованы в целые. Неверный тип смещения вызовет ошибку уровня E_NOTICE. Запись по отрицательному смещению вызовет ошибку уровня E_NOTICE, а при чтении вернет пустую строку. Используется только первый символ присваемой строки. Присвоение пустой строки присваивает нулевой байт (NULL).

Внимание

Строки в PHP внутренне представляют из себя массивы байт. Как результат, доступ или изменение строки по смещению небезопасно с точки зрения многобайтной кодировки, и должно выполняться только со строками в однобайтных кодировках, таких как, например, ISO-8859-1.

Пример #1 Несколько примеров строк

// Получение первого символа строки
$str = 'This is a test.';
$first = $str[0];

// Получение третьего символа строки
$third = $str[2];

// Получение последнего символа строки
$str = 'This is still a test.';
$last = $str[strlen($str)-1]; 

// Изменение последнего символа строки
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';

Начиная с PHP 5.4 смещение в строке должно задаваться либо целым числом либо строкой, содержащей цифры, иначе будет выдаваться предупреждение. Ранее смещение, заданное строкой вида "foo", без предупреждений преобразовывалось в 0.

Пример #2 Различия между PHP 5.3 и PHP 5.4

$str = 'abc';

var_dump($str['1']);
var_dump(isset($str['1']));

var_dump($str['1.0']);
var_dump(isset($str['1.0']));

var_dump($str['x']);
var_dump(isset($str['x']));

var_dump($str['1x']);
var_dump(isset($str['1x']));

Результат выполнения данного примера в PHP 5.3:

string(1) "b"
bool(true)
string(1) "b"
bool(true)
string(1) "a"
bool(true)
string(1) "b"
bool(true)

// Результат выполнения данного примера в PHP 5.4:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)

Замечание

Попытка доступа к переменным других типов (исключая массивы или объекты, реализующие определенные интерфейсы) с помощью [] или {} молча вернет NULL.

Замечание

В PHP 5.5 была добавлена поддержка доступа к символам в строковых литералах с помощью синтаксиса [] или {}.

Полезные функции и операторы

Строки могут быть объединены при помощи оператора '.' (точка). Обратите внимание, оператор сложения '+' здесь не работает. Дополнительную информацию смотрите в разделе Строковые операторы.

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

Основные функции описаны в разделе строковых функций, а для расширенного поиска и замены - функции регулярных выражений или Perl-совместимых регулярных выражений.

Также существуют функции для работы с URL, и функции шифрования/дешифрования строк (mcrypt и mhash).

Наконец, смотрите также функции символьных типов.

Преобразование в строку

Значение может быть преобразовано в строку, с помощью приведения (string), либо функции strval(). В выражениях, где необходима строка, преобразование происходит автоматически. Это происходит, когда вы используете функции echo или print, либо когда значение переменной сравнивается со строкой. Прочтение разделов руководства Типы и Манипуляции с типами сделает следующее более понятным. Смотрите также settype().

Значение boolean TRUE преобразуется в строку "1", а значение FALSE преобразуется в "" (пустую строку). Это позволяет преобразовывать значения в обе стороны - из булева типа в строковый и наоборот.

Целое (integer) или число с плавающей точкой (float) преобразуется в строку, представленную числом, состоящим из его цифр (включая показатель степени для чисел с плавающей точкой). Числа с плавающей точкой могут быть преобразованы с помощью экспоненциального представления (4.1E+6).

Замечание

Символ десятичной точки определяется из настроек локали текущего скрипта (категория LC_NUMERIC). Смотрите также setlocale().

Массивы всегда преобразуются в строку "Array", так что вы не можете отобразить содержимое массива (array), используя echo или print, чтобы узнать, что он содержит. Чтобы просмотреть отдельный элемент, используйте что-нибудь вроде echo $arr['foo']. Смотрите ниже советы о том, как отобразить/просмотреть все содержимое.

Объекты в PHP 4 всегда преобразовывались в строку "Object". Если вы хотите вывести значения полей объекта (object) с целью отладки, читайте дальше. Если вы хотите получить имя класса требуемого объекта, используйте get_class(). Начиная с PHP 5, также стал доступен метод __toString.

Resource всегда всегда преобразуется в string вида "Resource id #1", где 1 является номером ресурса привязанного к resource во время выполнения. И хотя не стоит точно полагаться на эту строку, которая может быть изменена в будущем, она всегда будет уникальной для текущего запуска скрипта (т.е. web-запроса или CLI-процесса) и не может использоваться повторно для другого ресурса. Если вы хотите получить тип ресурса, используйте get_resource_type().

NULL всегда преобразуется в пустую строку.

Как вы могли видеть выше, прямое преобразование в строку массивов, объектов или ресурсов не дает никакой полезной информации о самих значениях, кроме их типов. Более подходящий способ вывода значений для отладки - использовать функции print_r() и var_dump().

Большинство значений в PHP может быть преобразовано в строку для постоянного хранения. Этот метод называется сериализацией и может быть выполнен при помощи функции serialize(). Кроме того, если в вашей установке PHP есть поддержка WDDX, возможна также сериализация в XML-структуру.

Преобразование строк в числа

Если строка распознается как числовое значение, результирующее значение и тип определяется так, как показано далее.

Если строка не содержит какой-либо из символов '.', 'e', или 'E', и значение числа помещается в пределы целых чисел (определенных PHP_INT_MAX), строка будет распознана как целое число (integer). Во всех остальных случаях она считается числом с плавающей точкой (float).

Значение определяется по начальной части строки. Если строка начинается с верного числового значения, будет использовано это значение. Иначе значением будет 0 (ноль). Верное числовое значение - это одна или более цифр (могущих содержать десятичную точку), по желанию предваренных знаком, с последующим необязательным показателем степени. Показатель степени - это 'e' или 'E' с последующими одной или более цифрами.

$foo = 1 + "10.5";                // $foo это float (11.5)
$foo = 1 + "-1.3e3";              // $foo это float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo это integer (1)
$foo = 1 + "bob3";                // $foo это integer (1)
$foo = 1 + "10 Small Pigs";       // $foo это integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo это float (14.2)
$foo = "10.0 pigs " + 1;          // $foo это float (11)
$foo = "10.0 pigs " + 1.0;        // $foo это float (11)

Более подробную информацию об этом преобразовании смотрите в разделе о strtod(3) документации Unix.

Если вы хотите протестировать любой из примеров этого раздела, скопируйте и вставьте его и следующую строку, чтобы увидеть, что происходит:

echo "\$foo==$foo; тип: " . gettype ($foo) . "<br />\n";

Не ожидайте получить код символа, преобразовав его в целое (как это делается, например, в C). Для преобразования символов в их ASCII коды и обратно используйте функции ord() и chr().

Подробности реализации строкового типа

Строковый тип (string) в PHP реализован в виде массива байт и целого числа, содержащего длину буфера. Он не содержит никакой информации о способе преобразования этих байт в символы, предоставляя эту задачу программисту. Нет никаких ограничений на содержимое строки, например, байт со значением 0 ("NUL"-байт) может располагаться где угодно (однако, стоит учитывать, что некоторые функции, как сказано в этом руководстве, не являются "бинарно-безопасными", т.е. они могут передавать строки библиотекам, которые игнорируют данные после NUL-байта).

Данная природа строкового типа объясняет почему в PHP нет отдельного типа “byte” - строки играют эту роль. Функции, возвращающие нетекстовые данные - например, произвольный поток данных, считываемый из сетевого сокета - тем не менее возвращают строки.

Принимая во внимание тот факт, что PHP не диктует определенную кодировку для строк, можно задать вопрос, как в таком случае кодируются строковые литералы. Например, строка "á" эквивалентна "\xE1" (ISO-8859-1), "\xC3\xA1" (UTF-8, форма нормализации C), "\x61\xCC\x81" (UTF-8, форма нормализации D) или какому-либо другому возможному представлению? Ответом является следующее: строка будет закодирована тем образом, которым она записана в файле скрипта. Таким образом, если скрипт записан в кодировке ISO-8859-1, то и строка будет закодирована в ISO-8859-1 и т.д. Однако, это правило не применяется при включенном режиме Zend Multibyte: в этом случае скрипт может быть записан в любой кодировке (которая указывается ясно или определяется автоматически), а затем конвертируются в определенную внутреннюю кодировку, которая и будет впоследствии использована для строковых литералов. Учтите, что на кодировку скрипта (или на внутреннюю кодировку, если включен режим Zend Multibyte) накладываются некоторые ограничения: практически всегда данная кодировка должна быть надмножеством ASCII, например, UTF-8 или ISO-8859-1. Учтите также, что кодировки, зависящие от состояния, где одни и те же значения байт могут быть использованы в начальном и не начальном состоянии сдвига (initial and non-inital shift state), могут вызвать проблемы.

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

  • Некоторые функции предполагают, что строка закодирована в какой-либо однобайтовой кодировке, однако, для корректной работы им не требуется интерпретировать байты как определенные символы. Под эту категорию попадают, например, substr(), strpos(), strlen() и strcmp(). Другой способ мышления об этих функциях представляет собой оперирование буферами памяти, т.е. они работают непосредственно с байтами и их смещениями. offsets.
  • Другие функции ожидают передачу кодировку в виде параметра, возможно, предполагая некоторую кодировку по умолчанию, если параметр с кодировкой не был указан. Такой функцией является htmlentities() и большинство функций из расширения mbstring.
  • Другие функции используют текущие установки локали (см. setlocale()), но оперируют побайтово). В эту категорию попадают strcasecmp(), strtoupper() и ucfirst(). Это означает, что они могут быть использованы только с однобайтовыми кодировками, в том случае, когда кодировка совпадает с локалью. Например, strtoupper("á") может вернуть "Á", если локаль установлена корректно и буква á закодирована в виде одного байта. Если она закодирована в UTF-8, будет возвращен некорректный результат, и, в зависимости от текущей локали, результирующая строка может быть (или не быть) испорчена.
  • Наконец, есть функции, подразумевающие, что строка использует определенную кодировку, обычно UTF-8. Сюда попадают большинство функций из расширений intl и PCRE (в последнем случае, только при указании модификатора u). Хотя это и сделано специально, функция utf8_decode() подразумевает кодировку UTF-8, а utf8_encode() - ISO-8859-1.

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

Приведения типов

ОПЕРАТОРЫ

`$a + $b`, `$a - $b`, `$a * $b`, `$a / $b`  
`$a % $b`  
`$a ** $b` // возведение в степинь (PHP 5.6). Аналог - функция `pow( x, n )`  
`>`, `<`, `<=`, `>=`  
`!=` // не равно  
`=` // присваевание  
`&` // присваевание по ссылке

$a = 5;
$b = $a; // новая ячейка памяти
var_damp($a, $b) // 5, 5
$a = 7;
var_damp($a, $b) // 7, 5

$a = 5;
$b = &$a; // новая ячейка памяти не создается, $b ссылается на ячейку $a
var_damp($a, $b) // 5, 5
$a = 7;
var_damp($a, $b) // 7, 7
`==` // сравнение  
`===`, `!==` //   
`++$a` // префиксный инкремент  
`$a++` // постфиксный инкремент, аналоги $a = $a + 1, $a += 1  
`--$a` // перфиксный декркмент  
`$a--` // постфиксный декремент  
`.` // конкатенация  
`+=`, `-=`, `*=`, `/=`, `.=` // комбинированые операторы `$a = $a + 2 $a += 2`
`<=>` // Космический корабль (spaceship).

// Целые числа
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

// Числа с плавающей точкой
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

// Строки
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1

echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1

// Массивы
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1

// Объекты
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0

$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1

$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1

// сравниваются не только значения; ключи также должны совпадать
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 1

УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ

  • if
  • else
  • elseif
  • switch case

IF, ELSE, ELSEIF

if (exp) 
   statement
if() ...;
if() {...};
if() {...} else {...};
if() {...} elseif {...};
if() {...} elseif {...} else {...};
if() {...} elseif {...} elseif {...};
if() {...} elseif {...} elseif {...} else {...};

Тернарный оператор PHP / ?: / ??

$var = condition ? exp1 : exp2;
// PHP 5.3
$var = $value ?: "Другое значение"; // еквивалентно $var = $value ? $value : "Другое значение";
// Этот вариант полезно использовать, когда нужно изменить значение переменной, только в случае, когда проверяемая переменная не равняется true
// PHP 7
$var = $value ?? "Другое значение"; // // еквивалентно $var = isset($value) ? $value : "Другое значение";
// Такой вариант полезно использовать, если нужно сначала проверить существует ли переменная. Т. е., если переменная не существует, то использовать какое-то другое значение.

SWITCH CASE

$var = 3;

svitch($var) {
    case 1:
        echo 'Variable = 1';
    break;
    case 2:
        echo 'Variable = 2';
    break;
    case 3:
        echo 'Variable = 3';
    break;
    default:
        echo 'Something else...';
}

Альтернативный синтаксис управляющих структур

Для:

  • if
<?php if ($a == 5): ?>
A равно 5
<?php endif; ?>
if ($a == 5):
    echo "a равно 5";
    echo "...";
elseif ($a == 6):
    echo "a равно 6";
    echo "!!!";
else:
    echo "a не равно ни 5 ни 6";
endif;
  • while
  • for
  • forech
  • switch

require, include, require_once, include_once

require - в случае ошибки останавлевает скрипт

include - в случае ошибки продолжает скрипт

return

ПЕРЕМЕННЫЕ

$name = 'ZAPA';

МАССИВЫ

База

$arr = arrey('Ivanov', 'Petrov', 'Sidorov');
$arr = ['Ivanov', 'Petrov', 'Sidorov'] // с версии PHP 5.4

echo $arr[0]; // аналог $arr{0}
$arr[] = 'Pupkin'; // добавить элемент в конец масива
$arr[5] = 'Pupkin'; // добавить элемент в позицию с ключем "5" 
$countrys = ['USA', 'Canad', 'Spain'];

// многомерный, асоциативный массив
$friends = [
    'friend1' => [
        'name'  => 'Den',
        'age'   => 25,
    ],
    'friend2' => [
        'name'  => 'Tom',
      'age'   => 18,
    ]
];

echo $namesss;
echo $countrys[0];
echo $friends['friend2']['name'];

Функции для роботы с массивом

ЦИКЛЫ

  • while
  • do-while
  • for
  • foreach

while

while (expr)
    statement
while (expr):
    statement
    ...
endwhile;

Примеры:

$i = 1;
while ($i < 10) {
  echo $i;
  $i++;
}

$i = 1;
while($i < 10){
  echo $i++;
}
$i = 1;
echo "<table border=\"1\">\n";
while($i <= 15){
  echo "\t<tr>\n";
  $n = 1;
  while($n <= 5){
    echo "\t\t<td>Row $i | Col - $n</td>\n";
    $n++;
  }
  echo "\t</tr>\n";
  $i++;
}
echo '</table>';
$year = 1900;
echo '<select>' . "\n";
  while($year <= 2015){
    echo "\t<option value='$year'>$year</option>\n";
    $year++;
  }
echo '</select>';

do-while

$i = 10;
do {
  echo $i++ . '<br>';
} while ($i <= 10);
$countrys = ['USA', 'Canad', 'Spain'];

foreach ($countrys as $country) {
    echo $country . ' ';
}

for

foreach

ФУНКЦИИ

Сигнатура фунции

Сигнатура — это описание функции (метода), включающее в себя:

  • Модификатор доступа
  • Имя функции (метода)
  • Список аргументов, где для каждого аргумента указано:
    • Тип
    • Имя
    • Значение по умолчанию
    • либо оператор «три точки»
  • Тип возвращаемого значения

Примеры:

function ();
public function foo($arg = null);
protected function sum(int $x, int $y, ...$args): int;
pow ( number $base , number $exp ) : number

// Информация расшифровывается так:
// - функция называется pow
// - функция принимает два параметра: число (base) и число (exp)
// - функция возвращает число (number)

Совместимость сигнатур

Предположим, что у нас есть две функции, A и B. Сигнатура функции B считается совместимой с A (порядок важен, отношение несимметрично!) в строгом смысле, если:

Они полностью совпадают

//Тривиальный случай, комментировать тут нечего.

B добавляет к A аргументы по умолчанию

// A:
function foo($x);

// совместимые B:
function foo($x, $y = null);
function foo($x, ...$args);

B сужает область значений A

// A:
function foo(int $x);
// совместимые B:
// В A допускался возврат любых значений, в B эта область сужена только до целых чисел
function foo(int $x): int;

Пользовательские функции в PHP

Функция header в PHP

Функции работы со строками в PHP

php.net - Функции для работы со строками

addcslashes()  // Экранирует строку слешами в стиле языка C
addslashes()  // Экранирует строку с помощью слешей
bin2hex()  // Преобразует бинарные данные в шестнадцатеричное представление
chop()  // Псевдоним rtrim
chr()  // Генерирует односимвольную строку по заданному числу
chunk_split()  // Разбивает строку на фрагменты
convert_cyr_string()  // Преобразует строку из одной кириллической кодировки в другую                                       
convert_uudecode()  // Декодирует строку из формата uuencode в обычный вид                                                
convert_uuencode()  // Кодирует строку в формат uuencode                                                                  
count_chars()  // Возвращает информацию о символах, входящих в строку                                                
crc32()  // Вычисляет полином CRC32 для строки                                                                 
crypt()  // Необратимое хеширование строки                                                                     
echo  // Выводит одну или более строк                                                                       
explode()  // Разбивает строку с помощью разделителя                                                             
fprintf()  // Записывает отформатированную строку в поток                                                        
get_html_translation_table()  // Возвращает таблицу преобразований, используемую функциями htmlspecialchars и htmlentities          
hebrev()  // Преобразует текст на иврите из логической кодировки в визуальную                                   
hebrevc()  // Преобразует текст на иврите из логической кодировки в визуальную с преобразованием перевода строки 
hex2bin()  // Преобразует шестнадцатеричные данные в двоичные                                                    
html_entity_decode()  // Преобразует HTML-сущности в соответствующие им символы                                             
htmlentities()  // Преобразует все возможные символы в соответствующие HTML-сущности                                  
htmlspecialchars_decode()  // Преобразует специальные HTML-сущности обратно в соответствующие символы                            
htmlspecialchars()  // Преобразует специальные символы в HTML-сущности                                                    
implode()  // Объединяет элементы массива в строку                                                               
join()  // Псевдоним implode                                                                                  
lcfirst()  // Преобразует первый символ строки в нижний регистр                                                  
levenshtein()  // Вычисляет расстояние Левенштейна между двумя строками                                              
localeconv()  // Возвращает информацию о форматировании чисел                                                       
ltrim()  // Удаляет пробелы (или другие символы) из начала строки                                              
md5_file()  // Возвращает MD5-хеш файла                                                                           
md5()  // Возвращает MD5-хеш строки                                                                          
metaphone()  // Возвращает ключ metaphone для строки                                                               
money_format()  // Форматирует число как денежную величину                                                            
nl_langinfo()  // Возвращает информацию о языке и локали                                                             
nl2br()  // Вставляет HTML-код разрыва строки перед каждым переводом строки                                    
number_format()  // Форматирует число с разделением групп                                                              
ord()  // Конвертирует первый байт строки в число от 0 до 255                                                
parse_str()  // Разбирает строку в переменные                                                                      
print // Выводит строку                                                                                     
printf()  // Выводит отформатированную строку                                                                   
quoted_printable_decode()  // Преобразует строку, закодированную методом quoted-printable в 8-битную строку                      
quoted_printable_encode()  // Преобразует 8-битную строку с помощью метода quoted-printable                                      
quotemeta()  // Экранирует специальные символы                                                                     
rtrim()  // Удаляет пробелы (или другие символы) из конца строки                                               
setlocale()  // Устанавливает настройки локали                                                                     
sha1_file()  // Возвращает SHA1-хеш файла                                                                          
sha1()  // Возвращает SHA1-хеш строки                                                                         
similar_text()  // Вычисляет степень похожести двух строк                                                             
soundex()  // Возвращает ключ soundex для строки                                                                 
sprintf() // Возвращает отформатированную строку

$num = 5;
$location = 'tree';
$format = 'There are %d monkeys in the %s';

echo sprintf($format, $num, $location);
sscanf()  // Разбирает строку в соответствии с заданным форматом   
str_contains()  // Определяет, содержит ли строка заданную подстроку     
str_ends_with()  // Проверяет, заканчивается ли строка заданной подстрокой
str_getcsv()  // Выполняет разбор CSV-строки в массив                  
str_ireplace()  // Регистронезависимый вариант функции str_replace       
str_pad()  // Дополняет строку другой строкой до заданной длины     
str_repeat()  // Возвращает повторяющуюся строку                       
str_replace() // Заменяет все вхождения строки поиска на строку замены

$str = '[i]Hello![/i] my name is [b]Bob[/b]';
$search = ['[i]', '[/i]', '[b]', '[/b]'];
$replace = ['<i>', '</i>', '<b>', '</b>'];
$str = str_replace( $search, $replace. $str );
str_rot13()      // Выполняет преобразование ROT13 над строкой                                    
str_shuffle()    // Переставляет символы в строке случайным образом                               
str_split()      // Преобразует строку в массив                                                   
str_starts_with()// Проверяет, начинается ли строка с заданной подстроки                          
str_word_count() // Возвращает информацию о словах, входящих в строку                             
strcasecmp()     // Бинарно-безопасное сравнение строк без учёта регистра                         
strchr()         // Псевдоним strstr                                                              
strcmp()         // Бинарно-безопасное сравнение строк                                            
strcoll()        // Сравнение строк с учётом текущей локали                                       
strcspn()        // Возвращает длину участка в начале строки, не соответствующего маске           
strip_tags()     // Удаляет теги HTML и PHP из строки                                             
stripcslashes()  // Удаляет экранирование символов, произведённое функцией addcslashes            
stripos()        // Возвращает позицию первого вхождения подстроки без учёта регистра             
stripslashes()   // Удаляет экранирование символов                                                
stristr()        // Регистронезависимый вариант функции strstr                                    
strlen()         // Возвращает длину строки                                                       
strnatcasecmp()  // Сравнение строк без учёта регистра с использованием алгоритма "natural order" 
strnatcmp()      // Сравнение строк с использованием алгоритма "natural order"                    
strncasecmp()    // Бинарно-безопасное сравнение первых n символов строк без учёта регистра       
strncmp()        // Бинарно-безопасное сравнение первых n символов строк                          
strpbrk()        // Ищет в строке любой символ из заданного набора                                
strpos()         // Возвращает позицию первого вхождения подстроки                                
strrchr()        // Находит последнее вхождение символа в строке                                  
strrev()         // Переворачивает строку задом наперёд                                           
strripos()       // Возвращает позицию последнего вхождения подстроки без учёта регистра          
strrpos()        // Возвращает позицию последнего вхождения подстроки в строке                    
strspn()         // Возвращает длину участка в начале строки, полностью соответствующего маске    
strstr()         // Находит первое вхождение подстроки                                            
strtok()         // Разбивает строку на токены
strtolower()     // Преобразует строку в нижний регистр                                               
strtoupper()     // Преобразует строку в верхний регистр                                              
strtr()          // Преобразует заданные символы или заменяет подстроки                               
substr_compare() // Бинарно-безопасное сравнение 2 строк со смещением, с учётом или без учёта регистра
substr_count()   // Возвращает число вхождений подстроки                                              
substr_replace() // Заменяет часть строки                                                             
substr()         // Возвращает подстроку                                                              
trim() //удаляет пробелы (или другие символы) из начала и конца строки;

// Эта функция возвращает строку string с удалёнными из начала и конца строки пробелами. Если второй параметр не передан, trim() удаляет следующие символы:
// " " (ASCII 32 (0x20)), обычный пробел.
// "\t" (ASCII 9 (0x09)), символ табуляции.
// "\n" (ASCII 10 (0x0A)), символ перевода строки.
// "\r" (ASCII 13 (0x0D)), символ возврата каретки.
// "\0" (ASCII 0 (0x00)), NUL-байт.
// "\v" (ASCII 11 (0x0B)), вертикальная табуляция.

ucfirst()  // Преобразует первый символ строки в верхний регистр                
ucwords()  // Преобразует в верхний регистр первый символ каждого слова в строке
vfprintf() // Записывает отформатированную строку в поток                       
vprintf()  // Выводит отформатированную строку                                  
vsprintf() // Возвращает отформатированную строку                               
wordwrap() // Переносит строку по указанному количеству символов                
explode() // разбивает строку с помощью разделителя;
implode() // объединяет элементы массива в строку // join() — Псевдоним implode();
ltrim() // Удаляет пробелы (или другие символы) из начала строки;
rtrim() // Удаляет пробелы (или другие символы) из конца строки;
nl2br() // Вставляет HTML-код разрыва строки перед каждым переводом строки
str_ireplace() // Регистронезависимый вариант функции str_replace()
strip_tags() // Удаляет теги HTML и PHP из строки
strlen() // Возвращает длину строки. !!! Считает количество байтов, а не символов !!!
mb_strlen() // Получает длину строки

$str = "Привет";
echo mb_strlen( $str, 'utf-8' ); // вернет правильное значение
strpos(), mb_strpos() // Возвращает позицию первого вхождения подстроки
strtolower(), mb_strtolower() // Преобразует строку в нижний регистр
strtoupper(), mb_strtoupper() // Преобразует строку в верхний регистр
substr(), mb_substr() // Возвращает подстроку
htmlspecialchars() // Преобразует специальные символы в HTML-сущности

Функции даты и времени в PHP

php.net - Функции даты и времени

checkdate() // Проверяет корректность даты по григорианскому календарю 
date_add() // Псевдоним DateTime::add
date_create_from_format() // Псевдоним DateTime::createFromFormat
date_create_immutable_from_format() // Псевдоним DateTimeImmutable::createFromFormat
date_create_immutable() // Псевдоним DateTimeImmutable::__construct
date_create() // Псевдоним DateTime::__construct
date_date_set() // Псевдоним DateTime::setDate
date_default_timezone_get() // Возвращает часовой пояс, используемый по умолчанию всеми функциями даты/времени в скрипте 
date_default_timezone_set() // Устанавливает часовой пояс по умолчанию для всех функций даты/времени в скрипте 
date_diff() // Псевдоним DateTime::diff
date_format() // Псевдоним DateTime::format
date_get_last_errors() // Псевдоним DateTime::getLastErrors
date_interval_create_from_date_string() // Псевдоним DateInterval::createFromDateString
date_interval_format() // Псевдоним DateInterval::format
date_isodate_set() // Псевдоним DateTime::setISODate
date_modify() // Псевдоним DateTime::modify
date_offset_get() // Псевдоним DateTime::getOffset
date_parse_from_format() // Получение информации о заданной в определённом формате дате
date_parse() // Возвращает ассоциативный массив с подробной информацией о заданной дате/времени
date_sub() // Псевдоним DateTime::sub
date_sun_info() // Возвращает массив с информацией о закате/рассвете и начале/окончании сумерек
date_sunrise() // Возвращает время рассвета для заданных дня и местоположения
date_sunset() // Возвращает время захода солнца для заданных дня и местоположения
date_time_set() // Псевдоним DateTime::setTime
date_timestamp_get() // Псевдоним DateTime::getTimestamp
date_timestamp_set() // Псевдоним DateTime::setTimestamp
date_timezone_get()  // Псевдоним DateTime::getTimezone
date_timezone_set()  // Псевдоним DateTime::setTimezone
date() // Форматирует вывод системной даты/времени
getdate() // Возвращает информацию о дате/времени
gettimeofday() // Возвращает текущее время
gmdate() // Форматирует дату/время по Гринвичу
gmmktime() // Возвращает локальную метку времени Unix для времени по Гринвичу
gmstrftime() // Форматирует дату/время по Гринвичу с учётом текущей локали
idate() // Преобразует локальное время/дату в целое число
localtime() // Возвращает локальное время
microtime() // Возвращает текущую метку времени Unix с микросекундами
mktime() // Возвращает метку времени Unix для заданной даты
strftime() // Форматирует текущую дату/время с учётом текущих настроек локали
strptime() // Разбирает строку даты/времени, сгенерированную функцией strftime
strtotime() // Преобразует текстовое представление даты на английском языке в метку времени Unix
time() // Возвращает текущую метку системного времени Unix
timezone_abbreviations_list() // Псевдоним DateTimeZone::listAbbreviations
timezone_identifiers_list() // Псевдоним DateTimeZone::listIdentifiers
timezone_location_get() // Псевдоним DateTimeZone::getLocation
timezone_name_from_abbr() // Возвращает часовой пояс в соответствии с аббревиатурой
timezone_name_get() // Псевдоним DateTimeZone::getName
timezone_offset_get() // Псевдоним DateTimeZone::getOffset
timezone_open() // Псевдоним DateTimeZone::__construct
timezone_transitions_get() // Псевдоним DateTimeZone::getTransitions
timezone_version_get() // Получение номера версии базы данных часовых поясов

##БУФЕР ВЫВОДА==

Для начала, даю установку — буферов вывода в PHP несколько, плюс ещё модули web-сервера могут выполнять буферизацию, да ещё и браузеры могут играться с выводом и не сразу отображать полученный результат (надо бы тут освежить память, а то за упоминание Netscape могут освежевать).

Вот теперь буду рассказывать о буферизации в PHP.

Пользовательский буфер вывода

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

// включаем буфер
ob_start();
 
// этот, и весь последующий вывод, будет попадать в буфер вывода
echo "hello world";

Если же нам надо сохранить данные, или ещё как обработать вывод то нам потребуется функция ob_get_contents(). Сохранив данные, можно очистить и отключить буфер — для этого воспользуемся функцией ob_end_clean(), если свести всё перечисленное до кучи, то в результате получим следующий код:

// включаем буфер
ob_start();
 
// выводим информацию
echo "hello world";
 
// сохраняем всё что есть в буфере в переменную $content
$content = ob_get_contents();
 
// отключаем и очищаем буфер
ob_end_clean();

Практически все нужные нам функции имеют префикс «ob_», как не трудно догадаться это сокращение от «output buffer»

Функцию ob_get_contents() можно вызывать множество раз, на практике с таким не сталкивался:

// включаем буфер
ob_start();
 
// выводим информацию
echo "hello ";
 
// сохраняем всё что есть в буфере в переменную
// на данный момент там только `hello `
$a = ob_get_contents();
 
// выводим информацию
echo "world ";
 
// повторный вызов
// теперь буфер содержит `hello world `
$b = ob_get_contents();

Если вы стартанули буфер вывода, но по какой-то причине не закрыли его, то PHP это сделает за вас и в конце работы скрипта выполнит «сброс» буфера вывода в браузер пользователя

Если внутри блока ob_start – ob_end вы отправляете заголовок, то он не попадает в буфер, а сразу будет отправлен в браузер:

header("OB-START: 1");
ob_start();
 
echo "Never saw";
header("PHP-VERSION: ". PHP_VERSION);
 
ob_end_clean();
header("OB-END: 1");

В результате выполнения данного кода в http-пакете появятся следующие заголовки:

OB-START: 1
PHP-VERSION: 5.6.11-1+deb.sury.org~trusty+1
OB-END: 1

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

Данное правило по отправке заголовков верно как для непосредственного вызова функции header(), так и для неявного при вызове session_start():

ob_start();
{
    echo "hello world";
    session_start();  // тут всё будет работать корректно
    $content = ob_get_contents();
}
ob_end_clean();
echo "<h1>".$content."</h1>";

Перед вами небольшой life-hack – в PHP вы можете использовать скобочки {} для выделения некой логики в блоки, при этом никакой функциональной нагрузки они не несут, а вот читаемость кода – повышают

Чуть-чуть прояснили ситуацию — теперь в копилке наших знаний есть информация о том, как включить буфер, как получить из него данные, и как выключить. Что ещё интересное можно с ним вытворять? Да с ним практически ничего толком и не сделать — его можно отправить (сбросить) в браузер (ключевое слово flush), очистить (clean), отключить (end). Ну и скомбинировать это всё до кучи тоже можно:

  • ob_clean() — читаем название функции как «очищаем буфер вывода»
  • ob_flush() — «отправляем буфер вывода»
  • ob_end_clean() — «буфер вывода отключаем и очищаем»
  • ob_end_flush() — «буфер вывода отключаем и отправляем в браузер»
  • ob_get_clean() — «получаем буфер вывода, очищаем и отключаем» — тут небольшой отступление от правила, эта функция должна именоваться как ob_get_end_clean(), но решили упростить, и выкинули end
  • ob_get_flush() — «отправляем буфер вывода, очищаем и отключаем», ob_get_end_flush()

Что можно из перечисленного делать с буфером вывода, определяется третьим опциональным параметром $flags при вызове функции ob_start(), используется крайне редко

Для простого запоминания вот вам наглядная табличка по данному семейству функций:

вернёточиститотправитотключит
ob_get_contentsx
ob_cleanx
ob_flushx
ob_end_cleanxx
ob_end_flushxx
ob_get_cleanxxx
ob_get_flushxxx

Задание Дополните приведенный ниже код вызовом одной функции, чтобы он корректно вывел «hello world»:

ob_start();
{
    echo "hello";
    $a = ob_get_contents();
    echo "world";
    $b = ob_get_contents();
}
ob_end_clean();
 
echo $a .' '. $b;

Обработчик буфера

Пора вернуться к функции ob_start() и её первому параметру — $output_callback — обработчик буфера вывода. В качестве обработчика буфера должна быть указана callback-функция, которая принимает содержимое буфера как входной параметр и должна вернуть строку после обработки:

/**
 * @param  string  $buffer Содержимое буфера
 * @param  integer $phase  Битовая маска из значений PHP_OUTPUT_HANDLER_*
 * @return string
 */
function ob_handler ($buffer, $phase) {
    return "Length of string '$buffer' is ". strlen($buffer);
}
 
ob_start('ob_handler');
echo "hello world";
ob_end_flush();

В данном примере функция обработчик вернёт строку «Length of string ‘hello world’ is 11».

Важный момент — с этими функциями нужно быть поосторожней, обработали строки и ладненько, но не пытайтесь вывести либо сохранить данные, не пытайтесь стартовать другой буфер вывода внутри функции, и да есть функции которые создают буфер вывода внутри себя, вот print_r() и highlight_file() тому пример

Из стандартных же обработчиков можете повстречать https://www.php.net/function.ob-gzhandler, но лучше сжатие страничек оставлять на плечах web-сервера, и не вешать это на PHP.

Ещё момент, второй параметр $phase callback-функции может включать в себя флаги из семейства PHP_OUTPUT_HANDLER_*, но вам эта информация никогда не понадобится, я даже пример не смог придумать, зачем оно надо.

We need to go deeper

У буфера вывода есть килер-фича – внутри буфера можно стартовать ещё один буфер, а внутри нового ещё и так далее (пока памяти хватает):

echo ob_get_level();              // 1
ob_start();
    echo ob_get_level();          // 2
    ob_start();
        echo ob_get_level();      // 3
        ob_start();
            echo ob_get_level();  // 4
        ob_end_flush();
    ob_end_flush();
ob_end_flush();

В данном примере функция ob_flush() и производные от неё, будут «выбрасывать» содержимое буфера на более высокий уровень.

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

Если вы не знаете точно на какой «глубине» находитесь – то воспользуйтесь функцией ob_get_level(), а чтобы «проснуться» вам пригодится следующий код:

while (ob_get_level()) {
    ob_end_clean();
}

Задание Внесите изменения в код с вложенными вызовами ob_start() таким образом, чтобы цифры выводились в обратном порядке, для этого надо переставить три строчки кода.

Буфер «по умолчанию»

Если захотите создать обёртку над всем кодом, то для этого можно воспользоваться решением «из коробки» — буфер вывода «по умолчанию», за активацию оного отвечает директива output_buffering, её можно выставить как в On, так и указать размер буфера который нам потребуется (при достижении лимита, буфер будет отправлен в браузер пользователю). Данная директива должна быть проставлена либо в php.ini, либо в .htaccess (для апача), попытка выставить данное значение с использование ini_set() ни к чему не приведёт, т.к. PHP уже стартанул, и буфер вывода уже сконфигурирован согласно настроек:

// .htaccess
1php_value output_buffering 4096

Если при включенном буфере проверить уровень вложенности и вызвать функцию ob_get_level(), то получим 1:

if (ini_get('output_buffering')) {
    echo ob_get_level(); // 1
}

Т.е. если включить данный буфер, то можно будет избежать ошибок вида «headers already sent»? Да, пока буфера хватит, но никогда так не делайте, ведь понадеявшись на данный метод, вы фактически заложите бомбу замедленного действия, и неизвестно когда она «рванёт» и посыпит ошибками:

// сохраняем значение буфера
$buffer = ini_get('output_buffering');
 
// "выводим" текст на байт меньше буфера
echo str_pad('', $buffer - 1);
 
// отправляем заголовок
header("TAG-A: ". PHP_VERSION);
 
// ещё байт
echo " ";
 
// а второй заголовок уже не отправляется
// получите ошибку
header("TAG-B: ". PHP_VERSION);

Запомните, для CLI приложений директива output_buffering всегда 0, т.е. данный буфер отключен

Зачем это всё?

Хороший вопрос — зачем нужна работа с буфером вывода? Приведу несколько основных сценариев использования:

  1. Сжатие передаваемых данных — с использованием уже упомянутой ob_gzhandler()
  2. Отложенный вывод, чтобы избежать ошибки «headers already sent» (о данной ошибке подробно рассказано в статье Сессия)
  3. Работа с чужим кодом, который пытается самостоятельно что-то выводить
  4. Работа с HTML файлами: когда вам надо подключать текстовый файл (обычно речь о HTML), для дальнейшей работы с его содержимым

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

Системный буфер вывода

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

Вот так всё просто и кратко, ну а теперь о нюансах управления системным буфером вывода…

А теперь из академического интереса давайте рассмотрим реализацию данного «экшена» – там совсем чуть-чуть кода, и небольшая горстка полезных знаний по PHP:

echo "<h3>Please waiting for 10 seconds...</h3>";
 
for ($i = 1; $i <= 10; $i++) {
    echo $i;
    flush();
    sleep(1);
}
 
echo "<h3>Thx!</h3>";

Сразу бросается в глаза вызов функции flush() — вызвав данную функцию вы даёте указание PHP «сбросить» системный буфер, т.е. отправить всё что там есть в браузер пользователю (но учтите, если у вас стартован пользовательский буфер, то для начала надо будет «сбросить» его, и уже потом вызвать flush()). Т.е. происходящее можно описать как:

цикл на 10 итераций:
    - выводим число, вывод попадает в системный буфер
    - отправляем буфер пользователю в браузер
    - ждём секунду

Ещё одна особенность, о которой нужно помнить — директива implicit_flush, отвечает за то, чтобы после каждого вывода автоматически вызывался flush(), поэтому следующая комбинация сработает аналогично предыдущему примеру:

// .htaccess

php_flag implicit_flush on
for ($i = 1; $i <= 10; $i++) {
    echo $i;
    sleep(1);
}

Данную директиву можно изменять «на лету», для этого достаточно вызвать функцию ob_implicit_flush() (удивительное рядом, данную функцию стоило всё же назвать implicit_flush(), т.к. к пользовательскому буферу вывода она имеет опосредственное отношение — после вызова ob_flush() будет вызван flush()):

ob_implicit_flush();
for ($i = 1; $i <= 10; $i++) {
    echo $i;
    sleep(1);
}

Данные примеры работают только при выключенном output_buffering, иначе вам нужно будет его принудительно выключить и очистить в самом скрипте. Если же вы работаете в CLI, то знайте implicit_flush всегда включён, а output_buffering выключен, следовательно весь вывод будет без промедления попадать в консоль

Задание

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

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

$header = template('header', ['title' => 'Hello World!']);
$content = template('content', ['content' => "Lorem ipsum...", 'meta' => 'Author info']);
$footer = template('footer', ['copy' => "Copyright ". date('Y')]);
 
// ...skipped logic
 
echo $header, $content, $footer;
 
/**
 * @param  string $template
 * @param  array  $vars
 * @return string
 */
function template($template, $vars) {
    // place your code here
    // ...
}

Файлы шаблонов:

<!-- header.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><?=$title?></title>
</head>
<body>
<!-- content.phtml -->
<div class="container">
    <p><?=$content?></p>
    <p><?=$meta?></p>
</div>
<!-- footer.phtml -->
<footer>
    <?=$copy?>
</footer>
</body>
</html>

Исключени

NameSpace