mirror of
https://github.com/php/doc-ru.git
synced 2026-03-23 23:32:16 +01:00
1298 lines
50 KiB
XML
1298 lines
50 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 22583751fbfdaa3eaa41aeb6470d1343f5cb2c78 Maintainer: sergey Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<chapter xml:id="language.variables" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<title>Переменные</title>
|
||
|
||
<sect1 xml:id="language.variables.basics">
|
||
<title>Основы</title>
|
||
|
||
<simpara>
|
||
Переменные в PHP обозначаются знаком доллара, за которым идёт
|
||
имя переменной. Имя переменной чувствительно к регистру.
|
||
</simpara>
|
||
|
||
<para>
|
||
Правильное название переменной начинается с буквы в диапазонах
|
||
<literal>A-Z</literal> или <literal>a-z</literal>, ASCII-символа в диапазоне со 128-го по 255-й
|
||
байт или символа подчёркивания. Затем идёт произвольное количество букв, цифр или подчёркиваний.
|
||
В виде регулярного выражения правило именования переменных выражалось бы вот так:
|
||
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
PHP не поддерживает названия переменных в Юникоде, однако, отдельные кодировки
|
||
символов наподобие UTF-8 кодируют символы так, что каждый байт многобайтового символа
|
||
попадает в допустимый диапазон, поэтому такое название переменной
|
||
становится допустимым.
|
||
</simpara>
|
||
</note>
|
||
|
||
<note>
|
||
<simpara>
|
||
Переменная <literal>$this</literal> — специальная переменная, которой
|
||
нельзя присваивать значение.
|
||
До PHP 7.1.0 было возможно косвенное присваивание (например, через
|
||
<link linkend="language.variables.variable">переменные переменных</link>).
|
||
</simpara>
|
||
</note>
|
||
|
||
&tip.userlandnaming;
|
||
|
||
<example>
|
||
<title>Правильные названия переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$var = 'Боб';
|
||
$Var = 'Джо';
|
||
echo "$var, $Var"; // Инструкция выведет "Боб, Джо"
|
||
|
||
$_4site = 'ещё нет'; // Правильно; название переменной начинается с символа подчёркивания
|
||
$täyte = 'mansikka'; // Правильно; символ 'ä' — 228-я кодовая точка в кодировке Extended ASCII
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Неправильные названия переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$4site = 'not yet'; // Неправильно; название начинается с цифры
|
||
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
PHP принимает последовательность произвольных байтов как названия переменной.
|
||
Названия переменных, которые не соответствуют правилам именования,
|
||
доступны только динамически во время выполнения.
|
||
Раздел «<link linkend="language.variables.variable">Переменные переменных</link>»
|
||
рассказывает, как получить доступ к переменным переменных.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Доступ к неизвестным именам переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
${'invalid-name'} = 'bar';
|
||
$name = 'invalid-name';
|
||
echo ${'invalid-name'}, " ", $$name;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
bar bar
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<para>
|
||
По умолчанию переменные присваиваются по значению. Поэтому
|
||
когда переменной присваивают выражение, значение
|
||
исходного выражения копируется в целевую переменную. Это
|
||
означает, например, что после присваивания значения одной переменной
|
||
другой переменной, изменение одной переменной не повлияет
|
||
на другую. Дополнительную информацию об этом способе присваивания
|
||
смотрите в разделе «<link linkend="language.expressions">Выражения</link>».
|
||
</para>
|
||
<para>
|
||
PHP также предлагает другой способ присваивания значений переменным:
|
||
<link linkend="language.references">присваивание по ссылке</link>.
|
||
Это означает, что новая переменная просто ссылается (иначе говоря,
|
||
«становится псевдонимом» или «указывает») на оригинальную
|
||
переменную. Изменения в новой переменной отражаются на оригинале,
|
||
и наоборот.
|
||
</para>
|
||
<para>
|
||
Для присваивания по ссылке к началу имени присваиваемой (исходной) переменной
|
||
просто добавляют амперсанд &. Например,
|
||
следующий фрагмент кода дважды выводит «<literal>Меня зовут Боб</literal>»:
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$foo = 'Боб'; // Присваивает переменной $foo значение «Боб»
|
||
$bar = &$foo; // Ссылка на значение переменной $foo через переменную $bar
|
||
$bar = "Меня зовут $bar"; // Изменение значения переменной $bar...
|
||
echo $bar;
|
||
echo $foo; // ...меняет и значение переменной $foo
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Важно отметить, что по ссылке присваиваются только переменные.
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$foo = 25;
|
||
$bar = &$foo; // Это верное присваивание
|
||
$bar = &(24 * 7); // Неверно; ссылка на неименованное выражение
|
||
|
||
function test()
|
||
{
|
||
return 25;
|
||
}
|
||
|
||
$bar = &test(); // Неверно, потому что функция test() не возвращает переменную по ссылке
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
PHP не требует объявлять переменные, хотя рекомендует.
|
||
Доступ к неопределённой переменной до PHP 8.0.0 выдавал
|
||
уведомление <constant>E_NOTICE</constant>, а в новых версиях языка
|
||
выдаёт предупреждение <constant>E_WARNING</constant>.
|
||
Неопределённая переменная по умолчанию содержит значение &null;.
|
||
Языковая конструкция <function>isset</function> помогает определить,
|
||
инициализировали ли переменную; конструкция считает переменную инициализированной,
|
||
если значение переменной не равняется &null;.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Значение по умолчанию в неинициализированной переменной</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Пример переменной, которую не установили и (!) не упомянули в строковом,
|
||
// логическом, целочисленном или другом контексте
|
||
var_dump($unset_var);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Warning: Undefined variable $unset_var in ...
|
||
NULL
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
</para>
|
||
|
||
<simpara>
|
||
PHP разрешает автовивификацию массивов из неопределённых переменных.
|
||
Автовивификация (букв.: автоматическое оживление) — операция, при которой
|
||
новый массив создаётся автоматически при добавлении в него значения.
|
||
Добавление элемента к неопределенной переменной создаст новый массив
|
||
и не вызовет предупреждения.
|
||
</simpara>
|
||
<example>
|
||
<title>Автовивификация массива из неопределённой переменной</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$unset_array[] = 'value'; // Предупреждение не выдаётся
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Нельзя рассчитывать, что неинициализированная переменная сохранит значение по умолчанию
|
||
при включении одного файла в другой, поскольку появляется риск того, что неинициализированная переменная
|
||
получит значение переменной другого файла, если в файлах встретятся переменные с одинаковым названием.
|
||
</simpara>
|
||
</warning>
|
||
|
||
<simpara>
|
||
Переменную уничтожают языковой конструкцией <function>unset</function>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Подробнее о функциях работы с переменными рассказывает раздел
|
||
«<link linkend="ref.var">Функции обработки переменных</link>».
|
||
</simpara>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.variables.predefined">
|
||
<title>Предопределённые переменные</title>
|
||
|
||
<para>
|
||
PHP предлагает набор
|
||
<link linkend="reserved.variables">предопределённых переменных</link>,
|
||
и набор предопределённых массивов, в которых содержатся переменные веб-сервера
|
||
если контекст взаимодействия предполагает такие переменные, переменные окружения
|
||
и переменные пользовательского ввода. Доступ к этим массивам открывается из каждой области видимости.
|
||
Поэтому эти массивы называются «суперглобальными». В PHP нет механизма для пользовательских
|
||
суперглобальных переменных. Раздел
|
||
«<link linkend="language.variables.superglobals">Суперглобальные переменные</link>»
|
||
приводит список и подробнее рассказывает о суперглобальных массивах.
|
||
</para>
|
||
|
||
<note>
|
||
<title>Переменные переменных</title>
|
||
<para>
|
||
Суперглобальные переменные нельзя использовать
|
||
как <link linkend="language.variables.variable">переменные переменных</link>
|
||
внутри функций или методов класса.
|
||
</para>
|
||
</note>
|
||
|
||
<para>
|
||
Предопределённые массивы, которые соответствуют переменным,
|
||
останутся пустыми, если какие-то переменные не установили в директиве
|
||
<link linkend="ini.variables-order">variables_order</link>.
|
||
</para>
|
||
</sect1>
|
||
|
||
|
||
<sect1 xml:id="language.variables.scope">
|
||
<title>Область видимости переменной</title>
|
||
|
||
<simpara>
|
||
Область видимости переменной — контекст, в котором определили переменную.
|
||
В PHP предусмотрели область видимости функции и глобальную область видимости.
|
||
Переменная, которую определили за пределами функции, ограничивается глобальной областью видимости.
|
||
Код включаемого файла наследует ту же область видимости переменных,
|
||
что и строка, на которой включается файл.
|
||
</simpara>
|
||
<example>
|
||
<title>Пример глобальной области видимости переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1;
|
||
include 'b.inc'; // Код внутри файла b.inc получит доступ к переменной $a
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
Переменная, которую создали внутри именованной
|
||
или <link linkend="functions.anonymous">анонимной</link> функции,
|
||
ограничивается областью видимости тела функции.
|
||
<link linkend="functions.arrow">Стрелочные функции</link> вместо этого
|
||
связывают переменные родительской области видимости и переменные становятся доступны в теле стрелочной функции.
|
||
При включении файла внутри функции переменные, которые содержатся во включаемом файле,
|
||
будут доступны так, как будто переменные определили внутри вызывающей функции.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Пример локальной области видимости переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1; // Определяем переменную $a в глобальной области видимости
|
||
|
||
function test()
|
||
{
|
||
echo $a; // Переменная $a не определена, поскольку конструкция echo указывает на локальную версию переменной $a
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
До PHP 8.0.0 при вызове функции приведённый пример сгенерирует ошибку уровня <constant>E_NOTICE</constant>
|
||
о неопределённой переменной, а в новых версиях ошибку уровня <constant>E_WARNING</constant>.
|
||
Причина ошибки состоит в том, что языковая конструкция echo указывает на локальную версию переменной
|
||
<varname>$a</varname>, а переменной не присвоили значение в локальной области видимости.
|
||
Обратите внимание, поведение переменных отличается от языка C в том, что глобальные переменные в C
|
||
автоматически доступны функциям, если только глобальную переменную
|
||
не перезаписали локальным определением. Несовпадение поведения иногда вызывает проблемы
|
||
при непреднамеренном изменении глобальной переменной.
|
||
В PHP глобальные переменные потребуется объявить глобальными
|
||
внутри функции, если функция будет использовать эти переменные.
|
||
</simpara>
|
||
|
||
<sect2 xml:id="language.variables.scope.global">
|
||
<title>Ключевое слово <literal>global</literal></title>
|
||
<simpara>
|
||
Ключевое слово <literal>global</literal> связывает переменную
|
||
глобальной области видимости с локальной областью действия переменной. Ключевое слово
|
||
принимает отдельную переменную или список переменных. Ключевое слово создаст
|
||
локальную переменную, которая ссылается на глобальную переменную с тем же названием.
|
||
Ключевое слово создаст переменную в глобальной области видимости со значением &null;,
|
||
если переменную не установили в глобальной области действия переменной.
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>Пример поведения ключевого слова <literal>global</literal></title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1;
|
||
$b = 2;
|
||
|
||
function Sum()
|
||
{
|
||
global $a, $b;
|
||
|
||
$b = $a + $b;
|
||
}
|
||
|
||
Sum();
|
||
echo $b;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
3
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
</para>
|
||
|
||
<simpara>
|
||
При объявлении переменных <varname>$a</varname> и <varname>$b</varname>
|
||
глобальными внутри функции ссылки на эти переменные будут указывать на глобальную
|
||
версию. Количество глобальных переменных,
|
||
которыми умеет манипулировать функция, не ограничивается.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Второй способ доступа к переменным глобальной области видимости —
|
||
суперглобальный PHP-массив <varname>$GLOBALS</varname>. Перепишем
|
||
предыдущий пример так:
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>
|
||
Работа с суперглобальной переменной <varname>$GLOBALS</varname>
|
||
вместо ключевого слова global
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1;
|
||
$b = 2;
|
||
|
||
function Sum()
|
||
{
|
||
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
|
||
}
|
||
|
||
Sum();
|
||
echo $b;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<simpara>
|
||
Массив <varname>$GLOBALS</varname> — ассоциативный массив,
|
||
в котором ключ представляет название глобальной переменной,
|
||
а значение элемента массива — содержимое переменной.
|
||
Обратите внимание, суперглобальная переменная
|
||
<varname>$GLOBALS</varname> доступна в любой области видимости,
|
||
причина состоит в том, что <varname>$GLOBALS</varname> —
|
||
<link linkend="language.variables.superglobals">суперглобальная переменная</link>.
|
||
Пример ниже показывает силу суперглобальных переменных:
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>Суперглобальные переменные и область видимости</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function test_superglobal()
|
||
{
|
||
echo $_POST['name'];
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<note>
|
||
<simpara>
|
||
Не будет ошибкой, если указать ключевое слово <literal>global</literal>
|
||
вне функции, например в файле, который включается внутри функции другого файла.
|
||
</simpara>
|
||
</note>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.scope.static">
|
||
<title>
|
||
Переменные, которые определили через ключевое слово <literal>static</literal>
|
||
</title>
|
||
<simpara>
|
||
Другая важная особенность области видимости переменной —
|
||
<emphasis>статическая</emphasis> переменная. Статическая
|
||
переменная доступна только в локальной области видимости
|
||
функции, но не теряет своего значения, когда выполнение программы
|
||
выходит из этой области видимости. Рассмотрим следующий пример:
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>
|
||
Пример показывает, когда требуется статическая переменная
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function test()
|
||
{
|
||
$a = 0;
|
||
echo $a;
|
||
$a++;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<simpara>
|
||
Эта функция бесполезна, поскольку при каждом вызове
|
||
устанавливает для переменной <varname>$a</varname> значение <literal>0</literal>
|
||
и выводит <literal>0</literal>. Инкремент переменной <varname>$a</varname>++
|
||
здесь не играет роли, поскольку при выходе из функции переменная
|
||
<varname>$a</varname> исчезает. Чтобы написать полезную
|
||
функцию подсчёта, которая не потеряет текущего значения счётчика,
|
||
переменную <varname>$a</varname> объявляют статической:
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>Пример со статической переменной</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function test()
|
||
{
|
||
static $a = 0;
|
||
echo $a;
|
||
$a++;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<simpara>
|
||
Теперь функция проинициализирует переменную <varname>$a</varname> только
|
||
при первом вызове, а при каждом вызове функция <literal>test()</literal>
|
||
будет выводить значение переменной <varname>$a</varname>, а затем инкрементировать
|
||
значение.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Со статическими переменными также работают в рекурсивных функциях.
|
||
Следующая функция рекурсивно считает до 10, а статическая переменная
|
||
<varname>$count</varname> помогает определить момент остановки:
|
||
</simpara>
|
||
<para>
|
||
<example>
|
||
<title>Статические переменные и рекурсивные функции</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function test()
|
||
{
|
||
static $count = 0;
|
||
|
||
$count++;
|
||
echo $count;
|
||
|
||
if ($count < 10) {
|
||
test();
|
||
}
|
||
|
||
$count--;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
До PHP 8.3.0 статические переменные разрешалось инициализировать
|
||
только константными выражениями. С PHP 8.3.0 также разрешили
|
||
динамические выражения наподобие вызовов функций:
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Объявление статических переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function foo()
|
||
{
|
||
static $int = 0; // Правильно
|
||
static $int = 1 + 2; // Правильно
|
||
static $int = sqrt(121); // Правильно с PHP 8.3.0
|
||
|
||
$int++;
|
||
echo $int;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<simpara>
|
||
Статические переменные внутри анонимных функций сохраняются только внутри этого
|
||
конкретного экземпляра функции. Статическая переменная переинициализируется,
|
||
если анонимная функция воссоздаётся при каждом вызове.
|
||
</simpara>
|
||
<example>
|
||
<title>Статические переменные в анонимных функциях</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function exampleFunction($input)
|
||
{
|
||
$result = (static function () use ($input) {
|
||
static $counter = 0;
|
||
$counter++;
|
||
return "Функция получила значение: $input, счётчик: $counter\n";
|
||
});
|
||
|
||
return $result();
|
||
}
|
||
|
||
// Вызов функции exampleFunction пересоздаст анонимную функцию, поэтому статическая
|
||
// переменная не сохранит значение
|
||
echo exampleFunction('A'); // Выводит: Функция получила значение: A, счётчик: 1
|
||
echo exampleFunction('B'); // Выводит: Функция получила значение: B, счётчик: 1
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Начиная с PHP 8.1.0 при наследовании, но не переопределении, метода
|
||
со статическими переменными унаследованный метод будет использовать
|
||
статические переменные совместно с родительским методом.
|
||
Поэтому статические переменные в методах теперь ведут себя
|
||
как статические свойства класса.
|
||
</para>
|
||
|
||
<simpara>
|
||
Начиная PHP 8.3.0 статические переменные разрешили инициализировать произвольными выражениями.
|
||
Поэтому статическую переменную получится инициализировать, например, вызовом метода.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>
|
||
Статические переменные в унаследованных методах
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class Foo
|
||
{
|
||
public static function counter()
|
||
{
|
||
static $counter = 0;
|
||
$counter++;
|
||
return $counter;
|
||
}
|
||
}
|
||
|
||
class Bar extends Foo {}
|
||
|
||
var_dump(Foo::counter()); // int(1)
|
||
var_dump(Foo::counter()); // int(2)
|
||
var_dump(Bar::counter()); // int(3), до PHP 8.1.0 int(1)
|
||
var_dump(Bar::counter()); // int(4), до PHP 8.1.0 int(2)
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.scope.references">
|
||
<title>
|
||
Ссылки с глобальными (<literal>global</literal>)
|
||
и статическими (<literal>static</literal>) переменными
|
||
</title>
|
||
<simpara>
|
||
PHP использует модификаторы переменных
|
||
<link linkend="language.variables.scope.static">static</link> и
|
||
<link linkend="language.variables.scope.global">global</link> как
|
||
<link linkend="language.references">ссылки</link>. Например, реальная
|
||
глобальная переменная, которую внедрили в область видимости функции
|
||
через ключевое слово <literal>global</literal>, в действительности создаёт
|
||
ссылку на глобальную переменную. Это приводит к неожиданному
|
||
поведению, как показывает следующий пример:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function test_global_ref()
|
||
{
|
||
global $obj;
|
||
$new = new stdClass();
|
||
$obj = &$new;
|
||
}
|
||
|
||
function test_global_noref()
|
||
{
|
||
global $obj;
|
||
$new = new stdClass();
|
||
$obj = $new;
|
||
}
|
||
|
||
test_global_ref();
|
||
var_dump($obj);
|
||
test_global_noref();
|
||
var_dump($obj);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
&example.outputs;
|
||
|
||
<screen>
|
||
<![CDATA[
|
||
NULL
|
||
object(stdClass)#1 (0) {
|
||
}
|
||
]]>
|
||
</screen>
|
||
|
||
<simpara>
|
||
Аналогично ведёт себя и инструкция <literal>static</literal>. Ссылки не
|
||
хранятся статично:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function &get_instance_ref()
|
||
{
|
||
static $obj;
|
||
|
||
echo 'Статический объект: ';
|
||
var_dump($obj);
|
||
|
||
if (!isset($obj)) {
|
||
$new = new stdClass();
|
||
|
||
// Присвоить ссылку статической переменной
|
||
$obj = &$new;
|
||
}
|
||
|
||
if (!isset($obj->property)) {
|
||
$obj->property = 1;
|
||
} else {
|
||
$obj->property++;
|
||
}
|
||
|
||
return $obj;
|
||
}
|
||
|
||
function &get_instance_noref()
|
||
{
|
||
static $obj;
|
||
|
||
echo 'Статический объект: ';
|
||
|
||
var_dump($obj);
|
||
|
||
if (!isset($obj)) {
|
||
$new = new stdClass();
|
||
|
||
// Присвоить объект статической переменной
|
||
$obj = $new;
|
||
}
|
||
|
||
if (!isset($obj->property)) {
|
||
$obj->property = 1;
|
||
} else {
|
||
$obj->property++;
|
||
}
|
||
|
||
return $obj;
|
||
}
|
||
|
||
$obj1 = get_instance_ref();
|
||
$still_obj1 = get_instance_ref();
|
||
echo "\n";
|
||
$obj2 = get_instance_noref();
|
||
$still_obj2 = get_instance_noref();
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Статический объект: NULL
|
||
Статический объект: NULL
|
||
|
||
Статический объект: NULL
|
||
Статический объект: object(stdClass)#3 (1) {
|
||
["property"]=>
|
||
int(1)
|
||
}
|
||
]]>
|
||
</screen>
|
||
|
||
<simpara>
|
||
Пример показывает, что при назначении ссылки статической
|
||
переменной эта переменная <emphasis>не запоминается</emphasis>,
|
||
при повторном вызове функции <literal>&get_instance_ref()</literal>.
|
||
</simpara>
|
||
</sect2>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.variables.variable">
|
||
<title>Переменные переменных</title>
|
||
|
||
<simpara>
|
||
Иногда переменные имена переменных повышают удобство работы с кодом.
|
||
Переменное имя переменной — имя переменной, которое устанавливается и изменяется
|
||
динамически. Стандартную переменную устанавливают вот такой инструкцией:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 'hello';
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Переменная переменной принимает значение переменной и обрабатывает
|
||
значение как имя переменной. Значение <emphasis>hello</emphasis> из приведённого примера
|
||
станет именем переменной при обращении к переменной, которая хранит значение,
|
||
через двойной знак доллара.
|
||
То есть:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$$a = 'world';
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Теперь дерево символов PHP хранит два определения переменных:
|
||
переменная <varname>$a</varname>, которая содержит значение "hello",
|
||
и переменная <varname>$hello</varname>, которая содержит значение "world".
|
||
Поэтому инструкция:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo "{$a} {$$a}";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
...выведет то же, что и инструкция
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo "{$a} {$hello}";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Обе инструкции создадут строку: <computeroutput>hello world</computeroutput>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Для работы с переменными переменных и массивами потребуется разрешить неоднозначность.
|
||
Анализатору синтаксиса требуется знать, что имел в виду разработчик
|
||
в записи <varname>$$a[1]</varname>: использовать <varname>$a[1]</varname> как переменную
|
||
или <varname>$$a</varname>, а затем индекс [1] этой переменной.
|
||
Синтаксис, который разрешит эту неоднозначность, выглядит вот так:
|
||
<varname>${$a[1]}</varname> для первого случая и <varname>${$a}[1]</varname> для второго.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Доступ к свойствам класса также получают через переменные имена свойств.
|
||
Переменное имя свойства разрешается внутри области видимости, в которой
|
||
вызывают свойство класса. Например, для выражения <varname>$foo->$bar</varname>
|
||
PHP проверит присутствие в локальной области видимости переменной <varname>$bar</varname>,
|
||
значение которой возьмёт как имя свойства объекта <varname>$foo</varname>.
|
||
Это справедливо и тогда, когда через переменную <varname>$bar</varname> обращаются
|
||
к элементу массива.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Фигурные скобки также указывают, чтобы точно отделить название свойства.
|
||
Скобки наиболее полезны, когда получают доступ к значениям внутри свойства,
|
||
которое содержит массив, когда имя свойства состоит из нескольких частей,
|
||
либо когда имя свойства содержит символы, которые иначе не
|
||
действительны (например, из функции <function>json_decode</function>
|
||
или из модуля <link linkend="book.simplexml">SimpleXML</link>).
|
||
</simpara>
|
||
|
||
<para>
|
||
<example>
|
||
<title>Пример переменного имени свойства</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class Foo
|
||
{
|
||
public $bar = 'Я bar.';
|
||
public $arr = array('Я A.', 'Я B.', 'Я C.');
|
||
public $r = 'Я r.';
|
||
}
|
||
|
||
$foo = new Foo();
|
||
$bar = 'bar';
|
||
$baz = ['foo', 'bar', 'baz', 'quux'];
|
||
echo $foo->$bar . "\n";
|
||
echo $foo->{$baz[1]} . "\n";
|
||
|
||
$start = 'b';
|
||
$end = 'ar';
|
||
echo $foo->{$start . $end} . "\n";
|
||
|
||
$arr = 'arr';
|
||
echo $foo->{$arr[1]} . "\n";
|
||
echo $foo->{$arr}[1] . "\n";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Я bar.
|
||
Я bar.
|
||
Я bar.
|
||
Я r.
|
||
Я B.
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
</para>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Обратите внимание, переменные переменных нельзя использовать
|
||
с <link linkend="language.variables.superglobals">суперглобальными массивами</link>
|
||
PHP. Переменная <literal>$this</literal> — тоже специальная переменная,
|
||
на которую нельзя ссылаться динамически.
|
||
</simpara>
|
||
</warning>
|
||
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.variables.external">
|
||
<title>Переменные из внешних источников</title>
|
||
|
||
<sect2 xml:id="language.variables.external.form">
|
||
<title>HTML-формы. Методы GET и POST</title>
|
||
|
||
<simpara>
|
||
PHP-скрипт автоматически получает доступ к данным формы
|
||
после отправки формы скрипту.
|
||
Данные формы получают несколькими способами, например:
|
||
</simpara>
|
||
|
||
<para>
|
||
<example>
|
||
<title>Простая HTML-форма</title>
|
||
<programlisting role="html">
|
||
<![CDATA[
|
||
<form action="foo.php" method="post">
|
||
Имя: <input type="text" name="username" /><br />
|
||
Email: <input type="text" name="email" /><br />
|
||
<input type="submit" name="submit" value="Отправь меня!" />
|
||
</form>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
Доступ к данным HTML-формы получают только двумя способами.
|
||
Следующие параграфы перечисляют эти способы:
|
||
</para>
|
||
|
||
<para>
|
||
<example>
|
||
<title>
|
||
Доступ к данным несложной HTML-формы, которую отправили методом POST
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo $_POST['username'];
|
||
echo $_REQUEST['username'];
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
GET-формы обрабатывают аналогично, за исключением того, что вместо
|
||
суперглобальной переменной POST обрабатывают предопределённую
|
||
суперглобальную переменную GET.
|
||
Суперглобальная переменная GET также умеет работать с элементом
|
||
<literal>QUERY_STRING</literal>
|
||
(информация в URL-адресе после знака вопроса «?»). Так, например,
|
||
адрес <literal>http://www.example.com/test.php?id=3</literal> содержит
|
||
GET-данные, к которым получают доступ через <varname>$_GET['id']</varname>.
|
||
О переменных HTTP-запроса рассказывает раздел <varname>$_REQUEST</varname>.
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
Точки и пробелы в именах переменных преобразовываются в знаки
|
||
подчёркивания. Например, <literal><input name="a.b" /></literal> станет
|
||
<literal>$_REQUEST["a_b"]</literal>.
|
||
</para>
|
||
</note>
|
||
|
||
<simpara>
|
||
PHP также понимает массивы в контексте переменных формы
|
||
(смотрите раздел <link linkend="faq.html">PHP и HTML</link>).
|
||
Связанные переменные, например, группируют по имени
|
||
или получают значения из полей ввода с множественным выбором.
|
||
Отправим форму сами себе и отобразим данные:
|
||
</simpara>
|
||
|
||
<para>
|
||
<example>
|
||
<title>Более сложные переменные формы</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
if ($_POST) {
|
||
echo '<pre>';
|
||
echo htmlspecialchars(print_r($_POST, true));
|
||
echo '</pre>';
|
||
}
|
||
|
||
?>
|
||
<form action="" method="post">
|
||
Имя: <input type="text" name="personal[name]" /><br />
|
||
Email: <input type="text" name="personal[email]" /><br />
|
||
Пиво: <br />
|
||
<select multiple name="beer[]">
|
||
<option value="warthog">Warthog</option>
|
||
<option value="guinness">Guinness</option>
|
||
<option value="stuttgarter">Stuttgarter Schwabenbräu</option>
|
||
</select><br />
|
||
<input type="submit" value="Отправь меня!" />
|
||
</form>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
PHP без предупреждения проигнорирует конечные символы,
|
||
если имя внешней переменной начинается с корректного синтаксиса массива.
|
||
Например, <literal><input name="foo[bar]baz"></literal>
|
||
станет <literal>$_REQUEST['foo']['bar']</literal>.
|
||
</simpara>
|
||
</note>
|
||
|
||
<sect3 xml:id="language.variables.external.form.submit">
|
||
<title>
|
||
Имена переменных кнопки с картинкой для отправки формы
|
||
</title>
|
||
|
||
<simpara>
|
||
Чтобы у формы вместо стандартной кнопки отправки
|
||
появилось изображение, формируют тег наподобие такого:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="html">
|
||
<![CDATA[
|
||
<input type="image" src="image.gif" name="sub" />
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Когда пользователь щёлкнет по изображению,
|
||
браузер передаст форму на сервер с двумя
|
||
дополнительными переменными — <varname>sub_x</varname> и <varname>sub_y</varname>.
|
||
Эти переменные содержат координаты места, по которому пользователь нажал на изображении.
|
||
Программисты с опытом, наверное, заметили, что имена переменных,
|
||
которые отправил браузер, содержат точку, а не подчёркивание,
|
||
но PHP автоматически преобразует точку в подчёркивание.
|
||
</simpara>
|
||
</sect3>
|
||
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.external.cookies">
|
||
<title>HTTP Cookies</title>
|
||
|
||
<simpara>
|
||
PHP прозрачно поддерживает блоки данных cookies по HTTP-протоколу в соответствии с требованиями стандарта
|
||
<link xlink:href="&url.rfc;6265">RFC 6265</link>. Cookies —
|
||
механизм хранения данных в удалённом браузере, по которым сервер отслеживает
|
||
или идентифицирует пользователей, которые вернулись на сайт.
|
||
Cookies устанавливают функцией <function>setcookie</function>.
|
||
Cookies — часть HTTP-заголовка, поэтому функцию SetCookie
|
||
требуется вызывать перед отправкой вывода браузеру.
|
||
Это же ограничение касается функции <function>header</function>.
|
||
Данные, которые хранят cookie, доступны
|
||
в массивах данных cookie наподобие суперглобальных переменных <varname>$_COOKIE</varname>
|
||
или <varname>$_REQUEST</varname>. Подробности и примеры
|
||
даёт описание функции <function>setcookie</function>.
|
||
</simpara>
|
||
|
||
<note>
|
||
<simpara>
|
||
Начиная с PHP 7.2.34, 7.3.23 и 7.4.11 по соображениям безопасности
|
||
<emphasis>имена</emphasis> входящих cookie больше не декодируются
|
||
из URL-кодированной строки.
|
||
</simpara>
|
||
</note>
|
||
|
||
<simpara>
|
||
Когда одной переменной cookie требуется присвоить больше одного значения,
|
||
значения присваивают как массив. Например:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
setcookie("MyCookie[foo]", 'Testing 1', time() + 3600);
|
||
setcookie("MyCookie[bar]", 'Testing 2', time() + 3600);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Такой вызов создаст два разных блока данных cookie, хотя в скрипте
|
||
переменная <varname>MyCookie</varname> теперь будет одним массивом.
|
||
Если требуется установить только один блок данных cookie
|
||
с несколькими значениями, сначала обдумывают
|
||
вызов для таких значений функции наподобие <function>serialize</function>
|
||
или <function>explode</function>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Обратите внимание, что блок данных cookie заменит в браузере предыдущий
|
||
блок данных cookie с тем же именем, если только путь или домен не отличаются.
|
||
Так в приложении с корзиной покупок можно сохранить количество товаров:
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Пример использования функции <function>setcookie</function></title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
if (isset($_COOKIE['count'])) {
|
||
$count = $_COOKIE['count'] + 1;
|
||
} else {
|
||
$count = 1;
|
||
}
|
||
|
||
setcookie('count', $count, time() + 3600);
|
||
setcookie("Cart[$count]", $item, time() + 3600);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.external.dot-in-names">
|
||
<title>Точки в именах входящих переменных</title>
|
||
|
||
<para>
|
||
PHP, как правило, не изменяет имена переменных, которые передали скрипту.
|
||
Однако следует отметить, что точка — неправильный символ
|
||
в имени переменной PHP. Поэтому рассмотрим такую запись:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$varname.ext; /* Неправильное имя переменной */
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
В приведённом примере интерпретатор видит переменную
|
||
<varname>$varname</varname>, после которой идёт оператор
|
||
конкатенации, а затем голая строка (то есть строка, которую не заключили
|
||
в кавычки, и которая не соответствует ни одному из ключевых или
|
||
зарезервированных слов) «ext». Очевидно, что это не даст ожидаемого результата.
|
||
</para>
|
||
|
||
<para>
|
||
Поэтому важно отметить, что PHP будет автоматически
|
||
заменять точки в именах входящих переменных на символы
|
||
подчёркивания.
|
||
</para>
|
||
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.determining-type-of">
|
||
<title>Определение типов переменных</title>
|
||
|
||
<para>
|
||
Поскольку PHP определяет типы переменных и преобразовывает типы (как правило)
|
||
по мере необходимости, не всегда очевидно, какому типу принадлежит переменная
|
||
в каждый момент времени. PHP содержит несколько функций, которые умеют
|
||
определять тип переменной, например: <function>gettype</function>,
|
||
<function>is_array</function>, <function>is_float</function>,
|
||
<function>is_int</function>, <function>is_object</function>
|
||
и <function>is_string</function>. Подробнее о типах данных, которые
|
||
поддерживает PHP, рассказывает раздел
|
||
«<link linkend="language.types">Типы</link>».
|
||
</para>
|
||
<para>
|
||
HTTP — текстовый протокол, и большая, если не вся, часть содержимого,
|
||
которое попадает в <link linkend="language.variables.superglobals">суперглобальные массивы</link>
|
||
наподобие <varname>$_POST</varname> и <varname>$_GET</varname>, останется в виде строк.
|
||
PHP не будет преобразовывать значения в конкретный тип.
|
||
В приведённом примере элемент <varname>$_GET["var1"]</varname>
|
||
будет содержать строку «null», а элемент <varname>$_GET["var2"]</varname> — строку «123».
|
||
<programlisting>
|
||
<![CDATA[
|
||
/index.php?var1=null&var2=123
|
||
]]>
|
||
</programlisting>
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.variables.external.changelog">
|
||
&reftitle.changelog;
|
||
|
||
<para>
|
||
<informaltable>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>&Version;</entry>
|
||
<entry>&Description;</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry>7.2.34, 7.3.23, 7.4.11</entry>
|
||
<entry>
|
||
По соображениям безопасности <emphasis>имена</emphasis>
|
||
входящих cookie больше не декодируются из URL-кодированной строки.
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
</para>
|
||
</sect2>
|
||
|
||
</sect1>
|
||
|
||
</chapter>
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|