Сайт упал из-за ECHO
Привет, уважаемые читатели!
В данной статье я хотел описать решение проблемы с которой я столкнулся, на решение проблемы у меня ушло три часа, вот я не хочу, чтобы мои читатели не тратили так много времени.
Также данная статься предназначена для людей которые имеют представление об ООП, приведениях типов, в общем, с углубленным знанием PHP.
Итак. Я работаю с ZendFramework. В одном из проектов который я создаю было задача построения не простой формы, следовательно вывести во вьюхе:
<?php echo $this->form;?>
я не смог из-за сложной верстки (декорировать на зенде — дольше, чем на голом ХТМЛе создать), я просто разобрал созданную в контроллере форму по элементам:
$itemsList = $this->form->getElements ();
в таком виде я получил массив всех элементов, ключами массива служили название полей в форме, а значение — объект данного поля (валидаторы, декораторы и тд).
При построении кнопок в данной форме я воспользовался конструкцией тернарного оператора:
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"] : ''?> <?php echo isset($itemsList["reset"]) ? $itemsList["reset"] : ''?>
В форме при разных условиях часть кнопок отсутствовала, поэтому юзал условия.
При такой конструкции сайт ВАЛИТСЯ!!! Никаких сообщений нет, трейса нет, в логе-апача ничего нет — полный ГОЛЯК! Нашел я эту проблему методом «научного тыка».
Ну как ни у кого нет мысли почему эти строки валили сайт, еще скажу, если выводить какую-то одну из строк — все ОК?!
В общем дело в том, что именно оператор ECHO виновен, он не смог преобразовать объект в строку и выдать её, при этом никакого предупреждения не выдав!!!!!!!!
Если переписать эти строки вот так:
<?php print isset($itemsList["submit"]) ? $itemsList["submit"] : ''?> <?php print isset($itemsList["reset"]) ? $itemsList["reset"] : ''?>
, т.е. заменить echo на print все нормально срабатывало.
Как бы я не крутил конструкция с эхо, скобочки разные, короткое сокращение эхо, и тд ничего не происходило. Помогло только явное приведение к строке с помощью конструкции (string), или конкатенация с пустой строкой, или приведение к типу с помощью ООП метода __toString();
<?php echo isset($itemsList["submit"]) ? (string)$itemsList["submit"] : ''?> <?php echo isset($itemsList["reset"]) ? (string)$itemsList["reset"] : ''?>
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"].' ' : ''?> <?php echo isset($itemsList["reset"]) ? $itemsList["reset"].' ' : ''?>
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"]->__toString() : ''?> <?php echo isset($itemsList["reset"]) ? $itemsList["reset"]->__toString() : ''?>
Но самое, что для меня не понятное, почему если, я расписал условие в полном объеме:
if(isset($itemsList["submit"])) { echo $itemsList ["submit"]; } if(isset($itemsList["reset"])) { echo $itemsList ["reset"]; }
все выполняется, заметьте, преобразованием типа я не занимался!!!
Вот часть кодов, может кто хочет протестировать:
Класс формы
public function __construct($options = null) { ..... $this->_options = $options; ..... } public function init() { ..... $this->addElement( 'submit', 'submit', array( 'label' => 'submit', 'class' => 'but', 'decorators' => array('ViewHelper'), 'title'=>'submit' ) ); $this->addElement( 'submit', 'reset', array( 'label'=>'reset', 'class' => 'but', 'decorators' => array('ViewHelper'), 'title'=>'reset' ) ); ..... } protected $_options = array();
Контроллер
$form = new Module_Forms_MyForm(array('some options')); ..... $this->view->form = $form;
Вьюха
$itemsList = $this->form->getElements (); <form ....> ..... <?php echo isset($itemsList["submit"]) ? $itemsList["submit"] : ''?> <?php echo isset($itemsList["reset"]) ? $itemsList["reset"] : ''?> ..... </form>
Плиз, оставь свои мнения, почему в тернарном операторе эхо не сработало, а в общем условии — все ок!! Очень интересно знать, отвечу на любые вопросы.
UPD: Забыл сказать, все это без каких либо изменений работет по виндой, но подлинухом не работает!
Статья просмотренна 73593 раз, зашло посетителей 18562
Под рукой зенда нет, так что сам проверить не могу. Возникли две идеи. Попробуй переписать выод так:
и так:
Вдруг заработает 😉
мдя 🙁 блок код благополучно вырезал. Отправил копию в тветтере.
Надо было для каждого элемента вызывать его метод render().
Спасибо, я не пробовал, но думаю поможет. Также поможет метов __toString(). Но дело в том, какого ECHO так себя ведет, если меняешь на PRINT— всё супер. Не ошибка ли это самого пыха????
Я когда пользую тернарный оператор перестраховываюсь массой скобок. Просто нередко сталкивался с тем что он у меня работает не так, как ожидалось. ))
Вся загвоздка может банально оказаться в приоритете операторов.
Например, можно попробовать так:
echo (isset($itemsList[«submit»]) ? $itemsList[«submit»] : »);
хм… смайлики какие-то появились в коде… в общем там просто за скобки предлагаю вынести echo
Навскидку, так пробовали?
echo isset($itemsList[«reset»]) ? $itemsList[«reset»] : »
ps. Пред коммент можно/нужно затереть.
лучше всего юзать print или юзать метод render().
Как же я люблю WP. В общем вот:
http://gist.github.com/372460
Наберусь времени — перешерстю плгин камментов, т.к. он много всякого мне не нужного делает ))
«лучше» — это не решение проблемы. у вас интересная фигня вышла, и любопытно было бы узнать причину этой фигни. вы ее выяснили? -)
Я все расписал в статье, дальше я не занимался выяснение причины. Тут надо глубоко копать…
Разница очень простая: echo — это не функция, а специальная конструкция языка, и использовать ее нужно соответственно.
Вот возможное решение (не запускал) для echo без явного приведения типа:
echo isset($itemsList["submit"]) ? "{$itemsList['submit']}" : '';
Обратите внимание на двойные кавычки и фигурные скобки вокруг выражения а также одинарные кавычки вокруг submit.
попробуй получать не массив, а выводить по элементно, вместе с декораторами/без декораторов (только с вьюхелпером).
echo isset( $this->form->submit ) ? $this->form->submit : "";
Большое спасибо Вам за помощь, на тот момент я не знал о методе render() у элементов формы, сейчас именно так и юзаю формы, все работает отлично.