実際にはフレームワークの単なる棚です。今日から、これらをコントローラー、モデル、ビューから分離していきます。私が紹介します。
PS: ルーティングなど、これまでの内容の多くについては詳しく説明しませんでしたが、実際のフレームワークのルーティングは GET を通じて指定されるものではなく、通常のものであり、複数のサーバーと互換性がある必要があります。複数の方法。
すべてのリクエストはコントローラーを経由する必要があることがわかっているので、最初にコントローラーについて話しましょう。
以前にコントローラーの概念について説明しましたが、このコントローラーは機能的には単なるコントローラーであり、フレームワークは実際に一般的に使用されるいくつかの機能を実装できるわけではないため、まだ弱すぎます。関数を作成し、ユーザー定義のコントローラーがそれを継承するため、ユーザーが記述するコードが少なくなります。
以前のコントローラーは次のとおりです:
1 |
2 | class IndexController { |
4 | echo 'Hello world'; |
2
5 | } |
6 | } |
<テーブル>
パブリック関数 Index() {
1 |
2 | class IndexController extends Controller { |
3 | public function index() { |
4 | echo 'Hello world'; |
5 | } |
6 | } |
これを行う利点は何ですか? Controller が Base を継承しているため、IndexController も Base の機能を備えているため、ユーザーは多くのキャプチャ コードを記述する必要がありません。
もちろん、これにも欠点があり、IndexController をテストするときはさらに面倒です。
今日はまず、コントローラーの 2 つの基本機能、ジャンプと前進について説明します。
1 つ目はジャンプです。たとえば、ユーザーがログインするときに、処理が完了した後にログイン ボタンをクリックして、バックグラウンド処理ページに移動する必要があります。ジャンプを実装するにはどうすればよいですか?
いくつかの方法があります:
最初のもの: <script>location.href = "XXXX";</script>JS でジャンプを実現します。
2 番目のタイプ: header("Location:url"); 具体的な使用法については、PHP マニュアルを参照してください。
3 番目の方法: HTML メタで更新を設定します。ヘッダーを呼び出した時点で、前のページに出力があるとジャンプが無効になるため、metaのリフレッシュと併用する必要があります。 もちろん、JSを直接使用して実装することもできます。 、しかし、私はこの方法があまり好きではありません。なぜなら、以前にこの方法を使用してジャンプを実装したときに問題があったからです。
ジャンプ関数の名前を _redirect として定義します。なぜその前に _ を追加するのでしょうか? これは私の習慣でもあり、関数がパブリックでない限り、_ を使用します。接頭辞。なぜこの関数を public に設定しないのかと疑問に思われるかもしれません。ユーザーが作成したコントローラーはそれを継承するだけで、直接呼び出すことはないため、私はそれを protected に設定しました。
保護された関数 _redirect(Array $arr) {
1 | protected function _redirect(Array $arr) { |
2 |
2
3 |
4 | } |
当面は、ジャンプ パラメータが配列を介して渡されると仮定すると、渡されたパラメータがそうでない場合は、型ヒント (Array $arr) を使用してそれを行うことができます。配列の場合、エラーが直接報告されます。
これを使用する方法は次のようになります:
1 | $this->_redirect(array( |
2 | 'action' => 'test', |
$this->_redirect(array(
3 | 'controller' => 'Test', |
4 | 'param1' => '1' |
2
5 | )); |
'コントローラー' => 'テスト'、
テーブル>
3
01
protected function _redirect(Array $arr) {
02 | $controller= empty($_GET['c']) ? C('defaultController') : trim($_GET['c']); //设置了默认的控制器 |
03 | $action= empty($_GET['a']) ? C('defaultAction') : trim($_GET['a']); //设置了默认的Action |
'param1' => '1'
04 | array_key_exists('controller',$arr) $arr['controller'] = $controller; |
05 | array_key_exists('action',$arr) $arr['action'] = $action; |
06 | $str = '/?'; |
07 | foreach($arr as $key => $val) { |
08 | if(!is_int($key)) { |
09 | $str .= ($key . '=' . $val . '&'); |
10 | } |
11 | } |
12 | $str = substr($str,0,strlen($str) - 1); |
13 | Response::redirect($str); |
14 | } |
これは先ほど手書きしたジャンプコードです。実際には渡された配列を連結して文字列を形成します。Route.php がまだ処理されていないため、さらに処理します。 localhost/demo2/index.php?controller=a のような URL の場合、ジャンプ時にエラーが発生します。現在、localhost/index.php?controller=a のような URL と、$controller および $action の取得のみがサポートされています。これらは後で実際にルーティングを実装するときに説明する必要がありますが、私自身はこのようなコードは気持ち悪いと感じています。
この関数が URL に結合されると、Response のリダイレクト メソッドが直接呼び出されることに気づいたかもしれません。これはなぜでしょうか。
最初に: 実際のアプリケーションでは、コントローラー内で $this->_redirect を直接呼び出すことがニーズを満たすことができない可能性があります。現時点では、jump To などの Response::redirect を直接呼び出す必要があります。 Baidu のホームページにアクセスすると、Response::redirect("http://www.baidu.com");
のみを呼び出すことができます。2 番目: 論理的には、ジャンプはサーバーからクライアントへの応答であるため、Response に記述する必要があります。詳細については、Java を参照してください。
次に、Response.php のような新しいファイルを作成する必要があります:
01 |
02 | class Response extends Base { |
04 | if(is_string($url)) { |
02
05 | if(!headers_sent()) { |
06 | header("Location:" . $url); |
07 | exit(); |
08 | } else { |
09 | $str = ''; |
10 | exit($str); |
11 | } |
12 | } else { |
13 | //错误处理 |
14 | } |
15 | } |
16 | } |
実際には、出力があるかどうかを判断するため、出力がある場合は header("Location") を使用してジャンプします。メタのリフレッシュでジャンプ。
注: 実際には、このジャンプではさらに多くの機能を開発できますが、簡単に説明するだけなので、これ以上の内容は書きません。興味のある方は Toper にアクセスして読んでください。 。
このようにして、比較的単純なジャンプが完了しましたが、転送をどのように実装するか?
転送とは、実際には特定のコントローラーのアクションを再度呼び出すことであると単純に理解できます。
このようにして、比較的簡単に転送を実装できます:
01 | protected function _forward(Array $arr) { |
02 | $controller= empty($_GET['c']) ? C('defaultController') : trim($_GET['c']); //设置了默认的控制器 |
03 | $action= empty($_GET['a']) ? C('defaultAction') : trim($_GET['a']); //设置了默认的Action |
04 | if(array_key_exists('controller',$arr)) { |
05 | $controller = $arr['controller']; |
06 | } |
07 | if(array_key_exists('action',$arr)) { |
08 | $action = $arr['action']; |
09 | } |
10 | $controller .= 'Controller'; |
11 | if($controller === get_class()) { |
12 | if(method_exists($this,$action)) { |
13 | $this->$action(); |
14 | } else { |
15 | //时间有限,不写逻辑了 |
16 | } |
17 | } else { |
18 | if(class_exists($controller)) { |
19 | $class = new $controller(); |
20 | if(method_exists($class,$action)) { |
21 | $class->$action(); |
22 | } else { |
23 | //时间有限,不写了 |
24 | } |
25 | } else { |
26 | //时间有限,不写了 |
27 | } |
28 | } |
29 | } |
実際、ロジックは、呼び出されるアクションがこのコントローラーに属するかどうかを判断することです。このコントローラーの場合は、$this->$action() を直接呼び出すだけです。それ以外の場合は、インスタンスを作成する必要があります。このコントロール、つまり $class = new $controller() を呼び出して、このアクションを呼び出します。
書くのに30分かかると思っていましたが、時間が予算を超えたので、文法的な間違いがあるかどうかはわかりませんが、結局1時間かかりました。とにかく見てください アイデアを見るだけでOKです。