[解決済み】Symfony 2.xでは、本当にすべてをバンドルにすべきなのか?
質問
のような質問を意識しています。 これ ここでは、バンドルという Symfony 2 の一般的な概念について議論されることが多いようです。
つまり、特定のアプリケーション、たとえば twitter のようなアプリケーションでは、本当にすべてを一般的なバンドルの中に入れるべきなのか、ということです。 公式ドキュメント と言うのでしょうか?
この質問をした理由は、一般的にアプリケーションを開発するとき、フルスタックのグルーフレームワークにコードを高度に結合させたくないからです。
もし私がSymfony 2ベースのアプリケーションを開発し、ある時点でSymfony 2は本当に最良の選択ではないと判断した場合、次のようになります。 開発を継続する それは問題ないのでしょうか?
では、一般的な質問ですが、なぜすべてがバンドルであることが良いことなのでしょうか?
EDIT#1
この質問をしてから1年近く経ったので、私は 記事 このトピックに関する私の知識を共有するために。
どのように解決するのですか?
このトピックについて、より詳細で最新のブログ記事を書きました。 http://elnur.pro/symfony-without-bundles/
いいえ、すべてがバンドルである必要はありません。このような構造でもいいのです。
-
src/Vendor/Model
- モデル用です。 -
src/Vendor/Controller
- コントローラ用です。 -
src/Vendor/Service
- サービス用です。 -
src/Vendor/Bundle
- のように、バンドル用src/Vendor/Bundle/AppBundle
, - など
このようにすると
AppBundle
は、本当にSymfony2固有のものだけです。後で別のフレームワークに変更することを決めたら、その際に
Bundle
名前空間を選択したフレームワークのものに置き換えます。
なお、ここで提案しているのは アプリ の特定のコードです。再利用可能なバンドルには、やはり ベストプラクティス .
バンドルからエンティティを排除する
エンティティを
src/Vendor/Model
をどのバンドルにも属さないようにした。
doctrine
セクションを
config.yml
から
doctrine:
# ...
orm:
# ...
auto_mapping: true
になります。
doctrine:
# ...
orm:
# ...
mappings:
model:
type: annotation
dir: %kernel.root_dir%/../src/Vendor/Model
prefix: Vendor\Model
alias: Model
is_bundle: false
Doctrine リポジトリからアクセスするためのエンティティの名前は
Model
この場合、例えば
Model:User
.
サブネームスペースを使用して、例えば、関連するエンティティをグループ化することができます。
src/Vendor/User/Group.php
. この場合、エンティティの名前は
Model:User\Group
.
バンドルからコントローラを排除する
まず
JMSDiExtraBundle
をスキャンするために
src
フォルダに追加することで、サービスのための
config.yml
:
jms_di_extra:
locations:
directories: %kernel.root_dir%/../src
では、あなたは
コントローラをサービスとして定義する
の下に配置し
Controller
という名前空間があります。
<?php
namespace Vendor\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Elnur\AbstractControllerBundle\AbstractController;
use Vendor\Service\UserService;
use Vendor\Model\User;
/**
* @Service("user_controller", parent="elnur.controller.abstract")
* @Route(service="user_controller")
*/
class UserController extends AbstractController
{
/**
* @var UserService
*/
private $userService;
/**
* @InjectParams
*
* @param UserService $userService
*/
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
/**
* @Route("/user/add", name="user.add")
* @Template
* @Secure("ROLE_ADMIN")
*
* @param Request $request
* @return array
*/
public function addAction(Request $request)
{
$user = new User;
$form = $this->formFactory->create('user', $user);
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$this->userService->save($user);
$request->getSession()->getFlashBag()->add('success', 'user.add.success');
return new RedirectResponse($this->router->generate('user.list'));
}
}
return ['form' => $form->createView()];
}
/**
* @Route("/user/profile", name="user.profile")
* @Template
* @Secure("ROLE_USER")
*
* @param Request $request
* @return array
*/
public function profileAction(Request $request)
{
$user = $this->getCurrentUser();
$form = $this->formFactory->create('user_profile', $user);
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$this->userService->save($user);
$request->getSession()->getFlashBag()->add('success', 'user.profile.edit.success');
return new RedirectResponse($this->router->generate('user.view', [
'username' => $user->getUsername()
]));
}
}
return [
'form' => $form->createView(),
'user' => $user
];
}
}
なお、私が使っている ElnurAbstractControllerBundle(エルナー・アブストラクト・コントローラー・バンドル を使用することで、コントローラをサービスとして定義することを簡略化できます。
最後に残っているのは、バンドルのないテンプレートを探すように symfony に指示することです。私はテンプレート推測サービスをオーバーライドすることでこれを行いますが、アプローチが symfony 2.0 と 2.1 で異なるので、両方のバージョンを提供します。
Symfony 2.1+ のテンプレート推測ツールをオーバーライドする
を作成しました。 バンドル がそれをやってくれる。
symfony 2.0 のテンプレートリスナーをオーバーライドする
まず、クラスを定義します。
<?php
namespace Vendor\Listener;
use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener as FrameworkExtraTemplateListener;
use JMS\DiExtraBundle\Annotation\Service;
class TemplateListener extends FrameworkExtraTemplateListener
{
/**
* @param array $controller
* @param Request $request
* @param string $engine
* @throws InvalidArgumentException
* @return TemplateReference
*/
public function guessTemplateName($controller, Request $request, $engine = 'twig')
{
if (!preg_match('/Controller\\\(.+)Controller$/', get_class($controller[0]), $matchController)) {
throw new InvalidArgumentException(sprintf('The "%s" class does not look like a controller class (it must be in a "Controller" sub-namespace and the class name must end with "Controller")', get_class($controller[0])));
}
if (!preg_match('/^(.+)Action$/', $controller[1], $matchAction)) {
throw new InvalidArgumentException(sprintf('The "%s" method does not look like an action method (it does not end with Action)', $controller[1]));
}
$bundle = $this->getBundleForClass(get_class($controller[0]));
return new TemplateReference(
$bundle ? $bundle->getName() : null,
$matchController[1],
$matchAction[1],
$request->getRequestFormat(),
$engine
);
}
/**
* @param string $class
* @return Bundle
*/
protected function getBundleForClass($class)
{
try {
return parent::getBundleForClass($class);
} catch (InvalidArgumentException $e) {
return null;
}
}
}
そして、Symfonyにこれを使用するように次のように追加します。
config.yml
:
parameters:
jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener
バンドルなしでテンプレートを使用する
これで、バンドルの外にあるテンプレートを使用することができます。テンプレートは
app/Resources/views
フォルダーに格納されます。例えば、上の例のコントローラにある2つのアクションのテンプレートは、以下の場所にあります。
-
app/Resources/views/User/add.html.twig
-
app/Resources/views/User/profile.html.twig
テンプレートを参照する場合は、bundleの部分を省略すればよい。
{% include ':Controller:view.html.twig' %}
関連
-
[解決済み] ログアウトする。GETかPOSTか?
-
[解決済み] Composerで単一のライブラリを更新する方法は?
-
[解決済み】拡張子.yamlと.ymlの違いは何ですか?[重複あり]
-
[解決済み】Symfony 2.xでは、本当にすべてをバンドルにすべきなのか?
-
[解決済み】Twigテンプレートで現在のURLを取得する?
-
[解決済み] Symfony2 の config.yml から設定を読み込むには?
-
[解決済み] Symfony2のTwigテンプレートで設定パラメータを取得する方法
-
[解決済み] symfony2のコントローラでparameters.ymlから読み込むにはどうしたらいいですか?
-
[解決済み] Twigのパスに複数のパラメータを追加する
-
[解決済み] Doctrine 2 は manyToOne リレーションで nullable=false を使うことはできないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】拡張子.yamlと.ymlの違いは何ですか?[重複あり]
-
[解決済み】Doctrine QueryBuilder で行数を数える。
-
[解決済み】Symfony 2.xでは、本当にすべてをバンドルにすべきなのか?
-
[解決済み】Twigテンプレートで現在のURLを取得する?
-
[解決済み] Symfony2 の config.yml から設定を読み込むには?
-
[解決済み] Symfony2のTwigテンプレートで設定パラメータを取得する方法
-
[解決済み] symfony2のコントローラでparameters.ymlから読み込むにはどうしたらいいですか?
-
[解決済み] symfony2 : リクエストをフォームにバインドした後にフォームのバリデーションエラーを取得する方法
-
[解決済み] Twigのパスに複数のパラメータを追加する
-
[解決済み] Doctrine 2 は manyToOne リレーションで nullable=false を使うことはできないのですか?