Skip to content

WIP: [best practice] controllers.rst翻訳中 #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions best_practices/controllers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
コントローラー
===========
Symfonyは薄いコントローラとファットなモデルという哲学に従います。 つまり、コントローラは、
アプリケーションの様々な部分をとりまとめるグルーコードだけからなる薄いレイヤーにするべきです。

経験則として、正確な基準はありませんが、コントローラに定義する変数は5個以下、
アクションの数が10個以下で、各アクション内の行数は20行以内という「5-10-20ルール」に従う事は
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここは文章が長くなるので一度切るとよいのではないかと思いました。実際英文も切れていますし。

As a rule of thumb, you should follow the 5-10-20 rule, where controllers should only define 5 variables or less, contain 10 actions or less and include 20 lines of code or less in each action.

`経験則ですが、コントローラに定義する変数は5個、
アクションの数は10個、各アクションの行数は20行以下にするという「5-10-20ルール」に従うのがよいでしょう。

This isn't an exact science, but it should help you realize when code should be refactored out of the controller and into a service.

正確な基準というわけではありませんが、ルールに従うことでコントローラーからサービスにリファクタリングすべきタイミング(時)が分かるでしょう。

but it should help you realise~ → あたたが気づくのを助ける → 気がつける (分かる)
という感じかと。

@hidenorigoto ここの英語の解釈これで合ってますでしょうか?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

概ね間違っていないと思いますが、前の文からの流れも踏まえてブラッシュアップ(意訳)するとしたら

「この数字に科学的な根拠はありませんが、コントローラーからサービスへリファクタリングすべきタイミングを見極める基準としては役立ちます。」

コードをコントローラからサービスにリファクタリングする際に役に立ちます。

.. best-practice::

開発者がコントローラを作る場合``FrameworkBundle``のコントローラを継承し、
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここは主語なしで「コントローラーを作る場合〜」とすると良いと思います。

可能な限り、ルーティング、キャッシュとセキュリティをアノテーションで設定してください。


コントローラとフレームワークを連携させることで、フレームワークの機能すべてを
活用する事を可能にし、あなたの生産性を向上させます。

そして、コントローラーは薄く、数行のグルーコードであるべきで、
フレームワークからそれらを切り離すそうとすると、時間かかるので長期的に見ると利益になりません。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spending hours trying to decouple them from your
framework doesn't benefit you in the long run.

frameworkまでが主語ですね。ですので「フレームワークからそれらを切り離すことに時間を割くことは、長期的に見ると利益になりません。」とするとよいかと!

大量の時間を費やすだけで、何の価値もありません。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The amount of time wasted isn't worth the benefit.

The amount of ~ の意味は「~の量は」なので、これ自体に「多量の」というニュアンスは含まれないと思います。
またここでは、wastedは動詞ではなくThe amount of time wastedまでが主語ですね。wastedThe amount of timeを修飾してます。

翻訳してみると「消費された時間(の量)は何の価値もありません」でしょうか。

wasted自体に浪費するというニュアンスがあるみたいで「浪費された時間は何の価値もありません」と訳すと「浪費=価値がない」と日本語では当たり前すぎることを言ってしまうので、ここでは「消費された時間」としてみました。


加えて、 ルーティング、キャッシュ、セキュリティに対してアノテーションを使用すると簡単に設定する事ができます。
すべての設定は必要な場所に一つのフォーマットにすれば、YAML, XML, PHPなどの複数ファイルを見る必要がなくなります。

全体的にビジネスロジックをフレームワークから切り離すという手段は積極的に行うと
同時に、最大限に活用にするためにルーティングとコントローラは結合するべきです。

ルーティング設定
---------------------

コントローラで定義されたアノテーションを利用するにはrouting.ymlに以下の設定を追加します。

.. code-block:: yaml

# app/config/routing.yml
app:
resource: "@AppBundle/Controller/"
type: annotation

``src/AppBundle/Controller/`` ディレクトリとそのサブディレクトリからコントローラの
アノテーションをロードします。
もしアプリケーションに多くのコントローラがある場合、それらをサブディレクトリへ移動する事が可能です。

.. code-block:: text

<your-project>/
├─ ...
└─ src/
└─ AppBundle/
├─ ...
└─ Controller/
├─ DefaultController.php
├─ ...
├─ Api/
│ ├─ ...
│ └─ ...
└─ Backend/
├─ ...
└─ ...

テンプレート設定
----------------------

.. best-practice::

テンプレートの設定は ``@Template()`` アノテーションを使用しないでください。

``@Template``は便利ですがいくつかの魔法を伴うので、お勧めする事はできません。

ほとんどの場合、``@Template``はパラメータの設定をせず使用されます。そして設定すると、どの
テンプレートを表示するかをわかりづらくします。それはまた、必ずコントローラはレスポンスオブジェクトを
返すべきだと言う事を初心者にわかりにくくしてしまいます。(あなたがビューレイヤーを利用している場合以外)

最後に、@Templateアノテーションはkernel.viewイベントのイベントディスパッチのフックとして
TemplateListenerクラスで利用されます。そのリスナーのパフォーマンスへの影響を紹介します。
ブログのサンプルアプリケーションのホームページをレンダリングする場合、$this->render()メソッドを
使った場合5ミリ秒かかり、@Templateアノテーションを使った場合26ミリ秒かかりました。

How the Controller Looks
------------------------

Considering all this, here is an example of how the controller should look
for the homepage of our app:

.. code-block:: php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$posts = $em->getRepository('App:Post')->findLatest();

return $this->render('default/index.html.twig', array(
'posts' => $posts
));
}
}

.. _best-practices-paramconverter:

ParamConverterを使う
------------------------

もしDoctrineを使っている場合は必要に応じて`ParamConverter`_ を使い、自動的にエンティティを取得し、
コントローラの引数として渡す必要があります。

.. best-practice::

シンプルかつ簡単な場合は、自動的にDoctrineのエンティティを取得出来るParamConverterを使用
してください。

例:

.. code-block:: php

/**
* @Route("/{id}", name="admin_post_show")
*/
public function showAction(Post $post)
{
$deleteForm = $this->createDeleteForm($post);

return $this->render('admin/post/show.html.twig', array(
'post' => $post,
'delete_form' => $deleteForm->createView(),
));
}

通常は ``showAction`` では ``$id`` という変数を引数として使うと思います。
代わりに ``$post`` 引数と ``Post`` クラス(Doctrineのエンティティ)をタイプヒンティングする
ことによって、そのオブジェクトを自動的にParamConverterが``{id}`` の値と一致する
``$id`` プロパティのものを取得します。``Post`` が見つからなかった場合は404ページが表示されます。

高度な事
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This works without any configuration
This works without any configuration because the wildcard name ``{id}`` matches
the name of the property on the entity. If this isn't true, or if you have
even more complex logic, the easiest thing to do is just query for the entity
manually. In our application, we have this situation in ``CommentController``:

.. code-block:: php

/**
* @Route("/comment/{postSlug}/new", name = "comment_new")
*/
public function newAction(Request $request, $postSlug)
{
$post = $this->getDoctrine()
->getRepository('AppBundle:Post')
->findOneBy(array('slug' => $postSlug));

if (!$post) {
throw $this->createNotFoundException();
}

// ...
}

You can also use the ``@ParamConverter`` configuration, which is infinitely
flexible:

.. code-block:: php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

/**
* @Route("/comment/{postSlug}/new", name = "comment_new")
* @ParamConverter("post", options={"mapping": {"postSlug": "slug"}})
*/
public function newAction(Request $request, Post $post)
{
// ...
}

The point is this: the ParamConverter shortcut is great for simple situations.
But you shouldn't forget that querying for entities directly is still very
easy.

Pre and Post Hooks
------------------

If you need to execute some code before or after the execution of your controllers,
you can use the EventDispatcher component to `set up before/after filters`_.

.. _`ParamConverter`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
.. _`set up before/after filters`: http://symfony.com/doc/current/cookbook/event_dispatcher/before_after_filters.html