web-dev-qa-db-ja.com

Symfony2の概念的な問題:一般的なバンドルと特定のバンドル

編集: Symfonyのベストプラクティス 私の質問のほとんどに答えてください。

Symfony2アプリに関していくつか質問があります。

フロントエンドとバックエンドがあり、いくつかの一般的なコード(日付表示、ページネーター、よく使用されるテンプレートなど)を使用します。

そこで、たとえばそれぞれのレイアウトを含む1つのFrontendBundleと1つのBackendBundleを作成しました。最初の質問:フロントエンドとバックエンドのバンドルを作成することをお勧めします。これは、コントローラーさえも持たない「一般的な」バンドルです。

2番目の質問:クックブックで、レイアウトをバンドルではなく、app/Resources/views /ディレクトリに配置する必要があることを読みました。すでにbase.html.twigファイルがありますが、frontend_layout.html.twigファイルのように、レイアウトもそこに配置する必要があるのでしょうか。

RootBundleという名前のバンドルを作成しました。これには、アプリがフロントエンドとバックエンドで必要とするすべてのものが含まれます。それは良い習慣ですか?または、PaginatorBundle、DateDisplayerBundleなど、提案された機能ごとに専用のバンドルを作成する必要がありますか?どこに置くべきかわからないものすべてを含む「その他の」バンドルが1つあるのは奇妙に聞こえます。どうやってそれをしますか?

37
Nanocom

新しいアプローチ

この回答を書いてから数か月後、私のアプローチが変わったので、コミュニティと共有しています。この答えは今でもかなり人気があり、新参者を私がもはや最善だとは思わないアプローチに導く可能性があります。そう...

現在、1つアプリ固有バンドルしかなく、それをAppBundleと呼んでいます。古いアプローチにはいくつかの問題があり、そのいくつかを次に示します。

  • たくさんのバンドルを作成するのは面倒です。新しいバンドルごとにバンドルクラスと標準フォルダーの束を作成し、それをアクティブにして登録する必要があります。ルートとDIなど。

  • 不必要な筋金入りの意思決定プロセス。特定のものが複数のバンドルで使用されているため、特定のものがどのバンドルに属するかを判断できない場合があります。そして、半日を費やして最終的にそれをどこに置くかについて難しい決断をした後、数日または数週間で、どのバンドルを調べるべきかをすぐに判断できないことに気付くでしょう—ほとんどの場合、決定は純粋な論理に基づいておらず、コイントスまたはより高い力を助けにもたらすために使用する手段に基づいて選択する必要があったためです。

    過去に一般的なものにCommonBundleを使用することを提案しましたが、そうすると、使用するバンドルの数または数に基づいて、CommonBundleとの間で物を移動するために多くの不要なリファクタリングを行う必要があります。後でそのこと。

  • とにかくアプリ固有のバンドルは相互に依存しています。人々がバンドルのアイデアに初めて出会ったとき、彼らの頭に浮かぶ主な考えの1つは次のようなものです。 "わーい!再利用可能なバンドルをたくさん持ってきます!」そのアイデアは素晴らしく、私はそれに反対するものは何もありません。問題は、アプリ固有のバンドルは、とにかく再利用可能ではないということです—相互に依存しています。 thisの場合の再利用は忘れてください。

  • どこに置くべきかわからない Behat 機能とステップ定義。この問題は前の問題に関連しています:あなたは繰り返す必要がありますバンドルごとに同じ頭の悪い動きをしてから、ハードコアな決定を下します。

    Behatの機能を書き始めたとき、一度に複数のバンドルに属していたため、多くの機能とステップ定義をどこに配置するかを決めることができませんでした。それらをCommonBundleに入れるのはさらに悪いようでした。なぜなら、それが私がそのようなものを探す最後のバンドルだからです。それで、私はそのためにFeatureBundleを作成することになりました。

単一のバンドルに切り替えることで、これらすべての問題が解決しました。

また、たとえばすべてのエンティティに対して個別のバンドルを持っている人もいます。私はこのアプローチも好きではなく、実際には エンティティやその他のSymfony2以外の特定のものをバンドルから除外することをお勧めします

この新しいアプローチはアプリ固有バンドルに適用されることに再度注意してください。公式ドキュメントやその他の場所には、他のユーザーと共有し、多数のプロジェクトで再利用することを目的としたバンドルを構築する方法に関する優れたアドバイスが満載です。 私はこのタイプのバンドルを作成します も同様です。しかし、Symfony2プロジェクトに数か月取り組んだ後、私が見つけたのは、再利用を目的としたバンドルとアプリ固有のバンドルには違いがあるということです。1つのアプローチですべてに対応できるわけではありません。

そしてもちろん、アプリ固有のバンドルに再利用可能なものが出現しているのを見つけたら、それを抽出し、別のリポジトリに配置して、ベンダーとしてインストールします。

また、バンドルを論理的に分割する方法として、サブネームスペースをはるかに積極的に使用していることに気付きました。そのためのバンドルの束を作成して、これらすべての問題を経験する代わりに。

古いアプローチ

厳格なルールや特効薬はありませんが、物事を行うための私のアプローチを共有します。おそらく、1つか2つの洞察が得られるでしょう。

まず第一に、私はFrontendBundleBackendBundleのような2つの包括的なバンドルを持っていません。代わりに、バンドルにはフロントエンドとバックエンドの両方のコントローラー、ビューなどがあります。したがって、コントローラーとビューを除いてUserBundleからすべてを削除すると、その構造は次のようになります。

UserBundle
├── Controller
│   ├── Admin
│   │   └── UserController.php
│   └── UserController.php
├── Resources
│   └── views
│       ├── Admin
│       │   └── User
│       │       ├── add.html.twig
│       │       ├── delete.html.twig
│       │       ├── edit.html.twig
│       │       ├── form.html.twig
│       │       └── index.html.twig
│       └── User
│           ├── edit.html.twig
│           ├── sign-in.html.twig
│           ├── sign-up.html.twig
│           └── view.html.twig
└── UserBundle.php

次に、いくつかのバンドルで共有されるものに使用するCommonBundleがあります。

CommonBundle
├── Resources
│   ├── public
│   │   ├── css
│   │   │   ├── admin.css
│   │   │   ├── common.css
│   │   │   └── public.css
│   │   └── img
│   │       ├── add.png
│   │       ├── delete.png
│   │       ├── edit.png
│   │       ├── error.png
│   │       ├── return.png
│   │       ├── success.png
│   │       └── upload.png
│   └── views
│       ├── Admin
│       │   └── layout.html.twig
│       └── layout.html.twig
└── CommonBundle.php

ぼくの app/Resources/views/base.html.twigは、SymfonyStandardディストリビューションに付属しているものとほぼ同じです。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>{{ block('title') | striptags | raw }}</title>
        {% block stylesheets %}{% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    </body>
</html>

両方とも CommonBundle/Resources/views/layout.htmlおよびCommonBundle/Resources/views/Admin/layout.html拡張app/Resources/views/base.html.twig。他のバンドルのテンプレートは、フロントエンド用かバックエンド用かに応じて、これら2つのレイアウトのいずれかを拡張します。基本的に、これは私が使用している方法です レベルの継承アプローチ

だから、私はあなたの日付表示をCommonBundleに入れます。その複雑さに応じて、それは単なるテンプレート、 マクロ または 小枝拡張 である可能性があります。

ページネーションは一般的な問題であるため、ホイールを再発明する代わりに、 既存バンドル のいずれかを使用することをお勧めします—もちろん、それらがニーズに合っている場合。

はい、コントローラーやビューなどのないバンドルがあってもまったく問題ありません。

80

関連するコードをより一般的なバンドルに入れるのではなく、DateDisplayerBundleとPaginatorBundleを作成することをお勧めします。これにはいくつかの理由があります。

  • 各バンドルの役割は非常に明確であり、コードがどこにあるかがわかります。
  • 異なるプロジェクト間で機能の一部(日付表示、ページネーター)を共有することは、個別のバンドルがある場合は、プルーニングが必要になる可能性がある1つの一般的なバンドルよりも簡単です。

バンドルにはコントローラーが必要であるという厳格なルールはありません。バンドルには、ビジネスロジック、テンプレート、コントローラー、および構成を任意に組み合わせることができますが、バンドルに格納できるものに制限はありません。

一方、機能がそれほど複雑でない場合は、バンドルに含まれる必要がまったくない場合があります。この場合、/vendorにライブラリを作成できます。 symfonyはこの方法で多くのライブラリを利用します(たとえば、MonologとDoctrine)を参照してください。)

2番目の質問については、レイアウトをapp\Resources\viewsに保持する理由は、すべてのレイアウトを追跡するのに便利な方法だからだと思います。多くのバンドルがあるプロジェクトがある場合、特定のレイアウトがどこにあるかを見失う可能性があります。しかし、それらすべてを一元化された場所に保管すると、どこを見ればよいかを常に正確に知ることができます。 Symfony2の多くのものと同様に、これは決まったルールではありません。レイアウトをバンドルに簡単に保存できますが、これは推奨される方法ではないと思います。

一般的なルートバンドルについての質問については、ほとんどの場合、1つのバンドルでさまざまな機能をシューホーニングすることは避けてください。バンドルを特定に保つことについての私の以前のポイントを参照してください。 Symfony2で開発を始めたとき、どのコードをどのバンドルに入れるべきかを判断するのに苦労しました。それは私がプログラミングについて考えることに慣れていた方法ではありません。しかし、最終的には、パズルの個々のピースがどのように適合するかがわかり始めます。これにより、バンドル構造の決定が容易になります。

4