Symfony初心者がつまづきがちな22個のポイント

  • 106
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

この記事はSymfony Advent Calendar 2015 17日目の記事です。前日の記事は@teematsuさんの「Symfony 2.8とPHP-DIのAuto Wiring」でした。


こんにちは。はじめまして。tarokamikazeです。
すっかりSymfonyおじさんと化した私は、数々の後輩たちにSymfonyに関する相談を受けてきました。
そのなかでも、社内でよく聞かれることをまとめます。

導入編

The Symfony Book を読んだ人、ブログチュートリアルをやってみた人向けです。

01.この案件にSymfony2を使いたいんですが

下記のような条件では、Symfony2はおすすめです。

  • 専用サーバーを使える。
  • 他のPHP フレームワークを触ったことがある。
  • ビジネスロジックが複雑になりそうなシステムを作る。(業務アプリ等)
  • テストは当然書く。 1
  • プログラミング技術を磨きたい。
  • PHPのゆるふわさに嫌気が差してきた。2
  • (特に学習初期は)開発速度を犠牲にできる。ある程度学習コストを許容できる。
  • ドメイン駆動設計に興味がある。

02.公式サイトどこ?

日本語サイト は情報が古いです。本家(英語) を見ましょう。
不満に思う人は、翻訳作業に参加したらいいと思います。

以前参加したSymfony勉強会では
「Symfonyを使うくらいリテラシーのある人は、英語くらい読めるっしょwww」
と言っていました。恐ろしいですね。

03.日本語の本はありますか?

古いですが、「効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門 」しかなかったんですよ。書名にSymfonyって書いていないという罠。

しかし先日「基本からしっかり学ぶ Symfony2入門 」が出ました! いい時代ですね!

04.ここは読んどけって記事はありますか?

公式が充実してます。それを読めば、たいていのことは載っています。
Symfonyの歩き方/5分でわかるSymfony Best Practices はいい記事ですね。@ryo511 さん、ありがとうございます!

05.おすすめのバンドルは?

06.どのバージョンを使えばいいのでしょう?

ここを読んで考えましょう。Symfonyはサポート期間を明示してくれているので、利用バージョンを考えやすいですよね。

2015年12月現在、個人的には以下のように考えています。

  • 実案件なら、最新版LTSの 2.8
  • 勉強用なら、最新版の 3.0

07.公式の通りにインストールしたけど動かない

本当に公式の通りにインストールしたんですか? 本当に??

多くの人が、なぜかここ を読み飛ばします。
きちんとキャッシュ・ログディレクトリにパーミッションを設定しましょう。

  • Mac なら「2. Using ACL on a system that supports chmod +a」
  • CentOSなら「3. Using ACL on a system that does not support chmod +a」
  • Windowsなら、まずはMacを使わせてもらえるように上司(財布)と交渉しましょう。
    • 無理なら、VirtualBox に Linux を突っ込めばいいんじゃないでしょうかね。

08.フォルダ構成はどうしたらいいの?

Advent Calendarでちょうどいい記事が出ましたね。@issei-mさん、ありがとうございます!

09.設定は何で書けばいいの? XML?

Symfony Best Practicesによると、以下の様な感じです。

  • Routingは、アノテーション
  • DoctrineのEntity定義も、アノテーション
  • サービス設定はyaml 3

10.設定内容が反映されない><

キャッシュクリアしましょう。
 
php app/console cache:claer

それでもだめなら、apache(php-fpm)を再起動しましょう。
設定次第で、Symfony は app/cache だけではなく、APC(u) にもキャッシュをためます。

11.なんか英語のエラー出た><

まずは落ち着いて、エラーメッセージ読んでください。英語が苦手なら、Google翻訳に頼ってください。
それでもわからなければ、エラーメッセージでググってください。

利用者が多いフレームワークって、簡単なエラーでも記事が引っかかるのでいいですよね。

実装編

実案件で実装を始める人向けです。

12.Modelはどこに書くの?

「貴様の言うModelとは何だ? 」と訊くと、たいてい詰まりますよねw

Symfony2 は、(暗に)ドメイン駆動設計を推奨しています。 4

  • データを取り出したいなら、Repository
  • ビジネスロジックを記述したいなら、サービスを作ってDIコンテナに登録

という風に書けばよいでしょう。

13.確認フォームってどうやったら出せるの?

コツは、「Entity自体ではなく、Postされたarrayをセッションに詰めること」。
Doctrineは、Entity にメタデータを詰めます。このせいで、Entityをセッションに詰めると挙動がおかしくなります。(メタデータがserialize できません)
Formをからめるのであれば、POSTされたarrayをセッションに詰めましょう。

確認画面のAction ではセッションに詰めたarrayを、入力画面と同じFormType にbindしてあげればよいのです。

14.Ajax用の API 作りたい!

FOSRestBundle を使ってください。JMSSerializer便利だよぉ。

え、APIがちょっとしかないから、バンドルは導入したくない?しょうがないなぁ。
ここの通りにやればいいんじゃないのかなあ。

ちょっと古いけど、Symfony2 REST API: the best wayも目を通しておいた方がいいでしょう。

15.CSVダウンロード機能を作りたい!

最近のExcelは、XMLも読めますよ?(真顔) 5

冗談はさておき、こことか見たらいいんじゃないでしょうかね。

16.FormやAPIの形式とEntityの形がかけ離れている......つらい......

以下のようなやり方もあります。定義が散るので望ましくはないのですが。6

  1. Form / API の形に合わせたニセEntity(JavaBean的なモノ)をつくる。
  2. ニセEntity にあわせたFormType を用意し、リクエストデータはそれで受ける。
  3. ビジネスロジックに ニセEntity を 投げる。
  4. ビジネスロジック内でニセEntityを、本物のEntityに変換する。その後、永続化処理等を行う。

このときValidationは、form 側でやってもいいですし、変換後の本物EntityをValidatorサービスに投げてもいいでしょう。

17.ログインの仕組みを独自に作りたいんですけど......

悪いことは言わない。やめておけ。

Symfony2のログイン関係の仕組みは、複雑です。
可能な限りネイティブの仕組み、またはFOSUserBundleなどの外部バンドルにまかせたほうがいいです。
昔触ろうとして、一週間かかりました......

Doctrine編

18.Doctrineが不要なカラムもselectしようとしています。なんとかしたい。

ORM とはそういうものです。DBを富豪的に使うのです。
それでも重いというのなら、札束を積んで物理で殴ればよいのです。

19.Lazy Load うざい

デバッグコンソールを見ると、大量のSQLを吐いているときがあります。
原因としては、Doctrine で Entityに OneToMany を設定していると
「親も子も使うことがわかりきっているのに、子供にアクセスしたときにlazy load されて大量のSQLが走ってる」
というケースが多いです。

こういう場合は、DQLをしっかり書きましょう。
DQLでjoinすれば、一発で取ってきてくれます。

ParentRepository.php

class ParentRepository extends EntityRepository
{
    public function findOneWithChild($parentId)
    {
        $qb = $this->createQueryBuilder('p');
        $qb->select('p, c') // selectにもjoin先のaliasを書くのがコツ
            ->join('p.children', 'c')
            ->andWhere('p.id = :parentId')
            ->setParameter(':parentId', $parentId);
        return $qb->getQuery()->getSingleResult();
    }
}

20.論理削除ってどうすればいいの?

まずはここ を読め。話はそれからだ。

StofDoctrineExtensionsBundleSoftdeleteable を使います。
削除日時のカラムがNot Null だったら、削除とみなされます。

21. OneToMany を設定していて、親のEntityと子供のEntityを一気にpersistしようとしたらエラーが出た

こういう単純な例って、なかなか見つからないんですよね。7

test.php
$em = $this->get('doctrine.orm.entity_manager');

$parentEntity = new ParentEntity();
$childEntity = new ChildEntity();
$childEntity->setParent($parentEntity);

$em->persist($parentEntity);
$em->persist($childEntity);

$em->flush();

22.「Update時に、自動的にあのカラムも更新する」とかやりたい。EventLister を使えばいいの?

悪いことは言わない。やめておけ。
頼むから、更新対象のEntityをビジネスロジッククラスに渡して処理するんだ。

この面倒臭さを説明しだすと、ひとつの記事になってしまいます。
とりあえず Doctrineのこのクラス を読んでみてください。理由がわかってもらえるはずです。

ちなみに、更新日時を入れたいだけだったら
StofDoctrineExtensionsBundleTimestampable を使いましょう。


ちなみに22個である理由は、妻が猫好きだからです。
明日は@naoyes さんです!



  1. Symfony2はテストが書きやすいと言われています。 

  2. 自然とJavaっぽいコードになります。Java の Spring Framework に似ていると言われています。 

  3. JMSDiExtraBundleを使えば、サービスもアノテーションで定義できます。 

  4. そういった意味では、Symfonyは単なる「MVC」フレームワークではない何かです。以前参加したSymfony勉強会でも、ドメイン駆動設計の話題でもちきりでした。 

  5. 筆者はExcelとCSVを憎んでいます。エンジニアになる前は、Excel職人(運用のひと)でした。 

  6. 実例をGithubにあげたい。だが時間がない...... 

  7. Cascade persist する手もありますが、おすすめされていません。 

この投稿は Symfony Advent Calendar 201517日目の記事です。