У меня есть два связанных объекта в моем проекте symfony, которые хранятся с помощью Doctrine. Одной сущностью является «Рекламодатель», у которой есть идентификатор и имя. Другой объект, который вызывает проблему, предназначен для «Отчета», который имеет собственный идентификатор вместе с полем «advertiser_id».
При добавлении отчета для рекламодателя в форме Symfony я использую EntityType для поля рекламодателя_id, чтобы отображать выбранных рекламодателей. Эта часть работает отлично, но когда я пытаюсь отправить форму, я получаю сообщение об ошибке, потому что она передает объект Advertiser вместо идентификатора рекламодателя в поле Advertisingr_id.
Вот что у меня есть в конструкторе моей формы:
$builder
->add('advertiser_id', EntityType::class, [
'class' => Advertiser::class,
'query_builder' => $this->advertiserRepository->findAllNotDeletedUnpaginated(),
'choice_label' => 'name',
])
->add('submit', SubmitType::class, [
'label' => 'Submit',
])
;
Когда я отправляю форму, я получаю эту ошибку: Задан ожидаемый аргумент типа "целое число", "App\Entity\Advertiser".
Любая идея о том, как я могу заставить symfony пытаться сохранить только идентификатор выбранного рекламодателя, а не передавать всего рекламодателя?
UPDATE: Now that I've refactored it so that the advertiser is a related entity to report, I'm trying to figure out how to make the advertiser a hidden field and getting nowhere.
Я пробовал код, упомянутый ранее iirxs, с преобразователем обратного вызова - изменением «advertiser_id» на «advertiser», но мне не повезло с этим. Я читал сообщения, подобные этому Symfony hiddenType, использующий data_class для объекта вместо трансформатора, но у меня возникли проблемы с получением значения для «рекламодателя» так, как они получают $options['selected_course'] в этом примере.
Когда я пытаюсь (в целях тестирования) жестко запрограммировать значение 1 для рекламодателя, а затем помещаю его в форму, форма отображается, но при отправке я получаю сообщение об ошибке:
$advertiser=1;
$builder
->add('advertiser', HiddenType::class,['data' => $advertiser, 'data_class' => null])
Ошибка, которую я получаю при отправке формы: Ожидаемый аргумент типа "App\Entity\Advertiser or null", задана "строка".
Извините, что избил дохлую лошадь по этому поводу. Кажется, что это должно быть таким обычным/простым делом, но мне трудно найти, как сделать это скрытым полем. Благодарим за любую идею!
Вы можете поделиться здесь своим файлом сущности Report.php? Вы указали тип поля как ManyToOne в аннотациях?
Есть ли причина, по которой вы хотите передать в форму идентификатор, а не сущность? (symfony на самом деле делает за вас работу по сериализации/десериализации EntityType)




Проблема в том, что вы неправильно определили ассоциацию с сущностью "Рекламодатель" в сущности отчета. Вы должны были определить такую ассоциацию:
// inside Report.php class
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Advertiser")
*/
private $advertiser;
вместо определения поля, содержащего внешний ключ advertiser_id. Doctrine достаточно умна, чтобы самостоятельно сопоставить поле рекламодателя с внешним ключом advertiser_id в вашей базе данных, поэтому было бы лучше использовать сопоставление ассоциации. Вы можете найти больше в документация.
Однако, если вам действительно нужно использовать только целое число для хранения advertiser_id в виде целого числа по вашим собственным причинам, вам следует использовать Преобразователь данных Symfony для преобразования сущности рекламодателя в целое число, подобное этому:
$advertiserRepository = $this->advertiserRepository;
$builder->get('advertiser_id')
->addModelTransformer(new CallbackTransformer(
function ($advertiserAsInteger) use ($advertiserRepository) {
// transform the integer to an entity object
return $advertiserRepository->find($advertiserAsInteger);
},
function ($advertiserAsEntity) {
// transform the entity back to an integer
return $advertiserAsEntity->getId();
}
))
;
В приведенном выше коде я использовал CallbackTransformer для реализации преобразования, но вы также можете использовать для этого класс преобразователя. Вы также можете найти больше об этом в документация по преобразователям данных.
Спасибо, iirxs! Я собираюсь реорганизовать свою сущность в соответствии с вашим первым предложением.
Я провел рефакторинг приложения, чтобы рекламодатель был связан с отчетом. Сейчас пытаюсь отрендерить форму для отчета и пытаюсь понять как отобразить рекламодателя в форме. Я попробовал базовый «-> add('advertiser')» в конструкторе, но это дает мне эту ошибку: Catchable Fatal Error: Object of class App\Entity\Advertiser не может быть преобразован в строку. Будем признательны за любые мысли или ссылки о том, как правильно отображать форму, когда есть связанный объект!
Вы добавили поле рекламодателя в свою форму как EntityType?
Еще раз спасибо, iirxs! Изменение построителя, чтобы включить это, сработало! ->add('рекламодатель', EntityType::class, array( 'class' => Advertiser::class, 'choice_label' => 'name', ))
Я хотел добавить к части ответа @iiirxs пользовательский тип, который я только что реализовал на основе предложения преобразователя модели.
Этот тип расширяет встроенный EntityType, поэтому во многих случаях вы можете заменить EntityType на EntityReferenceType и вместо этого сопоставить идентификатор.
Это полезно, если форма не сопоставляется непосредственно с сущностью, например, с использованием шаблона команды, поэтому вы предпочитаете идентификатор.
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\PropertyAccess\PropertyAccess;
class EntityReferenceType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'id_property' => 'id'
]);
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addModelTransformer(
new CallbackTransformer(
function ($entityIdentifier) use ($options) {
if ($entityIdentifier === null) {
return null;
}
return $options['em']->getRepository($options['class'])->find($entityIdentifier);
},
function ($entity) use ($options) {
if ($entity === null) {
return null;
}
return PropertyAccess::createPropertyAccessor()->getValue($entity, $options['id_property']);
}
)
);
}
public function getParent(): string
{
return EntityType::class;
}
}
Не могли бы вы проверить
advertiser_idопределение этого поля в вашем объекте. Если он определен как целое число, вы должны изменить его.