シンプルなMVCアプリケーション

PHPの適切なアプリケーションアーキテクチャのトピックに触れたいと思います。 この記事では、MVCデザインパターンに焦点を当てます。 このパターンを理解することがPHPプログラマーになるための鍵であり、MVCについて考えさせられたのは事実です。 あなたが初心者で、プログラムを正しく書き始めたいなら、読み進めてください。



理論



要するに、MVC(モデルビューコントローラー)は、データの出力を担当するコードが1つの場所に記述され、このデータを生成するコードが別の場所に記述されている場合にプログラムを記述する方法です。 その結果、結論を修正する必要がある場合、すぐにどこを見ればよいかがわかります。 現在、すべての一般的なフレームワークはこのアーキテクチャを使用しています。



また、2つのキャンプがあるという事実に言及する価値があります。1つはコントローラーにロジックを書き込み、2つはモデルに書き込みます。 私が知っているフレームワーク(yii、laravel)では、ロジックはコントローラーで記述され、モデルはORMの単なるインスタンスです。 ちなみに、yiiでは、マニュアルに、モデルにロジックを記述する必要があると書かれており、コントローラ自体の例にロジックを記述するのは非常に面白いです。



ビジネスロジックを決定し、コントローラーに書き込みます。 また、コントローラーのメソッドでは、モデルが呼び出されます。モデルは、変更するデータベースからデータを取得するために、基本的にORMインスタンスを持っています。 最終結果はビューに送信されます。 ビューには、データをクロール、フォーマット、および表示するためのHTMLマークアップと小さなPHPコードの挿入が含まれます。



また、MVCページコントローラーとフロントコントローラーの2種類があることにも言及できます。 Page Controllerはめったに使用されず、そのアプローチは複数のエントリポイントを使用することです(サイトへの要求は複数のファイルに対して行われます)。各エントリポイントには独自の表示コードがあります。 フロントコントローラーを1つのエントリポイントで記述します。



練習する



サーバーをセットアップして、単一のエントリポイントにリダイレクトすることから始める必要があります。 Apacheがある場合、.htaccessファイルに次のように記述します。



RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule .* index.php [L]
      
      





さらに、プロジェクトのフォルダーに、たとえばAppという名前のフォルダーを作成します。 以下の内容になります。



サービスロケーター。 App.phpファイル



 <?php class App { public static $router; public static $db; public static $kernel; public static function init() { spl_autoload_register(['static','loadClass']); static::bootstrap(); set_exception_handler(['App','handleException']); } public static function bootstrap() { static::$router = new App\Router(); static::$kernel = new App\Kernel(); static::$db = new App\Db(); } public static function loadClass ($className) { $className = str_replace('\\', DIRECTORY_SEPARATOR, $className); require_once ROOTPATH.DIRECTORY_SEPARATOR.$className.'.php'; } public function handleException (Throwable $e) { if($e instanceof \App\Exceptions\InvalidRouteException) { echo static::$kernel->launchAction('Error', 'error404', [$e]); }else{ echo static::$kernel->launchAction('Error', 'error500', [$e]); } } }
      
      





サービスロケーターは、アプリケーションのコンポーネントを格納するために必要です。 単純なmvcアプリケーションがあるため、レジストリパターンを使用しません(たとえば、yiiの場合)。 そして、アプリケーションコンポーネントを静的プロパティに保存するだけで、簡単にアクセスできるようになります。 アプリは、クラスオートローダーと例外ハンドラーも登録します。



ルーター Router.phpファイル



 <?php namespace App; class Router { public function resolve () { if(($pos = strpos($_SERVER['REQUEST_URI'], '?')) !== false){ $route = substr($_SERVER['REQUEST_URI'], 0, $pos); } $route = is_null($route) ? $_SERVER['REQUEST_URI'] : $route; $route = explode('/', $route); array_shift($route); $result[0] = array_shift($route); $result[1] = array_shift($route); $result[2] = $route; return $result; } }
      
      





単純なmvcアプリケーションでは、ルーターに含まれるメソッドは1つだけです。 $ _SERVER ['REQUEST_URI']からアドレスを解析します。 サイトのページへのすべてのリンクはwww.ourwebsite.com/%controller%/%action%の形式である必要があります。%controller%はコントローラーファイルの名前で、%action%は呼び出されるコントローラーメソッドの名前です。



Db.phpファイル



 <?php namespace App; use App; class Db { public $pdo; public function __construct() { $settings = $this->getPDOSettings(); $this->pdo = new \PDO($settings['dsn'], $settings['user'], $settings['pass'], null); } protected function getPDOSettings() { $config = include ROOTPATH.DIRECTORY_SEPARATOR.'Config'.DIRECTORY_SEPARATOR.'Db.php'; $result['dsn'] = "{$config['type']}:host={$config['host']};dbname={$config['dbname']};charset={$config['charset']}"; $result['user'] = $config['user']; $result['pass'] = $config['pass']; return $result; } public function execute($query, array $params=null) { if(is_null($params)){ $stmt = $this->pdo->query($query); return $stmt->fetchAll(); } $stmt = $this->pdo->prepare($query); $stmt->execute($params); return $stmt->fetchAll(); } }
      
      





このクラスは、接続時に配列を返す設定ファイルを使用します



Config / Db.phpファイル



 <?php return [ 'type' => 'mysql', 'host' => 'localhost', 'dbname' => 'gotlib', 'charset' => 'utf8', 'user' => 'root', 'pass' => '' ];
      
      





私たちのコア。 Kernel.phpファイル



 <?php namespace App; use App; class Kernel { public $defaultControllerName = 'Home'; public $defaultActionName = "index"; public function launch() { list($controllerName, $actionName, $params) = App::$router->resolve(); echo $this->launchAction($controllerName, $actionName, $params); } public function launchAction($controllerName, $actionName, $params) { $controllerName = empty($controllerName) ? $this->defaultControllerName : ucfirst($controllerName); if(!file_exists(ROOTPATH.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR.$controllerName.'.php')){ throw new \App\Exceptions\InvalidRouteException(); } require_once ROOTPATH.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR.$controllerName.'.php'; if(!class_exists("\\Controllers\\".ucfirst($controllerName))){ throw new \App\Exceptions\InvalidRouteException(); } $controllerName = "\\Controllers\\".ucfirst($controllerName); $controller = new $controllerName; $actionName = empty($actionName) ? $this->defaultActionName : $actionName; if (!method_exists($controller, $actionName)){ throw new \App\Exceptions\InvalidRouteException(); } return $controller->$actionName($params); } }
      
      





カーネルはルーターにアクセスし、コントローラーのアクションを開始します。 カーネルは、コントローラーやメソッドが必要ない場合にも例外をスローする場合があります。



Controller.phpファイル



また、後で継承するために、コントローラーの基本クラスを作成する必要があります。 ビューをレンダリング(出力の生成)できるように、メソッドを継承する必要があります。 レンダリングメソッドは、レイアウトの使用をサポートしています。たとえば、フッターやヘッダーなど、すべてのタイプに共通のコンポーネントを含むテンプレートです。



 <?php namespace App; use App; class Controller { public $layoutFile = 'Views/Layout.php'; public function renderLayout ($body) { ob_start(); require ROOTPATH.DIRECTORY_SEPARATOR.'Views'.DIRECTORY_SEPARATOR.'Layout'.DIRECTORY_SEPARATOR."Layout.php"; return ob_get_clean(); } public function render ($viewName, array $params = []) { $viewFile = ROOTPATH.DIRECTORY_SEPARATOR.'Views'.DIRECTORY_SEPARATOR.$viewName.'.php'; extract($params); ob_start(); require $viewFile; $body = ob_get_clean(); ob_end_clean(); if (defined(NO_LAYOUT)){ return $body; } return $this->renderLayout($body); } }
      
      





Index.phpファイル



ルートにインデックスファイルを作成することを忘れないでください。



 <?php define('ROOTPATH', __DIR__); require __DIR__.'/App/App.php'; App::init(); App::$kernel->launch();
      
      





コントローラーとタイプを作成します



アプリケーション(ミニフレームでも言うことができます)での作業は、ビューとコントローラーの作成になりました。 コントローラの例は次のとおりです(Controllersフォルダ内):



 <?php namespace Controllers; class Home extends \App\Controller { public function index () { return $this->render('Home'); } }
      
      





表示例(Viewsフォルダー内):



 <img src="Img/my_photo.jpeg" alt="my_photo" id="my_photo"> <h1></h1> <p>     - -.</p>  :<br> 8-912-641-3462<br> goootlib@gmail.com
      
      





Views / Layoutフォルダーで、Layout.phpを作成します。



 <!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title> </title> <meta name="viewport" content="width=device-width,initial-scale=1"> <link href="/Css/style_layout.css" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet"> </head> <body> <header> <nav> <a id="about_button" href="/home"> </a> <a id="portfolio_button" href="/portfolio"></a> <a id="blog_button" href="/blog"></a> </nav> </header> <div class="main"> <?= $body ?> </div> </body> </html>
      
      





おわりに



説明したアプリケーションコードを使用する場合は、error404およびerror500メソッドを使用してエラーコントローラーを作成することを忘れないでください。 私が説明したデータベースを操作するためのクラスは、クエリを手動で記述するのに適しています。代わりにORMに接続して、実際のモデルを作成できます。



All Articles