When using EntityType to show a select, can't

2019-08-06 14:03发布

问题:

I have two related entities in my symfony project - which are stored using Doctrine. One entity is "Advertiser" which has an id and a name. The other entity - which is causing the problem - is for a "Report" which has an id of it's own along with a field called "advertiser_id".

When adding a report for an advertiser, in the Symfony form, I'm using EntityType for the advertiser_id field so that I can display a select of advertisers. That part is working great, but when I try to submit the form, I get an error because it's passing an Advertiser object instead of the id of the advertiser to the advertiser_id field.

Here's what I have in my form's builder:

$builder
    ->add('advertiser_id', EntityType::class, [
        'class'        => Advertiser::class,
        'query_builder' => $this->advertiserRepository->findAllNotDeletedUnpaginated(),
        'choice_label' => 'name',

    ])
    ->add('submit', SubmitType::class, [
        'label' => 'Submit',
    ])
;

When I submit the form, I get this error: Expected argument of type "integer", "App\Entity\Advertiser" given.

Any idea on how I can force symfony to only try to save the id of the advertiser that was selected rather than passing the entire advertiser?

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.

I've tried the code the iiirxs mentioned previously with the callback transformer - changing 'advertiser_id' to 'advertiser' - but I've had no luck with that. I've been reading posts like this Symfony hiddenType using data_class for entity instead of transformer, but I'm having trouble getting the value for 'advertiser' the way they are getting $options['selected_course'] in that example.

When I try (for testing purposes) hard coding a value of 1 for advertiser, then putting this on the form, the form shows, but I get an error when submitting it:

    $advertiser=1;

    $builder
        ->add('advertiser', HiddenType::class,['data' => $advertiser, 'data_class' => null])

The error I get when submitting the form is: Expected argument of type "App\Entity\Advertiser or null", "string" given.

I'm sorry for beating a dead horse about this. This seems like it should be such a common/easy thing to do, but I'm having a hard time finding how to make it a hidden field. Any ideas would be greatly appreciated!

回答1:

The problem is that you have not defined correctly an association with Advertiser entity in your Report entity. You should have defined an association like this:

// inside Report.php class

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\Advertiser")
 */
private $advertiser;

instead of defining a field that holds the foreign key advertiser_id. Doctrine is smart enough to map the advertiser field to an advertiser_id foreign key on your database on its own, so it would be better to use an association mapping. You can find more in the documentation.

However, if you indeed have to use only an integer to store the advertiser_id as an integer for your own reasons, you should use Symfony's Data Transformer to transform the advertiser entity to an integer like this:

$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();
            }
        ))
    ;

In my code above I used a CallbackTransformer to implement the transformation but you could also use a transformer class to do it. You can find also more about this in the data transformers documentation.