Zend-декодирование html-сущностей в элементе ввода формы приводит к пустому значению - PullRequest
2 голосов
/ 26 июля 2011

У меня есть элемент формы, который называется metaDescription:

        //inside the form
        $description = $this    -> createElement('text', 'metaDescription')
                                -> setLabel('Description:')
                                -> setRequired(false)
                                -> addFilter('StringTrim')
                                -> addValidator('StringLength', array(0, 300))
                                -> addErrorMessage('Invalid description.');               
        $this->addElement($description);

Всякий раз, когда эта форма загружается, я инициализирую ее значением по умолчанию, извлеченным из базы данных:

$form->setDefault('metaDescription', $oldPage->getMetaDescription());

Этоотлично работает.

Однако теперь я хочу htmlencode любое описание ввода, когда кто-то отправляет форму, и html_entity_decode значение по умолчанию, извлекаемое из базы данных, чтобы символы отображались в их первоначальной форме.снова.

Я сделал это так при обработке ввода формы:

//handle post
        if ($request->isPost()) {
            if ($form->isValid($request->getPost())) {
                $page = new Application_Model_PagePainter(array(
                    'metaDescription'   => htmlentities($form->getValue('metaDescription'))
                ));
                $pageMapper->save($page);

                ....

И теперь я установил значение по умолчанию следующим образом:

$form->setDefault('metaDescription', html_entity_decode($oldPage->getMetaDescription()));

Сначала этокажется, работает хорошо, а также.Когда я отправляю, например, woord1, woord2, me&you в качестве описания, это правильно сохраняется как woord1, woord2, me&amp;you в базе данных и корректно отображается снова как woord1, woord2, me&you.Тем не менее, когда я устанавливаю странный символ, такой как - например.wóórd1 это правильно сохраняется в базе данных как w&oacute;&oacute;rd1, но затем происходит нечто странное: при повторном отображении формы значение по умолчанию пусто.Когда я смотрю на источник, он действительно пустой: <input type="text" name="metaDescription" id="metaDescription" value="" />.

Это заставит меня поверить, что по какой-то причине html_entity_decode($oldPage->getMetaKeywords()) возвращает пустую строку.Однако, когда я повторяю это, он возвращает правильный результат: wóórd1, но setDefault не имеет никакого эффекта.Когда я удаляю html_entity_decode, setDefault снова работает правильно, и значение отображается в форме, но без декодированной сущности html.

Почему при декодировании этой сущности html значение формы становится пустым для такого странногосимволы?

Ответ vstm

В целях отладки я отменяю кодировку следующим образом:

$this->view->setEscape(array($this, 'myEscape'));

public function myEscape($inputString)
    {
        return $inputString;
    }

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

'metaDescription'   => htmlentities($form->getValue('metaDescription'), ENT_COMPAT, 'UTF-8')

И декодирую значение после его вывода из базы данных следующим образом:

$form->setDefault('metaDescription', html_entity_decode($oldPage->getMetaDescription(), ENT_COMPAT, 'UTF-8'));

Однако очень интересно то, что это похоже на кодировку UTF8, потому что когда я изменяю кодировку на

'metaDescription'   => htmlentities($form->getValue('metaDescription'), ENT_COMPAT 'ISO-8859-1') 

, сохраняя декодирование на UTF8, ввод tést приведет к тому, что поле ввода показывает tést, а не пустое значение, которое имеет место при установке обоих методов на UTF8.

Это вам помогает?

Ответы [ 2 ]

6 голосов
/ 26 июля 2011

Я знал, что это связано с тем, что Zend Framework делает свои собственные экранирование с использованием htmlspecialchars и utf-8 (если вы не измените это с помощью методов представления setEscape / setEncoding).И действительно, когда вы делаете это:

$test = "w&oacute;&oacute;rd1";
$test = html_entity_decode($test, ENT_COMPAT, "iso-8859-1");
$test = htmlspecialchars($test, ENT_COMPAT, "utf-8");

$test в конце пусто.

Таким образом, вы должны вызвать html_entity_decode с помощью "utf-8" или изменить кодировку представлений на "iso-8859-1 "(или какая у вас кодировка).Я думаю, что поставка «utf-8» - лучший вариант.

Война против кодировок

Кто бы ни изобрел кодировки символов, он был либо злым гением, либо глупым пещерным человеком.

Чтобы сделать это, вы также должны позаботиться о том, какую кодировку использует браузер, потому что в противном случае вы либо записываете мусор в свою базу данных, либо выводите мусор в свой вывод, либо и то, и другое (или ничего, если вы передаете неправильную кодировкунекоторые PHP-функции).(потерпите меня)

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

  1. заголовки ответа HTTP
  2. метатег Content-Type (основной параметр в ZF)

метатег типа контента в вашем HTML-выводе и какую кодировку он предлагает.Если метаинформация типа контента отсутствует или не содержит информацию о кодировке, вам следует добавить ее, желательно с utf-8, в свой макет (если вы не используете макет, сейчас самое время начать с него)).Это важно, иначе вы точно не знаете, какую кодировку вы вводите или какую кодировку вы должны передать браузеру.Это означает, что нечто подобное происходит после открытия <head> -Tag каждой страницы, возвращаемой вашим приложением:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

В следующих примерах мы предполагаем, что вы выбираете utf-8, но вы можете использовать все, что подходит- если вы измените значения соответствующим образом (это означает s / UTF-8 / вашу кодировку / g).

Теперь, когда вы получаете данные из браузера, вы знаете, какую кодировку вы должны предоставить для вызова htmlentities(utf-8):

'metaDescription'   => 
    htmlentities($form->getValue('metaDescription'), ENT_COMPAT, 'UTF-8')

Таким образом, это означает, что $form->getValue('metaDescription') возвращает строку в кодировке utf-8, которую необходимо преобразовать в строку HTML-сущностей, а это именно то, что нам нужно.

Таким образом, в базе данных теперь есть неугрожающая строка без умлаутов, акцентов или чего-либо еще.

Теперь мы рассмотрим часть редактирования.Там вы должны декодировать HTML-сущности, чтобы пользователь не имел с ними дело.Выходная строка должна быть закодирована с использованием нашей требуемой кодировки (да, верно: utf-8):

$form->setDefault('metaDescription', 
    html_entity_decode($oldPage->getMetaDescription(), ENT_COMPAT, 'UTF-8'));

Итак, теперь вы присвоили строку в кодировке utf-8, возвращаемую html_entity_decode для metaDescriptionтеперь нам нужно пройти только этот вызов htmlspecialchars, который вызывается по умолчанию, если кто-то использует $view->escape().

Последний шаг - убедиться, что Zend_View encode знает о нашемкодировка (это необязательно, если вы используете utf-8, так как это уже по умолчанию).Либо установите его для определенного представления в контроллере с помощью $this->view->setEncoding('UTF-8'), либо для всех представлений в bootstrap.php:

protected function _initView()
{
    $view = new Zend_View();
    $view->setEncoding('UTF-8');
    $viewRenderer =
        Zend_Controller_Action_HelperBroker::getStaticHelper(
            'ViewRenderer'
        );
    $viewRenderer->setView($view);
    return $view;
}

Если кто-то сейчас вызывает $view->escape(), он также ожидает строку utf-8 в качестве ввода,Вы должны быть в состоянии удалить вызов setEscape с помощью «нулевого» escape.

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

Таким образом, каждая функция получает кодировкуожидает, в противном случае он возвращает печально известную пустую строку (псевдо-блок-схему):

  1. Браузер -> отправляет данные в UTF-8
  2. htmlentities($browserData, ,'UTF-8') -> ожидает возврата UTF-8ASCII без умлаутов или других причудливых вещей
  3. База данных хранит ASCII-Text
  4. - проходит время -
  5. Затем при редактировании: загрузка ASCII из базы данных
  6. html_entity_decode($dbData, ,'UTF-8') -> ожидает ASCII, возвращает кодировку UTF-8
  7. Через $view->escape(): htmlspecialchars -> ожидает UTF-8, возвращает UTF-8
  8. Браузер -> ожидает UTF-8

tl; dr / recap

  • Установите метатег типа контента с нужным набором символов
  • Убедитесь, что все функции кодирования / декодирования осведомлены о выбранной вами кодировке (это означает: быть последовательным)
2 голосов
/ 26 июля 2011

Вы также можете использовать Zend_Filter_HtmlEntities () вместо функций php. Он не выполняет больше функций php, но гарантирует постоянную кодировку в вашей форме.

...