Intereting Posts
Функция PHP для перечисления всех атрибутов объектов Как предотвратить добавление doctype в HTML? Вопросительный знак равен, не работает на php Удалить скобки в json? Автоматический выход из системы, когда пользователь покидает приложение, не выполняя действия выхода из системы CakePHP 2.0.4 – findBy магические методы с условиями Справка Regex: сопоставление любого файла изображения, начинающегося с подчеркивания Попытка заполнить выпадающий список с помощью jquery и ajax Вызов представления базы данных в Yii с использованием Active Record многомерный массив в случайном порядке Как заставить GPG принимать входные данные от STDIN вместо попытки открыть файл? Как создать несколько флажков в форме symfony2 PHP Regex находит текст между настраиваемыми добавленными тегами HTML Разрешить PHP выполнять скрипт bash с правами root Удалить первые уровни идентификатора в массиве

Увеличение на "__toString"

Я не уверен, что должно быть в заголовке, но код должен объяснить это лучше:

class Group { private $number = 20; public function __toString() { return "$this->number"; } } $number = new Group(); echo $number, PHP_EOL; echo ++ $number, PHP_EOL; echo PHP_EOL; $number = "20"; echo $number, PHP_EOL; echo ++ $number, PHP_EOL; echo PHP_EOL; $number = 20; echo $number, PHP_EOL; echo ++ $number, PHP_EOL; 

Вывод:

 20 20 <--- Expected 21 20 21 20 21 

Любая идея, почему я получил 20 вместо 21 ? Даже тогда код ниже работает:

 $i = null ; echo ++$i ; // output 1 

Я знаю, что Group – это объект, который реализует __toString , я ожидал, что ++ работает со строкой из __toString или, по крайней мере, throw an error

Порядок, в котором происходят операции, важен:

  1. Переменная будет выбрана как объект, она не будет передана в целое число (или что-то еще).

  2. Этот оператор ++ увеличивает lval (длинное значение) zval , но обычно ничего не делает. Указатель объекта остается неизменным. Внутренняя (fast_)increment_function будет вызываться с zval которая имеет указатель на объект, который сначала проверяет тип. Если это объект, он ничего не делает. Поэтому, когда ваш zval является объектом, он так же полезен, как и без операции. Это не выдаст никаких предупреждений.

  3. Только тогда команда echo выполняет строку, отличную от его аргументов: вызывается метод __toString и возвращает 20 .

  4. 20 будет выводиться.

Чтобы ответить на вопрос с небольшим количеством кода.

 $number = new Group(); echo gettype($number); $number = "20"; echo gettype($number); $number = 20; echo gettype($number); 

В результате

 object string integer 

Три случая:

  • Вы не можете выполнять целую операцию над объектом, поэтому ваш код не делает то, что вы ожидаете. Метод __toString будет вызван очень поздно, когда вычисляется acutal-вывод, после того как вы безуспешно попытались выполнить математическую операцию с ним.
  • Вы можете использовать математику со строками, потому что PHP внутренне преобразует их обратно в числа
  • Очевидно, вы можете делать математику с целым числом

Бонус:

Это будет работать:

 $number = new Group(); echo 1 + "$number"; // 21 

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

Я думаю, что может быть яснее, просто изменив имена таких переменных:

 class Group { private $number = 20; public function __toString() { return "$this->number"; } } $group = new Group(); echo $group;//print 20 as per your __toString function ++ $group; 

Теперь кажется очевидным: что должен делать оператор «++» на объекте группы типов?

Почему бы вам не просто:

 class Group { private $number = 0; public function __construct($number = 0){ $this->number = intval($number); } public function __toString() { return number_format(++$this->number); // pre-increment } } $g = new Group(); echo $g; // 1 echo $g; // 2 

Я использую что-то подобное для форматирования смещений в таблицах.

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

 <?php class Group { private $number = 20; public function __toString() { return (string) $this->number; // replace "" w/string cast } } $number = (int)(string) new Group(); echo $number, PHP_EOL; echo ++$number, PHP_EOL; 

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

Приведение вновь созданного объекта в виде строки приводит к автоматическому выполнению метода магии __toString и возвращает числовую строку, которая при нажатии на int позволяет отображать число, увеличивать его и отображать снова.

Между прочим, пространство между ++ и $ number в порядке; Я закрыл его b / c, и это то, к чему я привык на других языках, таких как C.