3

「都市」エンティティと多対一の関係を持つ「人」エンティティがあります。

人の関係のマッピングは次のとおりです。

/**
* @ORM\ManyToOne(targetEntity="City", inversedBy="persons", cascade={"persist"})
*/
private $city;

および市の:

/**
* @ORM\OneToMany(targetEntity="Person", mappedBy="city")
*/
private $persons;

doctrine:generate:crud によって生成された基本的な Symfony 2 'person' コントローラーを使用します。

$entity  = new Person();
$form = $this->createForm(new PersonType(), $entity);
$form->bind($request);

if ($form->isValid()) {

        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();
}

PersonType フォーム タイプは CityType をインスタンス化します

class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
        $builder
        ->add('city', new CityType())
        ->add('firstname')
        ->add('lastname')
        ->add('gender')
        ...

CityType フォーム タイプには 1 つのテキスト フィールドがあります

class CityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('cityname', 'text');
     }
}

フォームを送信すると、cascade={"persist"} のおかげで、Person エンティティと City エンティティが作成されます。

DB に既に存在する都市名をフォームに入力すると問題が発生し、Doctrine は同じ都市名で別のエントリを作成します。

Doctrine がそれを検出し、Person テーブルで既存の city_id を使用する簡単な方法はありますか?

4

2 に答える 2

2

1つの解決策は、エンティティの永続化をカスケードしないことです。つまり

    if ($form->isValid()) {
        $data = $form->getData();
        $em = $this->getDoctrine()->getEntityManager();

        $city = $em->getRepository('YourBundle:City')
                   ->findOneByCityname($data['cityname']);

        if($city == null){
            $city = new City();
            $city->setName($data['cityname']);
            $em->persist($city);
            $em->flush();
        }

        $entity->setCity($city);
        $em->persist($entity);
        $em->flush();
    }
于 2012-10-27T04:04:26.840 に答える
2

@vadim が言ったように、datatransformer を使用する必要があります。最初は戸惑うかもしれませんが、30分もすれば覚えられるでしょう。世界中に同じ名前の都市がたくさんあることに注意してください。

最善の解決策はこれです。そのテキストフィールドに、ユーザーは次のような名前を入力しますBelgrade, Montana, Usa(ところで、ベオグラードはセルビアの首都で、同じ名前の都市の例を示しています)。Datatransformer は DB を読み取り、リンクできるベオグラードの正しい都市を見つけます。

これを実行すると (非常に簡単です)、そのフィールドのオートコンプリートを作成できます。@artworkad の提案は非常に複雑で、後でさらに問題が発生します。

于 2012-10-27T17:57:22.113 に答える