セクションごとのSymfony2アプリケーション

しかし、名人の魔術師と彼の美しいヘルパーの口を観察することは、多くは完全に異なる何かに焦点を当てています:彼はそれをどのように行うのですか? すべてが内部にどのように配置されていますか?





私たちのためにすべてを行うフレームワークで作業するときにも同じことが起こりますが、私はそれらがどのようにそれを行うかを知り、必要に応じて動作を変更できるようにしたいと思います。 残念ながら、ドキュメントは、それがどれほど優れていても( そしてSymfony 2はすでに優れています )、この「魔法」をすべて使用する方法を示していますが、本質全体は明らかにしていません。


この記事は、アプリケーションの初期化方法と「Symfony2カーネル」とは何かを理解しようとする試みです。



大きなテキストが気に入らない人のために、主要なコンポーネントの簡単な概要と実行されるアクションの簡単な説明がすぐに添付されます。



簡単なプロセスの説明







クリック可能



1.すべての要求は、フロントコントローラー(FrontController)によって受け入れられます。

2. autoloadクラスを構成します(autoload)。

3.環境に応じてカーネルが作成されます。

4.カーネルが起動します。

1.バンドルのリストが初期化されます。

2.依存性注入コンテナが作成されます。

1.メインパラメータを使用してコンテナが作成されます。

2.各バンドルはビルドコンテナを変更します。

3.アプリケーション構成がロードされています。

4.コンテナがコンパイルされます。

1.拡張機能が処理されています。

2.パラメーターへの参照は実際の値に置き換えられます。

3.コンテナは読み取り専用モード(凍結)になります。

3.バンドルが起動します。





フロントコントローラー



フロントコントローラーは通常のスクリプトです。 例は、 標準のSymfony2ディストリビューションからのスクリプトです。



これらすべてのフロントコントローラーは、同じ原理に基づいて構築されています。





カーネル



カーネルはKernelInterfaceインターフェースを実装するクラスであり、そのタスクは環境を初期化することです。 コアは、依存性注入コンテナー(理論は、たとえばFowlerから収集できます)とバンドルシステムの2つの主要なコンポーネントに基づいています。 このバンドルは、Symfony 1.xのプラグインに類似しています。 バンドルの詳細については、公式ドキュメントをご覧ください。 もちろん、カーネルインターフェース自体に加えて、標準の抽象的なカーネル実装もあります。これについては、主に後で説明します。

初期化コードは次のようになります。

// init bundles $this->initializeBundles(); // init container $this->initializeContainer(); foreach ($this->getBundles() as $bundle) { $bundle->setContainer($this->container); $bundle->boot(); }
      
      







コンテナの初期化



この段階の結果、完全に使用可能なコンテナが作成され、読み取り専用モードに切り替わります。 このプロセスは4つのサブステップに分かれています。

*コンパイラの理論では、「パス」という概念があり、ほぼ同じことを暗示しているため、CompilerPassはそのように翻訳しました。



コンテナバンドルの変更



上記のように、コンパイルプロセス中に、各バンドルには共通のコンテナを変更する機会があります。 変更する主な方法は、 コンパイラパスを追加することです



コンパイラーパス



コンパイル段階で、コンテナは一連のパスを実行して、コンテンツを最終状態に戻します。 パスは、 CompilerPassInterfaceインターフェースの実装であり、6種類(実行順)になります: merge、beforeOptimization、最適化、beforeRemoving、remove、afterRemoving-デフォルトでは、コンパイラー構成にはすでにパスワードのセットが含まれています。



バンドルでは、CompilerPassがコンテナ内のタグの処理に最もよく使用されます。 標準のTwigBundleの例:

  $definition = $container->getDefinition('twig'); $calls = $definition->getMethodCalls(); $definition->setMethodCalls(array()); foreach ($container->findTaggedServiceIds('twig.extension') as $id => $attributes) { $definition->addMethodCall('addExtension', array(new Reference($id))); } $definition->setMethodCalls(array_merge($definition->getMethodCalls(), $calls));
      
      







コンテナ拡張



コンテナはシステムの中心的な要素であり、実際、アプリケーションのすべての機能がそこに集中しているため、機能を追加するには、必要なサービスとパラメータをコンテナに入れる必要があります。 このような変更の便宜上、 コンテナ拡張機能があります(上記の特別な「マージ」パスで処理されます)。

ExtensionsはExtensionInterfaceインターフェイスの実装であり、抽象Extensionクラスはルーチンアクションを削減し、便利なメソッドを追加します。 通常、拡張機能は次のように機能します。



拡張設定の例( app / config / config.yml ):

 # Twig Configuration twig: debug: %kernel.debug% strict_variables: %kernel.debug%
      
      





この構成では、 twigExtensionInterface :: getAlias() )という名前の拡張機能( ExtensionInterface :: load() )に、対応するセクションで定義されたパラメーターを渡す必要があることを示しています。



バンドル拡張機能の接続は非常に簡単です。対応する名前( DependencyInjection \ BundleNameExtension )でクラスを作成するだけで、 拡張機能:: build()メソッドコードは拡張機能自体をロードします(主なことは親メソッドと継承者を呼び出すことを忘れないことです)。



バンドルを起動



そして最後の段階はバンドルの発売です。 実際、ほとんどのバンドルはこの段階では何​​もしません。コンテナでは実行できないアクションを実行するように設計されています。 たとえば、この段階で、メインのSymfony2バンドル(FrameworkBundle)は、この記事で複数回言及されたクラスキャッシュをロードします。



おわりに



これにより、Symfony2アプリケーションの初期化プロセスは完了したと見なすことができます。すべての準備手順が完了し、コンテナーに必要な機能がすべて含まれています。 コンテナから必要なサービスを取得し、そのメソッドを呼び出してアプリケーションを実行します。

読者はおそらく、かなり複雑でリソースを大量に消費する初期化プロセスを心配するでしょうが、それほど悪くはありません。 Symfony2は柔軟性とともに速度を忘れないため、すぐに多くの最適化ソリューションを提供します。 そのため、たとえば、すべての設定を含むクラスを作成することでコンテナーを作成するプロセス全体がキャッシュされ、さまざまなパラメーターの多くの構成、コンテナーコンパイラなどを読み込むのではなく、次回それを呼び出す(デバッグモードの場合) 生成されたクラスがロードされるだけで、すぐに使用可能なコンテナオブジェクトが作成されます。



著者から



これで、Symfony2の荒野への最初の飛び込みは終わりです。 Symfony2に関するこの種の記事が読者の興味を引くなら、フレームワークの内部、個々のコンポーネント、人気のあるバンドルを分析して、これらすべてを一連の記事に変えることができます。 さらに、Habréに長期滞在しているにもかかわらず、これは私の最初の記事です。 私は書くよりも話すのが好きですが、自分の考えを表現するこの方法で自分自身を教育しようとしています。 したがって、資料のプレゼンテーションに関する直接的なフィードバックに非常に感謝します。 強調する方が良いもの、少ないもの。 おそらくより多くの図とコード例が必要です。 サブジェクト領域に精通している人にもっと頼るか、誰にでもはっきりわかるように説明しようとするなど。



All Articles