-> Jarobman http://www.php.net/manual/en/language.types.string.php#89757 (mods: remove these two posts together as you please)
Please see http://www.php.net/manual/en/language.constants.syntax.php (first example, last row)
Plus, you have a typo: You obviously meant to use the object-operator as
<?php $object->membervar ?> instead of hyphen-minus for subtraction with
<?php $object-membervar == $object-'membervar' == $object-0 == (int)$object == 1 ?>
Строки
Строка - это набор символов, где символ - это то же самое, что и байт. Это значит, что PHP поддерживает ровно 256 различных символов, а также то, что в PHP нет встроенной поддержки Unicode. Смотрите также подробности реализации строкового типа.
Замечание: Строки могут быть размером более 2 Гб.
Синтаксис
Строка может быть определена четырьмя различными способами:
- одинарными кавычками
- двойными кавычками
- heredoc-синтаксисом
- nowdoc-синтаксисом (начиная с версии PHP 5.3.0)
Одинарные кавычки
Простейший способ определить строку - это заключить ее в одинарные кавычки (символ ').
Чтобы использовать одинарную кавычку внутри строки, проэкранируйте ее обратной косой чертой (\). Если необходимо написать саму обратную косую черту, продублируйте ее (\\). Все остальные случаи применения обратной косой черты будут интерпретированы как обычные символы: это означает, что если вы попытаетесь использовать другие управляющие последовательности, такие как \r или \n, они будут выведены как есть вместо какого-либо особого поведения.
Замечание: В отличие от синтаксиса двойных кавычек и heredoc, переменные и управляющие последовательности для специальных символов, заключенных в одинарные кавычки, не обрабатываются.
<?php
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) |
| \e | escape-знак (ESC или 0x1B (27) в ASCII) (с версии PHP 5.4.0) |
| \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: содержать только буквенно-цифровые символы и знак подчеркивания, и не должен начинаться с цифры (знак подчеркивания разрешается).
Очень важно отметить, что строка с закрывающим идентификатором не содержит других символов, за исключением, возможно, точки с запятой (;). Это означает, что идентификатор не должен вводиться с отступом и что не может быть никаких пробелов или знаков табуляции до или после точки с запятой. Важно также понимать, что первым символом перед закрывающим идентификатором должен быть символ новой строки, определенный в вашей операционной системе. Например, на Macintosh это \r. После закрывающего идентификатора (необязательно дополненного точкой с запятой) также сразу должна начинаться новая строка.
Если это правило нарушено и закрывающий идентификатор не является "чистым", считается, что закрывающий идентификатор отсутствует и PHP продолжит его поиск дальше. Если в этом случае верный закрывающий идентификатор так и не будет найден, то это вызовет ошибку парсинга с номером строки в конце скрипта.
Heredoc не может быть использован для инициализации полей класса. Начиная с версии PHP 5.3, это ограничение распространяется только на heredoc, содержащие внутри себя переменные.
Пример #1 Неверный пример
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
?>
Heredoc-текст ведет себя так же, как и строка в двойных кавычках, при этом их не имея. Это означает, что вам нет необходимости экранировать кавычки в heredoc, но вы по-прежнему можете использовать вышеперечисленные управляющие последовательности. Переменные обрабатываются, но с применением сложных переменных внутри heredoc нужно быть также внимательным, как и при работе со строками.
Пример #2 Пример определения heredoc-строки
<?php
$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 в аргументах
<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>
Начиная с версии 5.3.0, стала возможной инциализация статических переменных и свойств/констант класса с помощью синтаксиса heredoc:
Пример #4 Использование heredoc для инциализации статических переменных
<?php
// Статические переменные
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
<?php
echo <<<"FOOBAR"
Привет, мир!
FOOBAR;
?>
Nowdoc
Nowdoc - это то же самое для строк в одинарных кавычках, что и heredoc для строк в двойных кавычках. Nowdoc похож на heredoc, но внутри него не осуществляется никаких подстановок. Эта конструкция идеальна для внедрения PHP-кода или других больших блоков текста без необходимости его экранирования. В этом он немного похож на SGML-конструкцию <![CDATA[ ]]> тем, что объявляет блок текста, не предназначенный для обработки.
Nowdoc указывается той же последовательностью <<<, что используется в heredoc, но последующий за ней идентификатор заключается в одинарные кавычки, например, <<<'EOT'. Все условия, действующие для heredoc идентификаторов также действительны и для nowdoc, особенно те, что относятся к закрывающему идентификатору.
Пример #6 Пример использования nowdoc
<?php
$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 может быть использован в любом контексте со статическими данными. Типичный пример инициализации полей класса или констант:
Пример #7 Пример использования статичных данных
<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>
Замечание:
Поддержка nowdoc была добавлена в PHP 5.3.0.
Обработка переменных
Если строка указывается в двойных кавычках, либо при помощи heredoc, переменные внутри нее обрабатываются.
Существует два типа синтаксиса: простой и сложный. Простой синтаксис более легок и удобен. Он дает возможность обработки переменной, значения массива (array) или свойства объекта (object) с минимумом усилий.
Сложный синтаксис может быть определен по фигурным скобкам, окружающим выражение.
Простой синтаксис
Если интерпретатор встречает знак доллара ($), он захватывает так много символов, сколько возможно, чтобы сформировать правильное имя переменной. Если вы хотите точно определить конец имени, заключайте имя переменной в фигурные скобки.
<?php
$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). В индексах массива закрывающая квадратная скобка (]) обозначает конец определения индекса. Для свойств объекта применяются те же правила, что и для простых переменных.
Пример #8 Пример простого синтаксиса
<?php
$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 juice made of $juice[0]s.".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."; // Не будет работать
?>
Результат выполнения данного примера:
He drank some apple juice. He drank some orange juice. He drank some juice made of s. 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 .
Для чего-либо более сложного, используйте сложный синтаксис.
Сложный (фигурный) синтаксис
Он называется сложным не потому, что труден в понимании, а потому что позволяет использовать сложные выражения.
Любая скалярная переменная, элемент массива или свойство объекта, отображаемое в строку, может быть представлена в строке этим синтаксисом. Просто запишите выражение так же, как и вне строки, а затем заключите его в { и }. Поскольку { не может быть экранирован, этот синтаксис будет распознаваться только когда $ следует непосредственно за {. Используйте {\$, чтобы напечатать {$. Несколько поясняющих примеров:
<?php
// Показываем все ошибки
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()}";
?>
С помощью этого синтаксиса также возможен доступ к свойствам объекта внутри строк.
<?php
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. Однако, указываемое значение будет обработано как имя переменной в том же контексте, что и строка, в которой она определяется. Использование одинарных фигурных скобок ({}) не будет работать для доступа к значениям функций, методов, констант классов или статических переменных класса.
<?php
// Показываем все ошибки
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).
Пример #9 Несколько примеров строк
<?php
// Получение первого символа строки
$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';
?>
Замечание:
Попытка доступа к переменным других типов (исключая массивы или объекты, реализующие определенные интерфейсы) с помощью [] или {} молча вернет
NULL.
Полезные функции и операторы
Строки могут быть объединены при помощи оператора '.' (точка). Обратите внимание, оператор сложения '+' здесь не работает. Дополнительную информацию смотрите в разделе Строковые операторы.
Для модификации строк существует множество полезных функций.
Основные функции описаны в разделе строковых функций, а для расширенного поиска и замены - функции регулярных выражений или 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 id #1", где 1 - это уникальный номер ресурса (resource), присвоенный ему PHP во время выполнения. Не полагайтесь на эту структуру, она может измениться в любое время. Если вы хотите получить тип ресурса, используйте get_resource_type().
NULL всегда преобразуется в пустую строку.
Как вы могли видеть выше, прямое преобразование в строку массивов, объектов или ресурсов не дает никакой полезной информации о самих значениях, кроме их типов. Более подходящий способ вывода значений для отладки - использовать функции print_r() и var_dump().
Большинство значений в PHP может быть преобразовано в строку для постоянного хранения. Этот метод называется сериализацией и может быть выполнен при помощи функции serialize(). Кроме того, если в вашей установке PHP есть поддержка WDDX, возможна также сериализация в XML-структуру.
Преобразование строк в числа
Если строка распознается как числовое значение, результирующее значение и тип определяется так, как показано далее.
Если строка не содержит какой-либо из символов '.', 'e', или 'E', и
значение числа помещается в пределы целых чисел (определенных
PHP_INT_MAX), строка будет распознана как целое число (integer).
Во всех остальных случаях она считается числом с плавающей точкой (float).
Значение определяется по начальной части строки. Если строка начинается с верного числового значения, будет использовано это значение. Иначе значением будет 0 (ноль). Верное числовое значение - это одна или более цифр (могущих содержать десятичную точку), по желанию предваренных знаком, с последующим необязательным показателем степени. Показатель степени - это 'e' или 'E' с последующими одной или более цифрами.
<?php
$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.
Если вы хотите протестировать любой из примеров этого раздела, скопируйте и вставьте его и следующую строку, чтобы увидеть, что происходит:
<?php
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. Например, если программа предполагает существование в языке только строчных и заглавных букв, то она делает большую ошибку.
Heredoc literals delete any trailing space (tabs and blanks) on each line. This is unexpected, since quoted strings do not do this. This is probably done for historical reasons, so would not be considered a bug.
The documentation does not mention, but a closing semicolon at the end of the heredoc is actually interpreted as a real semicolon, and as such, sometimes leads to syntax errors.
This works:
<?php
$foo = <<<END
abcd
END;
?>
This does not:
<?php
foo(<<<END
abcd
END;
);
// syntax error, unexpected ';'
?>
Without semicolon, it works fine:
<?php
foo(<<<END
abcd
END
);
?>
Actually, HEREDOC works precisely as documented, with nothing hidden at all. It's just that it's one of those things which isn't entirely intuitive to grasp.
A HEREDOC block has to start with the delimiter followed by a newline, and end with a newline followed by the delimiter. That means that the leading and trailing newlines are part of the syntax, not a part of the block. So this
<?php
$foo = <<<EOF
this
is
a
block
EOF;
?>
is equivalent to this
<?php
$foo =
"this
is
a
block";
?>
or this
<?php
$foo = "this\nis\na\nblock";
?>
but not this:
<?php
$foo = "
this
is
a
block
";
?>
or this
<?php
$foo = "\nthis\nis\na\nblock\n";
?>
Viewing it with the syntax highlighting switched on helps to make the difference clearer.
The docs say: "Heredoc text behaves just like a double-quoted string, without the double quotes" but there is a notable hidden exception to that rule: the final newline in the string (the one before closing heredoc token) is elided. i.e. if you have:
$foo = <<<EOF
a
b
c
EOF;
the result is equivalent to "a\nb\nc", NOT "a\nb\nc\n" like the docs imply.
curly brackets for strings
<?php
$test_array = array("hey","people");
$key = 0;
$key1 = 1;
$letter = 0;
echo($test_array[$key]{$letter});
echo($test_array[$key1]{$letter});
?>
result: "hp"
Just want to mention that if you want a literal { around a variable within a string, for example if you want your output to be something like the following:
{hello, world}
and all that you put inside the {} is a variable, you can do a double {{}}, like this:
$test = 'hello, world';
echo "{{$test}}";
If you require a NowDoc but don't have support for them on your server -- since your PHP version is less than PHP 5.3.0 -- and you are in need of a workaround, I'd suggest using PHP's __halt_compiler() which is basically a knock-off of Perl's __DATA__ token if you are familiar with it.
Give this a run to see my suggestion in action:
<?php
//set $nowDoc to a string containing a code snippet for the user to read
$nowDoc = file_get_contents(__FILE__,null,null,__COMPILER_HALT_OFFSET__);
$nowDoc=highlight_string($nowDoc,true);
echo <<<EOF
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>NowDoc support for PHP < 5.3.0</title>
<meta name="author" content="Ultimater at gmail dot com" />
<meta name="about-this-page"
content="Note that I built this code explicitly for the
php.net documenation for demonstrative purposes." />
<style type="text/css">
body{text-align:center;}
table.border{background:#e0eaee;margin:1px auto;padding:1px;}
table.border td{padding:5px;border:1px solid #8880ff;text-align:left;
background-color:#eee;}
code ::selection{background:#5f5color:white;}
code ::-moz-selection{background:#5f5;color:white;}
a{color:#33a;text-decoration:none;}
a:hover{color:rgb(3,128,252);}
</style>
</head>
<body>
<h1 style="margin:1px auto;">
<a
href="http://php.net/manual/en/language.types.string.php#example-77">
Example #8 Simple syntax example
</a></h1>
<table class="border"><tr><td>
$nowDoc
</td></tr></table></body></html>
EOF;
__halt_compiler()
//Example code snippet we want displayed on the webpage
//note that the compiler isn't actually stopped until the semicolon
;<?php
$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 juice made of $juice[0]s.".PHP_EOL; // Won't work
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
?>
I recently discovered the joys of using heredoc with sprintf and positions. Useful if you want some code to iterate, you can repeat placeholders.
<?php
function getNumber($num = 0) {
$foo = rand(1,20);
return ($foo + $num);
}
function getString() {
$foo = array("California","Oregon","Washington");
shuffle($foo);
return $foo[0];
}
function getDiv() {
$num = getNumber();
$div = sprintf( "<div>%s</div>", getNumber(rand(-5,5)) );
return $div;
}
$string = <<<THESTRING
I like the state of %1\$s <br />
I picked: %2\$d as a number, <br />
I also picked %2\$d as a number again <br />
%3\$s<br />
%3\$s<br />
%3\$s<br />
%3\$s<br />
%3\$s<br />
THESTRING;
$returnText = sprintf( $string, getString(),getNumber(),getDiv() );
echo $returnText;
?>
Expected output of the above code:
I like the state of Oregon
I picked: 15 as a number,
I also picked 15 as a number again
5
5
5
5
5
Watch out for the "unexpected T_SL" error. This appears to occur when there is white space just after "<<<EOT" and since it's white space it's real hard to spot the error in your code.
Empty strings seem to be no real strings, because they behave different to strings containing data. Here is an example.
It is possible to change a character at a specific position using the square bracket notation:
<?php
$str = '0';
$str[0] = 'a';
echo $str."\n"; // => 'a'
?>
It is also possible to change a character with does not exist, if the index is "behind" the end of the string:
<?php
$str = '0';
$str[1] = 'a';
echo $str."\n"; // => 0a
?>
But if you do that on an empty string, the string gets silently converted into an array:
<?php
$str = '';
$str[0] = 'a';
echo $str."\n"; // => Array
?>
If you want a parsed variable surrounded by curly braces, just double the curly braces:
<?php
$foo = "bar";
echo "{{$foo}}";
?>
will just show {bar}. The { is special only if followed by the $ sign and matches one }. In this case, that applies only to the inner braces. The outer ones are not escaped and pass through directly.
Although current documentation says 'A string literal can be specified in four different ways: ...', actually there is a fifth way to specify a (binary) string:
<?php $binary = b'This is a binary string'; ?>
The above statement declares a binary string using the 'b' prefix, which is available since PHP 5.2.1. However, it will only have effect as of PHP 6.0.0, as noted on http://www.php.net/manual/en/function.is-binary.php .
If you need to emulate a nowdoc in PHP < 5.3, try using HTML mode and output capturing. This way '$' or '\n' in your string won't be a problem anymore (but unfortunately, '<?' will be).
<?php
// Start of script
ob_start(); ?>
A text with 'quotes'
and $$$dollars$$$.
<?php $input = ob_get_contents(); ob_end_clean();
// Do what you want with $input
echo "<pre>" . $input . "</pre>";
?>
Here is an easy hack to allow double-quoted strings and heredocs to contain arbitrary expressions in curly braces syntax, including constants and other function calls:
<?php
// Hack declaration
function _expr($v) { return $v; }
$_expr = '_expr';
// Our playground
define('qwe', 'asd');
define('zxc', 5);
$a=3;
$b=4;
function c($a, $b) { return $a+$b; }
// Usage
echo "pre {$_expr(1+2)} post\n"; // outputs 'pre 3 post'
echo "pre {$_expr(qwe)} post\n"; // outputs 'pre asd post'
echo "pre {$_expr(c($a, $b)+zxc*2)} post\n"; // outputs 'pre 17 post'
// General syntax is {$_expr(...)}
?>
One thing I have noticed (using PHP 5.2.4) is that alphanumeric text starting with letters or underscore without spaces and operators in PHP code without single or double quotes is interpreted as a string. I noticed this when trying to access a member variable from an object and getting an integer returned on what I thought should have been a syntax error. The text cannot correspond to most PHP keywords since that would generate a fatal error.
<?php
class MyObject
{
private $__internal_array = array();
//insert code for overloading __get(), __set(), etc. to
//access items from $__internal_array
}
$object = new MyObject();
//thought this would give a syntax error, put param returned an int somehow
some_function($object-membervar);
//correct
echo hiImAString;
//correct
echo hello.world._6789;
//correct
thisisastandalonestring;
//correct, outputs 0
echo string+anotherstring-yetanotherstring;
//correct, outputs 1concatenated
echo true.false.concatenated;
//incorrect, syntax error
echo cantdothis.1234567890;
//incorrect, syntax error, use of PHP keywords
echo try.and.do.this.if.you.can.else.break;
?>
Any other combination of the above with operators and other special characters will generate fatal errors. I think it would be the opinion of many people that this form of a string is not at all practical and should never be used at all. Personally, I think this looks like a bug, but I could be wrong. However, this is something else one could watch out for when debugging since this is hard to pick up in code especially when expecting integer or boolean values.
Cheers,
Jarobman
I commented on a php bug feature request for a string expansion function and figured I should post somewhere it might be useful:
using regex, pretty straightforward:
<?php
function stringExpand($subject, array $vars) {
// loop over $vars map
foreach ($vars as $name => $value) {
// use preg_replace to match ${`$name`} or $`$name`
$subject = preg_replace(sprintf('/\$\{?%s\}?/', $name), $value,
$subject);
}
// return variable expanded string
return $subject;
}
?>
using eval() and not limiting access to only certain variables (entire current symbol table including [super]globals):
<?php
function stringExpandDangerous($subject, array $vars = array(), $random = true) {
// extract $vars into current symbol table
extract($vars);
$delim;
// if requested to be random (default), generate delim, otherwise use predefined (trivially faster)
if ($random)
$delim = '___' . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . '___';
else
$delim = '__ASDFZXCV1324ZXCV__'; // button mashing...
// built the eval code
$statement = "return <<<$delim\n\n" . $subject . "\n$delim;\n";
// execute statement, saving output to $result variable
$result = eval($statement);
// if eval() returned FALSE, throw a custom exception
if ($result === false)
throw new EvalException($statement);
// return variable expanded string
return $result;
}
?>
I hope that helps someone, but I do caution against using the eval() route even if it is tempting. I don't know if there's ever a truely safe way to use eval() on the web, I'd rather not use it.
Expectedly <?php $string[$x] ?> and <?php substr($string, $x, 1) ?> will yield the same result... normally!
However, when you turn on the Function Overloading Feature (http://php.net/manual/en/mbstring.overload.php), this might not be true!
If you use this Overloading Feature with 3rd party software, you should check for usage of the String access operator, otherwise you might be in for some nasty surprises.
An interesting finding about Heredoc "syntax error, unexpected $end".
I got this error because I did not use the php close tag "?>" and I had no code after the heredoc code.
foo1.php code gives "syntax error, unexpected $end".
But in foo2.php and foo3.php, when you add a php close tag or when you have some more code after heredoc it works fine.
Example Code:
foo1.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7.
foo2.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7.
8. echo $str;
9.
foo3.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7. ?>
Simple function to create human-readably escaped double-quoted strings for use in source code or when debugging strings with newlines/tabs/etc.
<?php
function doubleQuote($str) {
$ret = '"';
for ($i = 0, $l = strlen($str); $i < $l; ++$i) {
$o = ord($str[$i]);
if ($o < 31 || $o > 126) {
switch ($o) {
case 9: $ret .= '\t'; break;
case 10: $ret .= '\n'; break;
case 11: $ret .= '\v'; break;
case 12: $ret .= '\f'; break;
case 13: $ret .= '\r'; break;
default: $ret .= '\x' . str_pad(dechex($o), 2, '0', STR_PAD_LEFT);
}
} else {
switch ($o) {
case 36: $ret .= '\$'; break;
case 34: $ret .= '\"'; break;
case 92: $ret .= '\\\\'; break;
default: $ret .= $str[$i];
}
}
}
return $ret . '"';
}
?>
To save Your mind don't read previous comments about dates ;)
When both strings can be converted to the numerics (in ("$a" > "$b") test) then resulted numerics are used, else FULL strings are compared char-by-char:
<?php
var_dump('1.22' > '01.23'); // bool(false)
var_dump('1.22.00' > '01.23.00'); // bool(true)
var_dump('1-22-00' > '01-23-00'); // bool(true)
var_dump((float)'1.22.00' > (float)'01.23.00'); // bool(false)
?>
So you want to get the last character of a string using "String access and modification by character"? Well negative indexes are not allowed so $str[-1] will return an empty string.
<?php
//Tested using: PHP 5.2.5
$str = 'This is a test.';
$last = $str[-1]; //string(0) ""
$realLast = $str[strlen($str)-1]; //string(1) "."
$substr = substr($str,-1); //string(1) "."
echo '<pre>';
var_dump($last);
var_dump($realLast);
var_dump($substr);
It's also valuable to note the following:
<?php
${date("M")} = "Worked";
echo ${date("M")};
?>
This is perfectly legal, anything inside the braces is executed first, the return value then becomes the variable name. Echoing the same variable variable using the function that created it results in the same return and therefore the same variable name is used in the echo statement. Have fun ;).
I encountered the odd situation of having a string containing unexpanded escape sequences that I wanted to expand, but also contained dollar signs that would be interpolated as variables. "$5.25\n", for example, where I want to convert \n to a newline, but don't want attempted interpolation of $5.
Some muddling through docs and many obscenties later, I produced the following, which expands escape sequences in an existing string with NO interpolation.
<?php
// where we do all our magic
function expand_escape($string) {
return preg_replace_callback(
'/\\\([nrtvf]|[0-7]{1,3}|[0-9A-Fa-f]{1,2})?/',
create_function(
'$matches',
'return ($matches[0] == "\\\\") ? "" : eval( sprintf(\'return "%s";\', $matches[0]) );'
),
$string
);
}
// a string to test, and show the before and after
$before = 'Quantity:\t500\nPrice:\t$5.25 each';
$after = expand_escape($before);
var_dump($before, $after);
/* Outputs:
string(34) "Quantity:\t500\nPrice:\t$5.25 each"
string(31) "Quantity: 500
Price: $5.25 each"
*/
?>
I think there's not that much to string comparison as claiming date recognition:
It's simply comparing ordinal values of the characters from the {0} to the {strlen-1} one.
In this case
<?php
$a = '2007-11-06 15:17:48';
$b = '2007-11-05 15:17:48';
var_dump($a > $b);
?>
mArIo@luigi ~ $: php test.php
bool(true)
here all characters match till it reaches position 9 (the "day")
there, 6 has a bigger ord()inal value than 5
<?php
$a = 'January 25th, 2008 00:23:38';
$b = 'Janury 24th, 2008 00:23:37'; // ($a > $b) === false
?>
Here when we reach 'r' in "Janury" we see that "a" is "less" than "r" so the example would evaluate as ($a < $b) === true
Here:
<?php
$a = 'February 1st, 2008 00:23:38';
$b = 'January 25th, 2008 00:23:38';
?>
as expected the letter "F" comes before "J" as an ordinal character, so $a is less than $b
Even here:
<?php
var_dump('Z' > 'M'); //bool(true)
?>
it gets confirmed that the string comparison operators >, <, =>, =<, == just do a ordinal character comparison starting from position {0} to the first difference or the end of the string.
If you want to use a variable in an array index within a double quoted string you have to realize that when you put the curly braces around the array, everything inside the curly braces gets evaluated as if it were outside a string. Here are some examples:
<?php
$i = 0;
$myArray[Person0] = Bob;
$myArray[Person1] = George;
// prints Bob (the ++ is used to emphasize that the expression inside the {} is really being evaluated.)
echo "{$myArray['Person'.$i++]}<br>";
// these print George
echo "{$myArray['Person'.$i]}<br>";
echo "{$myArray["Person{$i}"]}<br>";
// These don't work
echo "{$myArray['Person$i']}<br>";
echo "{$myArray['Person'$i]}<br>";
// These both throw fatal errors
// echo "$myArray[Person$i]<br>";
//echo "$myArray[Person{$i}]<br>";
?>
Unlike bash, we can't do
echo "\a" #beep!
Of course, that would be rather meaningless for PHP/web, but it's useful for PHP-CLI. The solution is simple: echo "\x07"
easy transparent solution for using constants in the heredoc format:
DEFINE('TEST','TEST STRING');
$const = get_defined_constants();
echo <<<END
{$const['TEST']}
END;
Result:
TEST STRING
error control operator (@) with heredoc syntax:
the error control operator is pretty handy for supressing minimal errors or omissions. For example an email form that request some basic non mandatory information to your users. Some may complete the form, other may not. Lets say you don't want to tweak PHP for error levels and you just wish to create some basic template that will be emailed to the admin with the user information submitted. You manage to collect the user input in an array called $form:
<?php
// creating your mailer
$mailer = new SomeMailerLib();
$mailer->from = ' System <mail@yourwebsite.com>';
$mailer->to = 'admin@yourwebsite.com';
$mailer->subject = 'New user request';
// you put the error control operator before the heredoc operator to suppress notices and warnings about unset indices like this
$mailer->body = @<<<FORM
Firstname = {$form['firstname']}
Lastname = {$form['lastname']}
Email = {$form['email']}
Telephone = {$form['telephone']}
Address = {$form['address']}
FORM;
?>
A simple benchmark to check differents about :
- simple and double quote concatenation and
- double quote and heredoc replacement
<?php
function test_simple_quote_concat()
{
$b = 'string';
$a = ' string'.$b.' string'.$b.' srting'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
}
function test_double_quote_concat()
{
$b = "string";
$a = " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
}
function test_double_quote_replace()
{
$b = "string";
$a = " string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b";
}
function test_eot_replace()
{
$b = <<<EOT
string
EOT;
$a = <<<EOT
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
EOT;
}
$iter = 2000;
for( $i=0; $i<$iter; $i++ )
test_simple_quote_concat();
for( $i=0; $i<$iter; $i++ )
test_double_quote_concat();
for( $i=0; $i<$iter; $i++ )
test_double_quote_replace();
for( $i=0; $i<$iter; $i++ )
test_eot_replace();
?>
I've use xdebug profiler to obtain the followed results:
test_simple_quote_concat : 173ms
test_double_quote_concat : 161ms
test_double_quote_replace : 147ms
test_eot_replace : 130ms
As of (at least) PHP 5.2, you can no longer convert an object to a string unless it has a __toString method. Converting an object without this method now gives the error:
PHP Catchable fatal error: Object of class <classname> could not be converted to string in <file> on line <line>
Try this code to get the same results as before:
<?php
if (!is_object($value) || method_exists($value, '__toString')) {
$string = (string)$value;
} else {
$string = 'Object';
}
?>
It may be obvious to some, but it's convenient to note that variables _will_ be expanded inside of single quotes if these occur inside of a double-quoted string. This can be handy in constructing exec calls with complex data to be passed to other programs. e.g.:
$foo = "green";
echo "the grass is $foo";
the grass is green
echo 'the grass is $foo';
the grass is $foo
echo "the grass is '$foo'";
the grass is 'green'
You may use heredoc syntax to comment out large blocks of code, as follows:
<?php
<<<_EOC
// end-of-line comment will be masked... so will regular PHP:
echo ($test == 'foo' ? 'bar' : 'baz');
/* c-style comment will be masked, as will other heredocs (not using the same marker) */
echo <<<EOHTML
This is text you'll never see!
EOHTML;
function defintion($params) {
echo 'foo';
}
class definition extends nothing {
function definition($param) {
echo 'do nothing';
}
}
how about syntax errors?; = gone, I bet.
_EOC;
?>
Useful for debugging when C-style just won't do. Also useful if you wish to embed Perl-like Plain Old Documentation; extraction between POD markers is left as an exercise for the reader.
Note there is a performance penalty for this method, as PHP must still parse and variable substitute the string.
Use caution when you need white space at the end of a heredoc. Not only is the mandatory final newline before the terminating symbol stripped, but an immediately preceding newline or space character is also stripped.
For example, in the following, the final space character (indicated by \s -- that is, the "\s" is not literally in the text, but is only used to indicate the space character) is stripped:
$string = <<<EOT
this is a string with a terminating space\s
EOT;
In the following, there will only be a single newline at the end of the string, even though two are shown in the text:
$string = <<<EOT
this is a string that must be
followed by a single newline
EOT;
Just some quick observations on variable interpolation:
Because PHP looks for {? to start a complex variable expression in a double-quoted string, you can call object methods, but not class methods or unbound functions.
This works:
<?php
class a {
function b() {
return "World";
}
}
$c = new a;
echo "Hello {$c->b()}.\n"
?>
While this does not:
<?php
function b() {
return "World";
}
echo "Hello {b()}\n";
?>
Also, it appears that you can almost without limitation perform other processing within the argument list, but not outside it. For example:
<?
$true = true;
define("HW", "Hello World");
echo "{$true && HW}";
?>
gives: Parse error: parse error, unexpected T_BOOLEAN_AND, expecting '}' in - on line 3
There may still be some way to kludge the syntax to allow constants and unbound function calls inside a double-quoted string, but it isn't readily apparent to me at the moment, and I'm not sure I'd prefer the workaround over breaking out of the string at this point.
You can use the complex syntax to put the value of both object properties AND object methods inside a string. For example...
<?php
class Test {
public $one = 1;
public function two() {
return 2;
}
}
$test = new Test();
echo "foo {$test->one} bar {$test->two()}";
?>
Will output "foo 1 bar 2".
However, you cannot do this for all values in your namespace. Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
<?php
class Test {
const ONE = 1;
}
echo "foo {Test::ONE} bar";
?>
This will output "foo {Test::one} bar". Constants and static properties require you to break up the string.
A note on the heredoc stuff.
If you're editing with VI/VIM and possible other syntax highlighting editors, then using certain words is the way forward. if you use <<<HTML for example, then the text will be hightlighted for HTML!!
I just found this out and used sed to alter all EOF to HTML.
JAVASCRIPT also works, and possibly others. The only thing about <<<JAVASCRIPT is that you can't add the <script> tags.., so use HTML instead, which will correctly highlight all JavaScript too..
You can also use EOHTML, EOSQL, and EOJAVASCRIPT.
watch out when comparing strings that are numbers. this example:
<?php
$x1 = '111111111111111111';
$x2 = '111111111111111112';
echo ($x1 == $x2) ? "true\n" : "false\n";
?>
will output "true", although the strings are different. With large integer-strings, it seems that PHP compares only the integer values, not the strings. Even strval() will not work here.
To be on the safe side, use:
$x1 === $x2
Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:
$string = 'a';
var_dump($string[2]); // string(0) ""
var_dump($string[7]); // string(0) ""
$string[7] === ''; // TRUE
It appears that anything past the end of the string gives an empty string.. However, when E_NOTICE is on, the above examples will throw the message:
Notice: Uninitialized string offset: N in FILE on line LINE
This message cannot be specifically masked with @$string[7], as is possible when $string itself is unset.
isset($string[7]); // FALSE
$string[7] === NULL; // FALSE
Even though it seems like a not-NULL value of type string, it is still considered unset.
Even if the correct way to handle variables is determined from the context, some things just doesn't work without doing some preparation.
I spent several hours figuring out why I couldn't index a character out of a string after doing some math with it just before. The reason was that PHP thought the string was an integer!
$reference = $base + $userid;
.. looping commands ..
$chartohandle = $reference{$last_char - $i};
Above doesn't work. Reason: last operation with $reference is to store a product of an addition -> integer variable. $reference .=""; (string catenation) had to be added before I got it to work:
$reference = $base + $userid;
$reference .= "";
.. looping commands ..
$chartohandle = $reference{$last_char - $i};
Et voil! Nice stream of single characters.
