【MVCとは? 】
MVC とは、「3 つの部分 (MVC の正式名称、モデル、ビュー、コントローラー)」を調和して組み合わせて、複雑なアプリケーションを形成できるようにする概念です。車は現実の MVC の非常に良い例です。私たちが車を見るとき、内装と外装という 2 つの View (表示) 部分を見ます。これらはどちらもコントローラー、つまりドライバーから切り離すことができません。ブレーキ システム、ステアリング ホイール、その他の制御システムはモデルを表します。これらはドライバー (コントローラー) から制御方法を取得し、それを内装と外装 (ビュー) に適用します。
[Web 上の MVC]
MVC フレームワークでカバーされる概念は非常にシンプルで、非常に柔軟です。基本的な概念は、パラメーター要求に基づいてフレームワーク内のすべてのアプリケーションを制御する単一のコントローラー (index.php など) があるということです。通常、このコントローラーには、モデル、イベント、および GET パラメーターを定義するパラメーターが (最小限) 含まれています。このようにして、コントローラーはすべてのリクエストを確認し、適切なイベントを実行できます。たとえば、 /index.php?module=foo&event=bar のようなリクエストは、おそらく foo という名前のクラスをロードし、 foo::bar() [bar( )function です] を実行するために使用されます。この利点は次のとおりです。
各コードには独自の相対パス、データベース リンク、検証などが存在するため、アプリケーション内で無数のコードを維持しながら、すべてのアプリケーションのインターフェイスを維持するのは
非常に面倒です。そうすることで、手間が省け、コードをマージして再利用できるようになります
。[独自の MVC フレームワークを作成する理由は何ですか?] 】
これまで、PHP で書かれた MVC フレームワークをあまり見たことがありません。実際、私が知っているのは Solar だけです。これは完全に PHP5 で書かれています。もう 1 つは Cake で、PHP の RoR (Ruby on Rails - Ruby 言語用のオープンソース ネットワーク フレームワーク) を目指しています。私自身、どちらのフレームワークにも不満があります。PEAR や Smarty などに含まれる既存のコードが利用されていません。最後に、Solar はほとんど 1 人で書かれたフレームワークです。この著者である Paul が善良な人間でも、優れたプログラマでもないと言うつもりはありません)。これらの質問を聞いても、おそらくそれを否定することはできませんし、まったく気にしていない可能性もあります。しかし、このため、できるだけそれらを見てください。
[古いやり方]
2001 年に戻って自分が書いたコードを見ると、作成者は次のような template.txt というファイルを見つけるかもしれません: www.phpv.net
<?php の
転載には出典を示してください。
require_once('config.php'); // その他の要件、DB 情報など
$APP_DB = 'mydb';
$APP_REQUIRE_LOGIN = false // スクリプトにログインが必要な場合は true に設定します。
$APP_TEMPLATE_FILE = 'foo.php' // Smarty テンプレート
$APP_TITLE = 'マイアプリケーション'
if ($APP_REQUIRE_LOGIN == true) {
if (!isset($_SESSION['userID'])) {
header("場所: /path/to/login.php");
出口();
}
$
db = DB::connect('mysql://'.$DB_USER.':'.$DB_PASS.'@localhost/'.$APP_DB);
if (!PEAR::isError($db)) {
$db->setFetchMode(DB_FETCHMODE_ASSOC);
} それ以外 {
die($db->getMessage());
}
// ここにロジックを記述します
// テンプレートを出力
include_once(APP_TEMPLATE_PATH.'/header.php');
include_once(APP_TEMPLATE_PATH.'/'.$APP_TEMPLATE_FILE);
include_once(APP_TEMPLATE_PATH.'/footer.php');
?>
なんと、このコードを見るだけでゾクゾクしてしまいます。このコードのコンセプトは、すべてのアプリケーションがこの処理方法に適応できるようにすることです。たとえば、template.txt を myapp.php にコピーし、いくつかの変数を変更するだけで、実行できるようになります。それでも、この高度に組織化されたアプローチにはいくつかの重大な欠点があります。
上司が作成者に myapp.php を使用して、場合によっては PDF、場合によっては HTML、場合によっては SOAP (XML リクエストを直接送信) を出力することを要求した場合はどうすればよいでしょうか。する?
このアプリで IMAP または LDAP 認証が必要な場合はどうすればよいですか?
さまざまな種類のコード (編集、アップグレード、削除など) をどのように処理すればよいですか?
マルチレベル認証 (管理者と非管理者) はどのように処理すればよいですか?
出力キャッシュを有効にするにはどうすればよいですか? www.phpv.net転載する場合は出典を明記してください
[新しい方法]
この MVC フレームワークにすべてを投げ込むと、人生はとてもシンプルであることがわかります。次のコードを比較してください:
<?php
クラス myapp は FR_Auth_User を拡張します
{
パブリック関数 __construct()
{
親::__construct();
関数
__default()
{
// ここで何かをします
関数
delete()
{ }
パブリック関数 __destruct()
{
親::__destruct();
}
、
データベースへのリンク、ユーザーがログインしているかどうかの判断、またはその他の情報の出力には使用されないことに注意してください
。
コントローラーにはすべてが備わっています。
LDAP に対して認証したい場合は、FR_Auth_LDAP を確立できます。コントローラーは特定の出力メソッド ($_GET['output'] など) を認識でき、いつでも PDF または SOAP に変換できます。イベント ハンドラーの delete は削除のみを担当し、その他のことは考慮しません。このモジュールには FR_User クラスのインスタンスがあるため、ユーザーがログインしているかどうかなどを簡単に判断できます。 Smarty はテンプレート エンジンとしてキャッシュを制御するのは当然ですが、コントローラーがキャッシュの一部を制御することもできます。
前述の古い方法から MVC 方法への移行は、多くの人にとって新しくて馴染みのない概念かもしれませんが、一度そのような概念に切り替えると、元に戻すのは非常に困難になります。
[最下層の構築]
私は PEAR、特に PEAR_Error クラスのファンです。 PHP5 では、PEAR_Error に代わる新しい組み込みクラス「Exception」が導入されています。ただし、PEAR_Error には、Exception よりも実用的な機能がいくつかあります。したがって、この一連の記事の MVC フレームワークの例では、エラー処理に MVC フレームワークを使用します。いずれにしても、コンストラクター自体はエラーを返すことができないため、コンストラクターからエラーを取得するには Exception を使用する必要があります。
これらの基本クラスを設計する目的は次のとおりです。
PEAR を使用して基本クラスに関数をすばやく追加し、
ユーザーがこのフレームワークでアプリケーションを迅速に開発できるように、繰り返し実行できる小さなクラスを作成します。
phpDocumentor
を使用してすべての基本クラスのドキュメントを生成します。
クラス階層は次のようになります。
- FR_Object は、使用する他のすべてのオブジェクトに基本的な機能を提供します (ロギング、一般的な setFrom()、toArray() を含む)
- FR_Object_DB は、サブクラスや他の関数へのデータベース リンクを提供する小さな層です
- FR_Module は、すべてのアプリケーションの最下位クラス (モジュール、モデルなどとも呼ばれます)
- FR_Auth はすべての検証メカニズムの最下位クラスです
· FR_Auth_User は、ユーザーがログインしているかどうかを検証する必要があるすべてのモジュールを検証するために使用される検証クラスです
· FR_Auth_No は検証を必要としないモジュールのすべての「偽の検証クラス」
- FR_Presenter は、読み込みと表示を処理するすべてのアプリケーションの基礎となるクラスです
。 - FR_Presenter_Smarty は、さまざまなドライブを読み込む機能を含むプレゼンテーション層です。 Smarty は非常に優れたテンプレート クラスで、キャッシュ メカニズムが組み込まれており、活発な開発グループが存在します (翻訳者注: これは明らかに宣伝です ~)
· FR_Presenter_debug はデバッグ部分の表示層です。
FR_Presenter_rest は、
開発者がアプリケーションを XML で出力できるようにする REST プレゼンテーション層です。
上記の基本的なクラス構造から、この MVC フレームワークのさまざまな部分がわかるはずです。 FR_Module はモジュールに必要なすべてを提供し、FR_Presenter はさまざまな表示メソッドを提供します。このシリーズの次の記事では、上記のすべての基本クラスを結び付けるコントローラーを作成します。
[コーディング標準]
コードを正式に記述する前に、パートナー (またはあなた自身) と座ってコーディング標準について話し合う (または考える) 必要があります。 MVC プログラミングの全体的な考え方は、コードの再利用性 (偶然の一致を減らす) とコードの標準化という 2 つの点を中心に展開されます。少なくとも次の点を考慮することをお勧めします。
まず考慮すべきことは、変数の命名と略語の標準です。これを理由にパートナーと大喧嘩にならないように注意してください。ただし、一度標準が設定されたら、特に低レベルのコード (基本クラス) を作成する場合には、最初から最後までその標準に従う必要があります。
すべての関数、クラス、グローバル変数で使用する標準プレフィックスをカスタマイズします。残念ながら、PHPは「ネームスペース(名前空間)」をサポートしていません。したがって、変数名との混乱や競合を避けるために、接頭辞を使用することが賢明です。この記事では、このような接頭辞として「FR_」を使用します。
[最下層の記述]
ファイルレベルの計画は非常に重要です。基本的な階層計画はシンプルですが、ある程度厳密に定義されています
。
config.php
インデックス.php
含まれるもの/
認証.php
認証/
No.php
ユーザー.php
モジュール.php
オブジェクト.php
物体/
DB.php
Presenter.php
プレゼンター/
共通.php
デバッグ.php
スマート.php
スマーティ/
モジュール/
例/
config.php
example.php
tpl/
たとえば .tpl
tpl/
デフォルト/
キャッシュ/
構成/
テンプレート/
templates_c/
このようなファイル階層には大量のコードが含まれているに違いないと思うかもしれません。確かにそうですが、やり遂げることはできます。このシリーズが終わる頃には、プログラミングがより簡単になり、開発速度が大幅に向上していることがわかるでしょう。
ファイル階層では、すべての基本クラスが include フォルダーにあります。各機能モジュールは、構成ファイル、少なくとも 1 つのモジュール ファイルと 1 つのテンプレート ファイルを使用します。すべてのモジュールは modules フォルダーに含まれています。私は、テンプレート ファイルを別の外部フォルダー (tpl フォルダー) に配置することに慣れてきました。
config.php - すべてのグローバル構成変数を含む中央構成ファイル。
Index.php - コントローラーについては、次の記事で詳しく説明します。
object.php - すべての基本クラスの基礎となるクラスで、クラスに必要な機能のほとんどを提供します。 FR_Object_DB はこのクラスを継承し、データベース リンクを提供します。
構造の基本概念は、すべてのサブクラスが中心クラスから継承し、すべてのサブクラスがいくつかの共通の機能を共有するようにすることです。 FR_Object にデータベースへのリンク機能を組み込むこともできますが、すべてのクラスにこの機能が必要なわけではないため、FR_Object_DB の存在理由があり、それについては後ほど説明します。
<?php
require_once('Log.php');
/**
*FR_オブジェクト
*
* フレームワークで使用するほとんどのクラスの基本オブジェクト クラス。
* 基本的なログ機能と設定/取得機能を提供します。
*
* @author Joe Stump < [email protected] >
* @packageFramework
*/
抽象クラス FR_Object
{
/**
* $log
*
* @varmixed $log PEAR ログのインスタンス
*/
保護された $log;
/**
*$me
*
* @var は ReflectionClass の $me インスタンスを混合しました
*/
$me を保護しました;
/**
* __構築
*
* @author Joe Stump < [email protected] >
* @アクセスパブリック
*/
パブリック関数 __construct()
{
$this->log = Log::factory('file',FR_LOG_FILE);
$this->me = 新しい ReflectionClass($this);
}
/**
* セットから
*
* @author Joe Stump < [email protected] >
* @アクセスパブリック
* @parammixed $data インスタンスに割り当てる変数の配列
* @return void
*/
パブリック関数 setFrom($data)
{
if (is_array($data) && count($data)) {
$valid = get_class_vars(get_class($this));
foreach ($valid as $var => $val) {
if (isset($data[$var])) {
$this->$var = $data[$var];
}
}
}
}
/**
* toArray
*
* @author Joe Stump < [email protected] >
* @アクセスパブリック
* @return 混合変数名をキーとしたメンバー変数の配列
*/
パブリック関数 toArray()
{
$defaults = $this->me->getDefaultProperties();
$return = 配列();
foreach ($defaults as $var => $val) {
if ($this->$var instanceof FR_Object) {
$return[$var] = $this->$var->toArray();
} それ以外 {
$return[$var] = $this->$var;
}
$return を返します
;
}
/**
* __破壊
*
* @author Joe Stump < [email protected] >
* @アクセスパブリック
* @return void
*/
パブリック関数 __destruct()
{
if ($this->log インスタンスオブログ) {
$this->log->close();
}
}
}
?>
auth.php – これは、すべての認証機能の基礎となるクラスです。これは FR_Module から拡張されており、その主な機能は基本的な検証クラスがどのように動作するかを定義することです。
FR_Module と同様に、一部のクラスはデータベースに接続する必要がありません。同様に、FR_Auth_No を作成して、認証関数を必要としないクラスに適用できます。
<?php
抽象クラス FR_Auth は FR_Module を拡張します
{
// {{{ __construct()
function__construct()
{
親::__construct();
}
// }}}
// {{{ 認証()
抽象関数authenticate();
// }}}
// {{{ __destruct()
関数 __destruct()
{
親::__destruct();
}
// }}}
}
?>
module.php - すべてのモジュールの中心
<?php
抽象クラス FR_Module は FR_Object_Web を拡張します
{
// {{{ プロパティ
/**
* $プレゼンター
*
* FR_Presenter::factory() でどのプレゼンテーション (ビュー) を決定するために使用されます
* モジュールにはクラスを使用する必要があります。
*
* @author Joe Stump < [email protected] >
* @var string $presenter
* @FR_Presenter、FR_Presenter_common、FR_Presenter_smarty を参照
*/
パブリック $presenter = 'スマート';
/**
* $データ
*
* 最終的にビューに渡されるモジュールによって設定されたデータ。
*
* @author Joe Stump < [email protected] >
* @varmixed $data モジュールデータ
* @FR_Module::set()、FR_Module::getData() を参照
*/
protected $data = array();
/**
* $name
*
* @author Joe Stump < [email protected] >
* @var string $name モジュールクラスの名前
*/
パブリック $name
/**
* $tplファイル
*
* @author Joe Stump < [email protected] >
* @var string $tplFile テンプレート ファイルの名前
* @FR_Presenter_smarty を参照
*/
パブリック $tplFile
/**
* $モジュール名
*
* @author Joe Stump < [email protected] >
* @var string $moduleName 要求されたモジュールの名前
* @FR_Presenter_smarty を参照
*/
public $moduleName = null;
/**
* $pageTemplateFile
*
* @author Joe Stump < [email protected] >
* @var string $pageTemplateFile 外側のページ テンプレートの名前
*/
public $pageTemplateFile = null;
// }}}
// {{{ __construct()
/**
* __構築
*
* @author Joe Stump < [email protected] >
*/
パブリック関数 __construct()
{
親::__construct();
$this->name = $this->me->getName();
$this->tplFile = $this->name.'.tpl';
}
// }}}
// {{{ __デフォルト()
/**
* __デフォルト
*
※イベントが指定されていない場合、この関数はコントローラによって実行されます
* ユーザーのリクエストに応じて。
*
* @author Joe Stump < [email protected] >
*/
抽象パブリック関数 __default();
// }}}
// {{{ set($var,$val)
/**
* セット
*
* モジュールのデータを設定します。これは最終的に に渡されます。
* FR_Module::getData() 経由のプレゼンター クラス。
*
* @author Joe Stump < [email protected] >
* @param string $var 変数の名前
* @parammixed $val 変数の値
* @return void
* @FR_Module::getData() を参照
*/
保護された関数 set($var,$val) {
$this->data[$var] = $val;
}
// }}}
// {{{ getData()
/**
*getData
*
* モジュールのデータを返します。
*
* @author Joe Stump < [email protected] >
* @return 混合
* @FR_Presenter_common を参照
*/
パブリック関数 getData()
{
$this->data を返します。
}
// }}}
// {{{ isValid($module)
/**
*は有効です
*
* $module が有効なフレームワーク モジュールであるかどうかを判断します。これは、によって使用されます。
* モジュールがフレームワークに適合するかどうかを判断するコントローラー
* モールド。FR_Module と FR_Auth の両方から拡張される場合は、次のようになります。
* 走れてよかった。
*
* @author Joe Stump < [email protected] >
* @static
* @param 混合 $module
* @return bool
*/
パブリック静的関数 isValid($module)
{
return (is_object($module) &&
FR_Module の $module インスタンス &&
$module インスタンス of FR_Auth);
}
// }}}
// {{{ __destruct()
パブリック関数 __destruct()
{
親::__destruct();
}
// }}}
}
?>
presenter.php - プレゼンテーション層のコア。
<?php
クラス FR_プレゼンター
{
// {{{ ファクトリー($type,FR_Module $module)
/**
*工場
*
* @author Joe Stump < [email protected] >
* @アクセスパブリック
* @param string $type プレゼンテーション タイプ (私たちの見解)
* @parammixed$module プレゼンターが表示するモジュール
* 失敗または有効なプレゼンターの場合は @return 混合 PEAR_Error
* @static
*/
静的パブリック関数ファクトリー($type,FR_Module $module)
{
$file = FR_BASE_PATH.'/includes/Presenter/'.$type.'.php';
if (include($file)) {
$class = 'FR_Presenter_'.$type;
if (class_exists($class)) {
$presenter = 新しい $class($module);
if ($presenter インスタンスof FR_Presenter_common) {
$presenter を返します。
}
return PEAR::raiseError('無効なプレゼンテーション クラス: '.$type);
}
return PEAR::raiseError('プレゼンテーション クラスが見つかりません: '.$type);
}
return PEAR::raiseError('プレゼンター ファイルが見つかりません: '.$type);
}
// }}}
}
?>
次回はコントローラー(MVCではController、この記事ではindex.php)の構造を紹介します。第3回目はプレゼンテーション層(MVCでの表示)について紹介します。 4 回目の記事では、例として特定のモジュールを使用してアプリケーション (MVC のモジュールまたはモデル) を作成します。