Вы могли бы попробовать использовать 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));
});
Спасибо! Оно работает! Для этой задачи я также использовал событие PrePersist. Но я хочу понять следующее. Как я могу изменить данные формы перед сохранением, а затем сохранить результат в базе данных с помощью FormEvents. Вы можете мне помочь? – Antin
Какой из моих методов вы попробовали? PrePersist также работал бы, но имейте в виду, что это будет только для первоначальной вставки, а не для каких-либо обновлений. Какую задачу вы пытаетесь сделать в PrePersist? Вы имеете в виду делать это через это, а не другие методы, которые у меня выше? –
Извините, что я еще не писал. Я имею в виду подмножество одного из FormEvents в общедоступной функции кода buildForm (FormBuilderInterface '$ builder, array $ options) { $ builder-> add ('url'); $ builder-> addEventListener (DO DO) ' – Antin