Intereting Posts
Почему, если я зарегистрировался на своем веб-сайте как зарегистрированный пользователь, я не могу получить доступ к другим страницам после установки правил сеанса? Отправить переменную с одной страницы на другую в PHP Простое, но тяжелое приложение, потребляющее много ресурсов. Как оптимизировать? PHP array_merge, если не пустой Заменить текст в скобках так называемой переменной в PHP Как получить IP-адрес пользователя REST Использование NSURLRequest для передачи пар ключ-значение в PHP-скрипт с помощью POST phpunit не находит никаких тестов с тегом Director xml, но делает с (некоторыми) файлами теги Как мне вызывать мои C ++-файлы через интерфейс CGI? Как скрыть форму при отправке на ту же страницу? Вывести соединение mysql в другой класс Как преобразовать скрипт с использованием функций mysql_ для использования функций mysqli_? Symfony2 – FOSUserBundle – Несколько мест входа в систему Разница между требованием и установкой против создания проекта в композиторе Как обновить статус Facebook с моего собственного сайта?

symfony: не можем ли мы иметь скрытое поле объекта?

Я передаю форму с полем сущности в symfony.

Он работает хорошо, когда я выбираю регулярное поле объекта.

$builder ->add('parent','entity',array( 'class' => 'AppBundle:FoodAnalytics\Recipe', 'attr' => array( 'class' => 'hidden' ) )) 

Он выдает следующую ошибку при выборе -> add ('parent', 'hidden'):

Ожидается, что данные вида формы будут иметь тип scalar, массив или экземпляр \ ArrayAccess, но это экземпляр класса AppBundle \ Entity \ FoodAnalytics \ Recipe. Вы можете избежать этой ошибки, установив опцию «data_class» в «AppBundle \ Entity \ FoodAnalytics \ Recipe» или добавив трансформатор представлений, который преобразует экземпляр класса AppBundle \ Entity \ FoodAnalytics \ Recipe в скаляр, массив или экземпляр \ ArrayAccess. 500 Внутренняя ошибка сервера – LogicException

Не можем ли мы иметь скрытые поля объектов? Почему нет? Должен ли я поместить другое скрытое поле для получения идентификатора объекта?

РЕДАКТИРОВАТЬ :

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

Solutions Collecting From Web of "symfony: не можем ли мы иметь скрытое поле объекта?"

Я думаю, вы просто сбиты с толку о типах полей и о том, что они представляют.

Поле entity является типом поля choice . Поля выбора зависят от значений, выбираемых пользователем в форме. Когда эта форма отображается, Symfony будет генерировать список возможных вариантов, основанных на базовом классе поля сущности, а значение каждого выбора в списке – это идентификатор соответствующего объекта. После отправки формы Symfony увлажнит объект для вас, представляющий выбранный объект. Поле entity обычно используется для отображения ассоциаций сущностей (например, список roles вы можете выбрать для назначения user ).

Если вы просто пытаетесь создать местозаполнитель для поля идентификатора объекта, то вы будете использовать hidden ввод. Но это работает только в том случае, если класс формы, который вы создаете, представляет собой объект (т. data_class формы относится к сущности, которую вы определили). Затем поле ИД правильно сопоставляет идентификатор объекта типа, определенного в виде data_class формы.

EDIT: одним из решений вашей конкретной ситуации, описанным ниже, было бы создание нового типа поля (назовем его EntityHidden), который расширяет тип hidden поля, но обрабатывает преобразование данных для преобразования в / из объекта / id. Таким образом, ваша форма будет содержать идентификатор объекта как скрытое поле, но приложение будет иметь доступ к самой сущности после отправки формы. Конечно, преобразование выполняется преобразователем данных.

Вот пример такой реализации, для потомков:

 namespace My\Bundle\Form\Extension\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\DataTransformerInterface; /** * Entity hidden custom type class definition */ class EntityHiddenType extends AbstractType { /** * @var DataTransformerInterface $transformer */ private $transformer; /** * Constructor * * @param DataTransformerInterface $transformer */ public function __construct(DataTransformerInterface $transformer) { $this->transformer = $transformer; } /** * @inheritDoc */ public function buildForm(FormBuilderInterface $builder, array $options) { // attach the specified model transformer for this entity list field // this will convert data between object and string formats $builder->addModelTransformer($this->transformer); } /** * @inheritDoc */ public function getParent() { return 'hidden'; } /** * @inheritDoc */ public function getName() { return 'entityhidden'; } } 

Просто обратите внимание, что в классе типа формы все, что вам нужно сделать, это назначить скрытый объект его соответствующему свойству поля формы (в рамках модели / класса данных), а Symfony будет генерировать скрытый ввод HTML должным образом с идентификатором объекта как его значение. Надеюсь, это поможет.

Просто сделал это на Symfony 3 и понял, что он немного отличается от того, что уже было опубликовано здесь, поэтому я решил, что стоит поделиться.

Я просто создал универсальный преобразователь данных, который можно было бы легко повторно использовать во всех типах вашей формы. Вам просто нужно передать свой тип формы, и все. Нет необходимости создавать собственный тип формы.

Прежде всего, давайте посмотрим на трансформатор данных:

 <?php namespace AppBundle\Form; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Class EntityHiddenTransformer * * @package AppBundle\Form * @author Francesco Casula <fra.casula@gmail.com> */ class EntityHiddenTransformer implements DataTransformerInterface { /** * @var ObjectManager */ private $objectManager; /** * @var string */ private $className; /** * @var string */ private $primaryKey; /** * EntityHiddenType constructor. * * @param ObjectManager $objectManager * @param string $className * @param string $primaryKey */ public function __construct(ObjectManager $objectManager, $className, $primaryKey) { $this->objectManager = $objectManager; $this->className = $className; $this->primaryKey = $primaryKey; } /** * @return ObjectManager */ public function getObjectManager() { return $this->objectManager; } /** * @return string */ public function getClassName() { return $this->className; } /** * @return string */ public function getPrimaryKey() { return $this->primaryKey; } /** * Transforms an object (entity) to a string (number). * * @param object|null $entity * * @return string */ public function transform($entity) { if (null === $entity) { return ''; } $method = 'get' . ucfirst($this->getPrimaryKey()); // Probably worth throwing an exception if the method doesn't exist // Note: you can always use reflection to get the PK even though there's no public getter for it return $entity->$method(); } /** * Transforms a string (number) to an object (entity). * * @param string $identifier * * @return object|null * @throws TransformationFailedException if object (entity) is not found. */ public function reverseTransform($identifier) { if (!$identifier) { return null; } $entity = $this->getObjectManager() ->getRepository($this->getClassName()) ->find($identifier); if (null === $entity) { // causes a validation error // this message is not shown to the user // see the invalid_message option throw new TransformationFailedException(sprintf( 'An entity with ID "%s" does not exist!', $identifier )); } return $entity; } } 

Поэтому идея состоит в том, что вы вызываете ее, передавая там объект-менеджер, объект, который вы хотите использовать, а затем имя поля, чтобы получить идентификатор объекта.

В основном так:

 new EntityHiddenTransformer( $this->getObjectManager(), Article::class, // in your case this would be FoodAnalytics\Recipe::class 'articleId' // I guess this for you would be recipeId? ) 

Давайте теперь все вместе. Нам просто нужен тип формы и немного конфигурации YAML, и тогда нам хорошо идти.

 <?php namespace AppBundle\Form; use AppBundle\Entity\Article; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\OptionsResolver\OptionsResolver; /** * Class JustAFormType * * @package AppBundle\CmsBundle\Form * @author Francesco Casula <fra.casula@gmail.com> */ class JustAFormType extends AbstractType { /** * @var ObjectManager */ private $objectManager; /** * JustAFormType constructor. * * @param ObjectManager $objectManager */ public function __construct(ObjectManager $objectManager) { $this->objectManager = $objectManager; } /** * @return ObjectManager */ public function getObjectManager() { return $this->objectManager; } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('article', HiddenType::class) ->add('save', SubmitType::class); $builder ->get('article') ->addModelTransformer(new EntityHiddenTransformer( $this->getObjectManager(), Article::class, 'articleId' )); } /** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => 'AppBundle\Entity\MyEntity', ]); } } 

И затем в вашем файле services.yml :

 app.form.type.article: class: AppBundle\Form\JustAFormType arguments: ["@doctrine.orm.entity_manager"] tags: - { name: form.type } 

И в вашем контроллере:

 $form = $this->createForm(JustAFormType::class, new MyEntity()); $form->handleRequest($request); 

Это оно 🙂

Быстрое решение без создания новых классов трансформаторов и типов. Если вы хотите предварительно сформировать связанный объект из db.

 // Hidden selected single group $builder->add('idGroup', 'entity', array( 'label' => false, 'class' => 'MyVendorCoreBundle:Group', 'query_builder' => function (EntityRepository $er) { $qb = $er->createQueryBuilder('c'); return $qb->where($qb->expr()->eq('c.groupid', $this->groupId())); }, 'attr' => array( 'class' => 'hidden' ) )); 

Это приводит к одному скрытому выбору, например:

 <select id="mytool_idGroup" name="mytool[idGroup]" class="hidden"> <option value="1">MyGroup</option> </select> 

Но да, я согласен с тем, что при использовании DataTransformer вы можете добиться чего-то вроде:

 <input type="hidden" value="1" id="mytool_idGroup" name="mytool[idGroup]"/> 

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

 {% block _recipe_parent_widget %} {%- set type = 'hidden' -%} {{ block('form_widget_simple') }} {% endblock %}