Symfony2: buildFormのform entity(choices)でwhereを通す


フォームの選択肢に他のテーブルで自分が登録したデータを表示するなどの場合、FormTypeを変更すればいいわけですが

$builder
    ->add('column_name', 'entity', array(
        'class' => 'AcmeYourBundle:Address',
        'query_builder' => function($repository){
            return $repository->createQueryBuilder('u')->orderBy('u.sort', 'DESC');
        }
    )
);

とすればいいわけですが、例えば

$repository->createQueryBuilder('u')->where('u.createdUser = '.$this->getUser()->getId());

を指定したい場合、これが非常にややこしくなります。非常によく使うケースで、簡単にできそうそうなのに。

どうしたら実現できるかというと2ステップで実現します。

1.”@security.context” と “@doctrine.orm.entity_manager” をインジェクション
2.FormTypeの編集
3.FormTypeにアクセスする

1.”@security.context” と “@doctrine.orm.entity_manager” をインジェクション

service.ymlにインジェクション内容を書き込みます。
“@security.context”, “@doctrine.orm.entity_manager”の2つをインジェクションします。

services:
    acme_yourbundle_address_form:
        class: AcmeYourBundle\Form\AddressType
        arguments: ["@security.context", "@doctrine.orm.entity_manager"]

2.FormTypeの編集

FormTypeを編集します。form typeはentityにしてclass option、query_builder optionをしています。classオプションは指定しなくともquery_builderで直接書いているので実際は不要なのですが仕様がそうなっていないので仕方がありません。

‘property’ => ‘title’はAcmeYourBundle:Addressのリストのラベルとして表示するカラム名を指定します。toString()を指定していればこの設定は無くともよいかと思います。

    
    private $securityContext, $entityManager;
    
    public function __construct($securityContext, $entityManager)
    {
        $this->securityContext = $securityContext;
        $this->entityManager = $entityManager;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $user = $this->securityContext->getToken()->getUser();
        $your_bundle = 'AcmeYourBundle:Address';
        $repository = $this->entityManager->getRepository($your_bundle);
        $query_builder = $repository->createQueryBuilder('u')->where('u.createdUser = '.$user->getId());
        $builder
            ->add('column_name', 'entity', array(
                'class' => $your_bundle,
                'query_builder' => $query_builder,
                'property' => 'title'
            ))
        ;
    }

3.FormTypeにアクセスする

ControllerなどからFormTypeにアクセスします。$this->get(‘acme_yourbundle_address_form’) としてアクセスします。

$editForm = $this->createForm($this->get('acme_yourbundle_address_form'), $entity);

New, Edit などのController methodを編集することになります。

  • このエントリーをはてなブックマークに追加

コメント

  1. shin より:

    調べものをしていて、この投稿に着いたのですが、 DI で指定しなくても、コントローラの createForm の第三引数に、 user_id を渡せますよね。そうすれば、query_builder で指定できると思いますが、どうでしょう?

  2. shin より:

    おっと。失敬。そのままでは、 user_id は渡せないですね。

    attr の属性として配列で user_id を渡すか、
    $resolver->setRequiredで、user_id を指定して渡せるようにすれば、良さそうですね

  3. yuta より:

    そんな簡単にFormType ClassにUser通ります? インジェクションしないと色々と実現できず、未だにこの方法が主流なのです。2.3.3から変わったりしているのかチェックしていないのですがうーむ。出来るのかもしれん。

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です