2014-12-19 4 views
2

У меня есть объект сообщения с полем 'url'. И форма MessageType. Пользователь может вводить разные URL-адреса в 'url', но только хост сохраняется в базе данных. Мне нужно использовать Symfony2 Form Event. Так что я пытаюсь реализовать его в следующем коде:Изменить данные поля формы после отправки

class MessageType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('url'); 

     $builder->addEventListener(
       FormEvents::SUBMIT, 
       function(FormEvent $event) { 
        $form = $event->getForm(); 

        $data = $event->getData(); 
        $url = $data->getUrl(); 
        $form->setData(parse_url($url), PHP_URL_HOST); 
       } 
     ); 
    } 
} 

я получаю следующее уведомление:

«Примечание: Массив для преобразования строки»

Что это значит?

Моей сущности Сообщений имеет метод __toString():

public function __toString() 
{ 
    return $this->getUrl(); 
} 

Спасибо Вам

ответ

5

Вы могли бы попробовать использовать Data Transformer, который предназначен для этой цели. Например:

namespace Vendor\MyBundle\Form\DataTransformer; 

use Symfony\Component\Form\DataTransformerInterface; 

class HostFromUrlTransformer implements DataTransformerInterface 
{ 
    public function transform($host) 
    { 
     return ($host === null) ? "" : $host; 
    } 

    public function reverseTransform($url) 
    { 
     return parse_url($url, PHP_URL_HOST); 
    } 
} 

Затем реализации в виде:

use Vendor\MyBundle\Form\DataTransformer\HostFromUrlTransformer; 

class MessageType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add(
      $builder->create('url') 
       ->addModelTransformer(new HostFromUrlTransformer()) 
     ); 
    } 
} 

Этот метод, безусловно, имеет свои недостатки, однако. Вы не сможете добавить Assert\URL на объект, потому что валидация происходит после преобразований, а просто наличие хост-части больше не сделает ее действительной. Вы можете обойти это, передав валидатор Symfony на ваш преобразователь данных, а затем проверив $ url против Assert\Url, аналогичный методу здесь: Combine constraints and data transformers, но это также немного взломано.

Простейшее решение, чем все это было бы просто обновить метод setUrl($url) в вашей организации, чтобы что-то вроде этого:

public function setUrl($url) 
{ 
    $host = parse_url($url, PHP_URL_HOST); 
    $this->url = $host ?: $url; 
} 

Таким образом, в этом случае, если вы передаете в URL он сохраняет как только $ host, и если вы используете setUrl(), и он уже преобразован, он просто сохранит уже существующее значение.

Даже еще лучше, вы могли бы просто сохранить полный URL они посылают вас, что позволит вам поддерживать проверку @Assert\URL, а затем добавьте следующие две функции:

public function getHost() 
{ 
    return parse_url($this->url, PHP_URL_HOST); 
} 

public function __toString() 
{ 
    return $this->getHost(); 
} 

выше позволяет сохранить все данные, которые были сохранены, и изменяет работу по разбору URL-адреса, который будет выполняться вашим приложением, вместо того, чтобы пытаться разобрать на уровне базы данных. Метод __toString() всегда возвращает хост, и у вас все еще есть доступ к полному URL-адресу, который был передан, если вам это нужно. Вы даже можете избавиться от функции getHost() выше.

Если вы хотите использовать FormEvent, вы на правильном пути, но код немного не работает. См. http://symfony.com/doc/current/components/form/form_events.html#b-the-formevents-submit-event для более подробной информации.

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) 
{ 
    $data = $event->getData(); 
    $data['url'] = parse_url($data['url'], PHP_URL_HOST); 

    $event->setData($data); 

    // this one-liner might also work in place of the 3 lines above 
    $event->setData('url', parse_url($event->getData('url'), PHP_URL_HOST)); 
}); 
+0

Спасибо! Оно работает! Для этой задачи я также использовал событие PrePersist. Но я хочу понять следующее. Как я могу изменить данные формы перед сохранением, а затем сохранить результат в базе данных с помощью FormEvents. Вы можете мне помочь? – Antin

+0

Какой из моих методов вы попробовали? PrePersist также работал бы, но имейте в виду, что это будет только для первоначальной вставки, а не для каких-либо обновлений. Какую задачу вы пытаетесь сделать в PrePersist? Вы имеете в виду делать это через это, а не другие методы, которые у меня выше? –

+0

Извините, что я еще не писал. Я имею в виду подмножество одного из FormEvents в общедоступной функции кода buildForm (FormBuilderInterface '$ builder, array $ options) { $ builder-> add ('url'); $ builder-> addEventListener (DO DO) ' – Antin

1

Согласно PHP документу для parse_url():

Если параметр компонента опущен, ассоциативный массив возвращаемых ,

http://php.net/manual/en/function.parse-url.php

Похоже, вы не правильно передать параметр компонента в вашем коде, есть неуместны скобка:

$form->setData(parse_url($url), PHP_URL_HOST); 

Должно быть:

$form->setData(parse_url($url, PHP_URL_HOST)); 

Кроме того, я не уверен, re устанавливая данные как вы должны, но я могу ошибаться. Это, как я думаю, что вы должны сделать это:

$form->get('url')->setData(parse_url($url, PHP_URL_HOST)); 

Вот полный (и непроверенные) код, который я имел в виду:

class MessageType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('url'); 

     $builder->addEventListener(
       FormEvents::SUBMIT, 
       function(FormEvent $event) { 
        $form = $event->getForm(); // FormInterface 
        $data = $event->getData(); 
        $url = $data->getUrl(); 
        $host = parse_url($url, PHP_URL_HOST); 
        if ($host) 
         $form->get('url')->setData($host); 
       } 
     ); 
    } 
} 
+0

Большой улов по параметрам, я пропустил его в первый раз, когда я посмотрел на вопрос. –

+0

@ Джейсон Роман. Что означает ваш комментарий? – Antin

+0

@paulgv Если вам нетрудно, пожалуйста, продемонстрируйте пример кода, как я могу изменить данные формы. Я пытаюсь по-разному, но полный URL-адрес сохраняется в моей базе данных. – Antin

Смежные вопросы