以前はエントリ ファイル内で Route::run() を直接呼び出していましたが、これには問題がありますか?
答えはイエスです!
ルーティングの前後に追加の処理が必要になる場合があります。これまでのようにエントリ ファイル内で直接 Route::run() を呼び出す場合、これらの処理プロセスはエントリ ファイル内にしか記述できません。エントリーファイルはそのようなことをするべきではありませんが、この問題をどのように解決すればよいでしょうか?
マスター コントロールに相当するフロントエンド コントローラーの概念を導入します。すべての外部リクエストはその制御範囲内にあるため、これらの追加の処理をこのコントローラーに配置できますか? !
それでは、エントリ ファイルを変更しましょう:
01 |
02 | defined('APP_PATH') define('APP_PATH',dirname(__FILE__) . '/..'); |
04 | defined('MODULES_PATH') define('MODULES_PATH',APP_PATH . '/UserApps/Modules'); |
02
05 | defined('CONFIGS_PATH') define('CONFIGS_PATH',APP_PATH . '/UserApps/Configs'); |
06 | include FRAMEWORK_PATH . '/function.php'; |
07 | C(Config::factory(Config::PHP)); //写入配置信息 |
08 | include FRAMEWORK_PATH . '/FrontController.php'; |
09 | $frontController = FrontController::getInstance(); |
10 | $frontController->run(); |
このコードは実際にはあまり変更されていないため、次のように変更されます:
1 | include FRAMEWORK_PATH . '/FrontController.php'; |
2 | $frontController = FrontController::getInstance(); |
FRAMEWORK_PATH を含めます。 '/FrontController.php';
3 | $frontController->run(); |
2
このコードには、最初にフロントエンド コントローラーのファイルが含まれ、次にフロントエンド コントローラーをインスタンス化して、フロントエンド コントローラー クラスの run メソッドを呼び出します。
$frontController = new FrontController() を使用しないのはなぜでしょうか?
次のコードをダウンロードして実行すると、エラーが報告されることがわかります。なぜですか?
ここで、別の概念、シングルトン パターンを紹介する必要があります。
シングルトン モードとは、データベース接続など、プログラム全体の実行中にインスタンスが 1 つだけ存在することを意味します。たとえ多数のクラスがあったとしても、これらのクラスはすべてデータベース接続を共有する可能性があるため、データベース接続は 1 つのみになります。シングルトン。
01 |
なぜシングルトンを使用するのですか?
02 | class Test { |
03 | private static $_instance = null; |
考えてみてください。フロントエンド コントローラーはプログラム全体の動作を制御するので、実際には複数のコピーを持つべきではありませんよね?
04 | private function __construct() {} |
05 | private function __clone() {} |
06 | public static function getInstance() { |
07 | if(null === self::$_instance) { |
08 | self::$_instance = new Test(); |
09 | echo '1'; |
10 | } |
11 | return self::$_instance; |
12 | } |
13 | } |
14 |
15 | $test = Test::getInstance(); |
16 | $test2 = Test::getInstance(); |
このコードを実行すると、1 だけが出力されることがわかります。これは、インスタンス化が 1 回だけ実行されることを示します。
ここまで述べましたが、誰もが理解できるはずなので、フロントエンド コントローラーのコードを投稿しましょう:
<テーブル>
01 |
02 | class FrontController { |
04 | private function __construct() {} |
02
05 | private function __clone() {} |
06 | public static function getInstance() { |
07 | if(!(self::$_instance instanceof self)) { |
08 | self::$_instance = new FrontController(); |
09 | } |
10 | return self::$_instance; |
<テーブル>
11 | } |
12 | public function run() { |
13 | Route::run(); |
14 | } |
15 | } |
もちろん、フロントエンド コントローラーでの決定には、instanceof を使用しました。実際には、null === self::$_instance を直接使用して決定することもできます。
このコードは非常に単純で、実際には Route::run() を FrontController に転送するだけで、他には何も変更しません。
エントリー ファイルの内容がまだ多すぎることに気づいたかもしれませんが、なぜ FrontController に移行できるエントリー ファイルの内容はどうなるのでしょうか?実際、ユーザーが APP_PATH を定義する限り、他の定数はフレームワークによってデフォルトに設定され、その後、このコンテンツ フレームワークがそれ自体で完全に処理できるようになります。エントリファイルは次のようになります:
<テーブル>
1 |
2 | defined('APP_PATH') define('APP_PATH',dirname(__FILE__) . '/..'); |
4 | include FRAMEWORK_PATH . '/FrontController.php'; |
2
5 | $frontController = FrontController::getInstance(); |
6 | $frontController->run(); |
フレームワーク ファイルを参照するため、ここでは FRAMEWORK_PATH を残しておきます。実際には、FRMAEWORK_PATH は定義されていませんが、代わりに '/Library/Test/FrontController.php' を含めます。
同様に、FrontController のコードも変更されました:
01 |
02 | defined('APP_PATH') exit('未定义APP_PATH'); |
03 | defined('FRAMEWORK_PATH') define('FRAMEWORK_PATH',APP_PATH . '/Library/Test'); |
04 | defined('MODULES_PATH') define('MODULES_PATH',APP_PATH . '/UserApps/Modules'); |
02
05 | defined('CONFIGS_PATH') define('CONFIGS_PATH',APP_PATH . '/UserApps/Configs'); |
06 | include FRAMEWORK_PATH . '/function.php'; |
07 | class FrontController { |
08 | private static $_instance = null; |
09 | private function __construct() { |
10 | C(Config::factory(Config::PHP)); //写入配置信息 |
11 | } |
12 | private function __clone() {} |
13 | public static function getInstance() { |
14 | if(!(self::$_instance instanceof self)) { |
15 | self::$_instance = new FrontController(); |
16 | } |
17 | return self::$_instance; |
18 | } |
19 | public function run() { |
20 | Route::run(); |
21 | } |
22 | } |
まず、このファイルは APP_PATH が定義されているかどうかを決定します。この定数は非常に重要であるため、他のパスはこれに依存するため、ユーザーが指定しない場合はプログラムを停止する必要があります。他の定数が定義されていない場合は、それらを定義するのは非常に簡単です。
構成ファイルはコンストラクターに書き込まれます。これは、getInstance が何回呼び出されても、コンストラクターは 1 回だけ呼び出され、構成ファイルを書き込む必要があるのは 1 回だけであるためです。