Symfony2に基づいて独自のフレームワークを作成します。 (パート3)

目次









これまで、アプリケーションは1ページしか含まれていないため、非常にシンプルでした。

物事を少し複雑にするために、「さようなら」という別のページを追加します。

<?php // framework/bye.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response('Goodbye!'); $response->send();
      
      





ご覧のとおり、ほとんどのコードは最初のページとまったく同じです。

すべてのページに共通のコードを個別に強調してみましょう。

「共通コードの共有」は、最初の「実際の」フレームワークの素晴らしい計画のように思えます!



PHP内では、リファクタリングはインクルードファイルの作成で構成されます。

  <?php // framework/init.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response();
      
      





実際に見てみましょう:

  <?php // framework/index.php require_once __DIR__.'/init.php'; $input = $request->get('name', 'World'); $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); $response->send();
      
      





さようならページの場合:

  <?php // framework/bye.php require_once __DIR__.'/init.php'; $response->setContent('Goodbye!'); $response->send();
      
      





そのため、共通のコードを1か所にまとめました。 しかし、それは良いレベルの抽象化のようには見えませんか?

まず、すべてのページでsend()メソッドを呼び出しているため、ページは通常のテンプレートとは異なり、コードを「正しく」テストできません。



もう1つの深刻な問題は、新しいページを追加すると、新しいPHPスクリプトを作成する必要があることです。

その名前はURL(http://example.com/bye.php)で送信され、Webサーバーによって呼び出されます。

柔軟性を高めるために、目的のスクリプトへの呼び出しをコードに転送することをお勧めします。

これは、すべてのリクエストを単一のPHPスクリプト(フロントコントローラー)にリダイレクトすることで実現できます。







スクリプト自体は次のようになります。

  <?php // framework/front.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response(); $map = array( '/hello' => __DIR__.'/hello.php', '/bye' => __DIR__.'/bye.php', ); $path = $request->getPathInfo(); if (isset($map[$path])) { require $map[$path]; } else { $response->setStatusCode(404); $response->setContent('Not Found'); } $response->send();
      
      





そして、新しいhello.phpの例:

  <?php // framework/hello.php $input = $request->get('name', 'World'); $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8')));
      
      





front.phpスクリプトでは、 $ mapはURLのパスをスクリプトファイルへの対応するパスにリンクします。



ボーナスとして、クライアントが一致の配列で定義されていないパスを要求した場合、404エラーを返します。

今、あなた自身がサイトを制御します。



ページにアクセスするには、フロントコントローラーのfront.phpスクリプトを使用する必要があります





/ helloおよび/ byeはページパスです。



ヒント。

ApacheやnginxなどのほとんどのWebサーバーは書き換え可能です

ページのURLをリクエストして、フロントコントローラーのファイル( front.php )の名前をそれらから削除します。

ユーザーはexample.com/hello?name=Fabienと入力するだけでよくなります。





したがって、トリックはRequest :: getPathInfo()メソッドを使用することです。このメソッドは、「 Request 」からパスの一部を返します

すべてのサブディレクトリを含むフロントコントローラーのファイルの名前を削除します(必要な場合のみ-上記のヘルプを参照してください)。



Webサーバーを構成する必要さえありません。 ただ

呼び出しを置き換えます$ request = Request :: createFromGlobals(); $ request = Request :: create( '/ hello?name = Fabien');など

ここで、引数はシミュレートするクエリです。



ページへのすべてのリクエストが1つのスクリプト(front.php)を通過するようになったため、

ルートWebディレクトリの外部にある他のすべてのPHPファイルを転送することにより、セキュリティに貢献できます。

     example.com
     +-composer.json
     src src
     ¦ +-autoload.php
     ¦ L--ページ
     ¦ +-hello.php
     ¦ L-- bye.php
     +-ベンダー
     L--ウェブ
         L-- front.php


次に、 web /ディレクトリがそのルートになるようにWebサーバーを構成します。

クライアントは他のすべてのファイルを使用できなくなります。



このディレクトリ構造が機能するには、一部のプロジェクトファイルのパスを変更する必要があります。

これらの変更は読者にとって宿題になります。



すべてのページで繰り返される最後のことは、 setContent()の呼び出しです。

コンテンツを出力するだけで、すべてのページを「テンプレート」に変えることができます

フロントコントローラースクリプトから直接setContent()を呼び出します:

  <?php // example.com/web/front.php // ... $path = $request->getPathInfo(); if (isset($map[$path])) { ob_start(); include $map[$path]; $response->setContent(ob_get_clean()); } else { $response->setStatusCode(404); $response->setContent('Not Found'); } // ...
      
      





これで、 hello.phpスクリプトをテンプレートに再作成できます。

  <!-- example.com/src/pages/hello.php --> <?php $name = $request->get('name', 'World') ?> Hello <?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?>
      
      





今日、フレームワークは次のようになります。

  <?php // example.com/web/front.php require_once __DIR__.'/../src/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response(); $map = array( '/hello' => __DIR__.'/../src/pages/hello.php', '/bye' => __DIR__.'/../src/pages/bye.php', ); $path = $request->getPathInfo(); if (isset($map[$path])) { ob_start(); include $map[$path]; $response->setContent(ob_get_clean()); } else { $response->setStatusCode(404); $response->setContent('Not Found'); } $response->send();
      
      





ページの追加は、2つのステップで行われます:要素を一致の配列に追加し、作成します

src / pages /にある PHPテンプレート。 テンプレートから、「 リクエスト 」データは$リクエスト変数を介して利用可能です

また、 $応答変数を使用して応答ヘッダー( " Response ")を操作できます。



すぐに停止する場合は、構成ファイルに一致するURLの配列を入力することをお勧めします。




All Articles