いきなりですが、本稿は『SymfonyとVue.jsを組み合わせるときは「Symfony Forms」の機能を使うのは諦めた方がいいかもしれない』ということを伝えたい、ただそれだけの記事です。『エンジニアたる者、どんなときでもまずは結論から話せ』と、物心ついた頃(嘘)から聞かされてきましたしね。
Symfonyで一般的なデータの入力や保存を行う画面をつくるなら、「Symfony Forms」という機能を利用するのが基本のようです。
公式ドキュメントでも、基本的な実装方法として紹介されています。
Symfony Formsを使うことで、コントローラー側でフォームと画面項目の定義をしておいて、画面側(テンプレート側)では自力でタグを書いたりせずに表示することができます。
試しに、テキスト項目が2つあるだけの画面を作る場合、こういう感じになるでしょうか。
// エンティティ namespace App\Entity; class Master { private string $name = ''; private string $description = ''; public function getName(): string { return $this->name; } public function setName(string $name): self { $this->name = $name; return $this; } public function getDescription(): string { return $this->description; } public function setDescription(string $description): self { $this->description = $description; return $this; } }
// フォーム namespace App\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; class MasterEditType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('name', TextType::class) ->add('desctiption', TextType::class) ; } }
// コントローラー namespace App\Controller; use App\Entity\Master; use App\Form\Type\MasterEditType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class MasterEditController extends AbstractController public function edit(Request $request) : Response { $master = new Master(); // ... $form = $this->createForm(MasterEditType::class, $master); return $this->render('master/edit.html.twig', [ 'form' => $form->createView(), ]); } }
<!-- 画面テンプレート(Symfony Form使用) --> <div> <div> <label>名称</label> {{ form_widget(form.name) }} </div> <div> <label>説明</label> {{ form_widget(form.description) }} </div> </div>画面のテンプレートには
<input type="text">
といったごく普通のHTMLタグが登場しません。Symfony formsがタグを生成してくれるのですね。ただ、リッチなフロント画面をVue.jsでごりごり書きたいときは、
<input type="text" v-model="master.name">
などとVue.jsのディレクティブを入れることになるのですが、Symfony Formsを使っているとそれがしにくくなります。そんなわけで、Vue.jsでいろいろやりたいならば、Symfonyは使ったとしてもSymfony Formsの機能は使わない方が良さそう、といった印象です。
Symfony Formsを使わずに書くなら、サーバ側ではSymfony Formの代わりに単純なオブジェクトを作ってリターンし、画面側ではVue.jsのお作法でそれを表示するような作りが良さそうです。
先ほどのコードを、Symfony Formsを使わずに(Vue.jsを使えるように)書き直すと、こんな感じでしょうか。
// 変更後のコントローラー(Symfony Formを使わない) namespace App\Controller; use App\Entity\Master; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class MasterEditController extends AbstractController public function edit(Request $request) : Response { $master = new Master(); // ... return $this->render('master/edit.html.twig', [ 'master' => [ 'name' => $master->getName(), 'description' => $master->getDescription(), ], ]); } }
// 変更後の画面テンプレート(Vue.js使用) <div> <div> <label>名称</label> <input type="text" v-model="mst.name"> </div> <div> <label>説明</label> <input type="text" v-model="mst.description"> </div> </div>
<!-- Vue.jsのスクリプト部分 --> <script> export default { props: { master: {}, }, setup(props) { const mst = ref(props.master); return { mst, }; }, } </script>ということで今回は、SymfonyとVue.jsを組み合わせるときのお話でした。Symfony単体やVue.js単体での使い方は情報があっても、組み合わせ方の情報はなかなか無いので書いてみました。
Web界隈はフレームワークやライブラリがたくさんあって、組み合わせるときは試行錯誤が要りますね。