Molarro
Molarro

Reputation: 1047

Unclear Symfony form error "This value is already used"

I use Symfony 2.7.3 and I have following form ("app_cargo_source"):

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('country', 'choice', [
            'choices' => $this->worldManager->getCountriesByRegionIds([1, 2]),
            'choice_label' => 'name',
            'choice_value' => 'id',
            'label' => false,
            // *this line is important* see docs for choice type
            'choices_as_values' => true
        ])

       // ...
    ;

    // ...
}

The form is used in another form (app_cargo):

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('source', 'app_cargo_source')
        // ...
    ;

    // ...
}

“choices” field in first form is an array of WorldCountry objects, which are selected from database by regions id. Here is a picture of the array from Profiler:

enter image description here

WorldCountry and WorldRegion have unidirectional ManyToOne relationship.

The problem is, when I select country in country field and submit the form, back I receive following error for country field:

enter image description here

Why that happens, and why Symfony at all try assign a value to region?

P.S. Please let me know if more information is needed.

Upvotes: 3

Views: 2024

Answers (1)

Molarro
Molarro

Reputation: 1047

Right! It seems that problem was in uniqueness of region field in my WorldCountry entity. My WorldRegion entity is following:

/**
 * WorldRegion
 *
 * @ORM\Table(name="world_region")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\WorldRegionRepository")
 *
 * @UniqueEntity(fields={"code"}, message="Region code must be unique")
 */
class WorldRegion
{
    /**
     * @var integer
     *
     * @ORM\Column(name="region_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     * @Assert\NotBlank()
     *
     * @ORM\Column(name="region_code", type="string", length=5,
     *  unique = true, nullable=false)
     */
    protected $code;

    // ...
}

And WorldCountry:

/**
 * WorldCountry
 *
 * @ORM\Table(name="world_country")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\WorldCountryRepository")
 *
 * @UniqueEntity(fields={"iso2"})
 * @UniqueEntity(fields={"iso3"})
 * @UniqueEntity(fields={"region"}) // This line should be removed!
 */
class WorldCountry
{
    /**
     * @var integer
     *
     * @ORM\Column(name="country_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var WorldRegion
     *
     * @ORM\ManyToOne(targetEntity="WorldRegion",
     *  cascade={"all"}
     * )
     * @ORM\JoinColumn(name="region_id", referencedColumnName="region_id")
     */
    protected $region;

    // ...
}

As seen WorldCountry has unique constraint on region field. In this case it is logical error. Because ManyToOne states that in database table for WorldCountry, countries are unique, but regions - not. But I, using @UniqueEntity, claim that regions also should be unique. So, annotation @UniqueEntity(fields={"region"}) should be removed from WorldCountry entity.

P.S. Please let me know if I can improve my answer.

Upvotes: 2

Related Questions