mirror of
https://github.com/php/doc-ru.git
synced 2025-07-22 18:26:31 +00:00
1222 lines
46 KiB
XML
1222 lines
46 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 5700871f9d037a59d137be318f89deb7e146bbf6 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>
|
||
Имена переменных соответствуют тем же правилам, что и
|
||
остальные наименования в PHP. Правильное имя переменной
|
||
начинается с буквы или символа подчёркивания и состоит из
|
||
букв, цифр и символов подчёркивания в любом количестве.
|
||
Это можно отобразить регулярным выражением:
|
||
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
Под буквами здесь подразумеваются символы a-z, A-Z и байты от
|
||
128 до 255 (<literal>0x80-0xff</literal>).
|
||
</simpara>
|
||
</note>
|
||
|
||
<note>
|
||
<simpara>
|
||
Переменная <literal>$this</literal> — специальная переменная, которой
|
||
нельзя ничего присваивать.
|
||
До PHP 7.1.0 было возможно косвенное присваивание (например, через
|
||
<link linkend="language.variables.variable">переменные переменных</link>).
|
||
</simpara>
|
||
</note>
|
||
|
||
&tip.userlandnaming;
|
||
|
||
<para>
|
||
Информацию о функциях работы с переменными
|
||
даёт раздел
|
||
<link linkend="ref.var">функции работы с переменными</link>.
|
||
</para>
|
||
|
||
<para>
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$var = 'Боб';
|
||
$Var = 'Джо';
|
||
echo "$var, $Var"; // Выведет "Боб, Джо"
|
||
|
||
$4site = 'ещё нет'; // Неверно; начинается с цифры
|
||
$_4site = 'ещё нет'; // Верно; начинается с символа подчёркивания
|
||
$täyte = 'mansikka'; // Верно; 'ä' это (Расширенный) ASCII 228.
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<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(); // Неверно
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Хорошей практикой считается инициализировать переменные, хотя в PHP
|
||
это не обязательное требование. Неинициализированные переменные
|
||
принимают значение по умолчанию своего типа, который зависит
|
||
от контекста, в котором встречается переменная: логические переменные
|
||
принимают значение &false;, целые числа и числа с плавающей точкой —
|
||
ноль, строки (например, при вызове с конструкцией <function>echo</function>) —
|
||
пустую строку, а массивы становятся пустыми массивами.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Значения по умолчанию в неинициализированных переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Неустановленная И без ссылок (то есть без контекста использования) переменная; выведет NULL
|
||
var_dump($unset_var);
|
||
|
||
// Логический контекст; выведет 'false' (Подробнее
|
||
// об этом синтаксисе рассказывает раздел о тернарном операторе)
|
||
echo $unset_bool ? "true\n" : "false\n";
|
||
|
||
// Строковый контекст; выведет 'string(3) "abc"'
|
||
$unset_str .= 'abc';
|
||
var_dump($unset_str);
|
||
|
||
// Целочисленный контекст; выведет 'int(25)'
|
||
$unset_int += 25; // 0 + 25 => 25
|
||
var_dump($unset_int);
|
||
|
||
// Контекст числа с плавающей точкой (float); выведет 'float(1.25)'
|
||
$unset_float += 1.25;
|
||
var_dump($unset_float);
|
||
|
||
// Контекст массива; выведет array(1) { [3]=> string(3) "def" }
|
||
$unset_arr[3] = "def"; // array() + array(3 => "def") => array(3 => "def")
|
||
var_dump($unset_arr);
|
||
|
||
// Контекст объекта; создаёт новый объект stdClass (смотрите http://www.php.net/manual/ru/reserved.classes.php)
|
||
// Выведет: object(stdClass)#1 (1) { ["foo"]=> string(3) "bar" }
|
||
$unset_obj->foo = 'bar';
|
||
var_dump($unset_obj);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Полагаться на значения по умолчанию неинициализированных переменных
|
||
проблематично при включении одного файла в другой,
|
||
который использует переменную с таким же именем.
|
||
При работе с неинициализированной переменной выдаётся ошибка уровня
|
||
<constant>E_WARNING</constant> (до PHP 8.0.0 выдавалась ошибка уровня <constant>E_NOTICE</constant>),
|
||
но не при добавлении элементов в неинициализированный массив.
|
||
Определять, инициализировали ли переменную, помогает языковая конструкция <function>isset</function>.
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.variables.predefined">
|
||
<title>Предопределённые переменные</title>
|
||
|
||
<para>
|
||
Любому запускаемому скрипту PHP даёт большое количество
|
||
предопределённых переменных. Однако многие из этих переменных
|
||
нельзя полностью задокументировать, поскольку переменные зависят
|
||
от сервера, который запускает скрипт, его версии и настроек, а также других факторов.
|
||
Часть этих переменных недоступна, когда PHP запустили
|
||
из <link linkend="features.commandline">командной строки</link>.
|
||
Раздел «<link linkend="reserved.variables">Предопределённые переменные</link>»
|
||
даёт дополнительную информацию.
|
||
</para>
|
||
|
||
<para>
|
||
PHP даёт дополнительный набор
|
||
предопределённых массивов, которые содержат переменные сервера (если
|
||
они доступны), окружения и пользовательского ввода. Эти
|
||
массивы особенные, поскольку они становятся глобальными автоматически —
|
||
то есть автоматически доступны в любой области видимости. По этой
|
||
причине эти массивы также известны как «суперглобальные
|
||
переменные». (В 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 только одна область
|
||
видимости. Эта единая область видимости охватывает также файлы,
|
||
которые включили в скрипт выражениями <function>include</function> и <function>require</function>.
|
||
Например:
|
||
</simpara>
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1;
|
||
include 'b.inc';
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<simpara>
|
||
Здесь переменная <varname>$a</varname> будет доступна внутри
|
||
включённого скрипта <filename>b.inc</filename>. Однако определение (тело)
|
||
пользовательской функции задаёт локальную область видимости данной функции.
|
||
Переменная внутри функции по умолчанию ограничена локальной областью видимости функции.
|
||
Например:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 1; /* Глобальная область видимости */
|
||
|
||
function test()
|
||
{
|
||
echo $a; /* Ссылка на переменную в локальной области видимости */
|
||
}
|
||
|
||
test();
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Этот скрипт сгенерирует неопределенную переменную
|
||
<constant>E_WARNING</constant> (или <constant>E_NOTICE</constant> до PHP 8.0.0)
|
||
для диагностики.
|
||
Однако если в настройках INI-директивы <link linkend="ini.display-errors">display_errors</link>
|
||
установили скрытие такой диагностики, то ничего выводиться не будет.
|
||
Это связано с тем, что языковая конструкция echo указывает на локальную версию переменной
|
||
<varname>$a</varname>, а в пределах этой области видимости переменной
|
||
не присвоили значение. Можно заметить, что поведение немного
|
||
отличается от языка C в том, что глобальные переменные в C
|
||
автоматически доступны функциям, если только глобальную переменную
|
||
не перезаписали локальным определением. Это может вызвать некоторые
|
||
проблемы, поскольку люди могут нечаянно изменить глобальную
|
||
переменную. В PHP глобальные переменные требуется объявлять глобальными
|
||
внутри функции, если функция будет использовать эти переменные.
|
||
</simpara>
|
||
|
||
<sect2 xml:id="language.variables.scope.global">
|
||
<title>Ключевое слово <literal>global</literal></title>
|
||
<simpara>
|
||
Сначала пример ключевого слова <literal>global</literal>:
|
||
</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>
|
||
</para>
|
||
|
||
<simpara>
|
||
Приведённый скрипт выведет значение <literal>3</literal>. После определения
|
||
переменных <varname>$a</varname> и <varname>$b</varname> внутри функции как
|
||
global, ссылки на любую из этих переменных укажут на глобальную версию этих переменных.
|
||
Ограничений на количество глобальных переменных,
|
||
которые будет обрабатывать функция, нет.
|
||
</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>
|
||
<para>
|
||
Не будет ошибкой, если указать ключевое слово <literal>global</literal>
|
||
вне функции. Слово указывают вне функции в файле, который подключают
|
||
внутри функции другого файла.
|
||
</para>
|
||
</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>
|
||
Статическим переменным разрешается присваивать значения
|
||
в виде константных выражений, но динамические выражения
|
||
наподобие вызова функции вызовут ошибку разбора.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Объявление статических переменных</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function foo() {
|
||
static $int = 0; // Правильно
|
||
static $int = 1 + 2; // Правильно
|
||
static $int = sqrt(121); // Неправильно, поскольку это функция
|
||
|
||
$int++;
|
||
echo $int;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
Начиная с PHP 8.1.0, когда наследуется (но не переопределяется) метод
|
||
со статическими переменными, унаследованный метод будет использовать
|
||
статические переменные совместно с родительским методом.
|
||
Это означает, что статические переменные в методах теперь ведут себя
|
||
как статические свойства.
|
||
</para>
|
||
|
||
<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>
|
||
|
||
<note>
|
||
<para>
|
||
Статические объявления вычисляются во время компиляции скрипта.
|
||
</para>
|
||
</note>
|
||
</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] — индекс этой переменной.
|
||
PHP предлагает такой синтаксис разрешения неоднозначности:
|
||
<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 = array('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";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
Я bar.
|
||
Я bar.
|
||
Я bar.
|
||
Я r.
|
||
</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 прозрачно поддерживает HTTP cookies в соответствии с требованиями стандарта <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
|
||
-->
|