MVCモードのPHP実現
7878 ワード
MVCモードはウェブサイトアーキテクチャでよく見られる.これにより、3つの階層構造のアプリケーションを構築し、コードから有用な階層を分離し、デザイナーと開発者の共同作業を支援し、既存のプログラムを維持し、拡張する能力を高めることができます.
ビュー(View)
「ビュー」は主にWebブラウザに送られた最終結果を指しますか?例えば、私たちのスクリプトが生成したHTMLです.ビューといえばテンプレートを思い浮かべる人が多いが,テンプレートスキームをビューと呼ぶ正確性は疑わしい.
ビューにとって最も重要なことは、「自己意識(self aware)」であるべきかもしれません.ビューがレンダリングされると、ビューの要素はより大きなフレームワークでの役割を意識することができます.
XMLを例にとると,XMLが解析されたとき,DOM APIはこのような認知を持っていたと言えるだろうか.DOMツリーのノードは、どこにあるか、何が含まれているかを知っています.(XMLドキュメントのノードをSAXで解析する場合、そのノードを解析する場合にのみ意味があります.)
ほとんどのテンプレートスキームでは、簡単なプロセス言語とこのようなテンプレートラベルが使用されます.
ドキュメントには意味がありません.PHPは他のもので置き換えられるだけです.
このようなビューのばらばらな説明に同意すれば、ほとんどのテンプレートスキームがビューとモデルを効果的に分離していないことにも同意します.テンプレートラベルは、モデルに格納されるものに置き換えられます.
ビューを実装するときに、「全体のビューの置き換えは簡単ですか?」といくつか質問します.「新しいビューを実装するにはどのくらいかかりますか?」「ビューの記述言語を簡単に置き換えることができますか?(例えば同じビューでHTMLドキュメントをSOAPドキュメントで置き換える)
モデル(Model)
モデルはプログラムロジックを表します.(エンタープライズ・プログラムではビジネス・レイヤと呼ばれることが多い)
総じて、モデルのタスクは、既存のデータをビューに表示されるいくつかの意味を含むデータに変換することです.通常、モデルはデータ・クエリーをカプセル化し、いくつかの抽象データ・クラス(データ・アクセス・レイヤ)によってクエリーを実現することができます.例えば、イギリスの年間降雨量(自分で良いリゾートを探すためだけ)を計算したい場合は、モデルは10年間の毎日の降雨量を受信し、平均値を計算してからビューに渡します.
コントローラ
簡単に言えば、コントローラは、Webアプリケーションに入力されたHTTPリクエストの最初の呼び出しの一部である.GET変数などの受信したリクエストをチェックし、適切なフィードバックを行います.最初のコントローラを書く前に、他のPHPコードを書くのは難しいです.最も一般的な使い方はindexです.phpのswitch文のような構造:
このコードはプロシージャとオブジェクト向けのコードを混用していますが、小さなサイトでは通常最適です.上のコードは最適化できますが.
コントローラは、実際にはモデルのデータとビュー要素との間のバインドをトリガするためのコントロールです.
例
ここではMVCモードを用いた簡単な例である.
まず、通常のクラスであるデータベース・アクセス・クラスが必要です.
その上に模型を置きます.
モデルとデータ・アクセス・クラスの間で、それらのインタラクションは1行以上ではないことに注意してください.多くの行が転送されていないので、すぐにプログラムが遅くなります.同じプログラムは使用モードのクラスに対して、メモリに1行(Row)?保存されたクエリーリソース(query resource)?言い換えれば、私たちはMYSQLに結果を維持させます.
次はビュー??私はHTMLを削除してスペースを節約して、あなたはこの文章の完全なコードを見ることができます.
最後にコントローラで、ビューをサブクラスに実装します.
MVCを実現する唯一の方法ではないことに注意してください??たとえば、コントローラを使用してモデルを実装し、ビューを統合できます.これはプレゼンテーションモードの1つの方法にすぎません.
私たちのindex.phpファイルは次のように見えます.
きれいで簡単です.
PHPでは、コントローラを使用するテクニックがあります.
1つの提案は、プログラムURLの名前空間形式(namespace)を定義したほうがいいということです.これにより、次のような規範が比較されます.
コントローラをこのように処理できます.
開発速度と適応性のバランスをとるなど、コントローラを構築するのは難しい場合があります.インスピレーションを得る良い場所はApacheグループのJava Strutsで、そのコントローラは完全にXMLドキュメントによって定義されています.
関連添付ファイル:本明細書の完全な例
本文の英文原版住所:http://www.phppatterns.com/index.php/article/articleview/11/
ビュー(View)
「ビュー」は主にWebブラウザに送られた最終結果を指しますか?例えば、私たちのスクリプトが生成したHTMLです.ビューといえばテンプレートを思い浮かべる人が多いが,テンプレートスキームをビューと呼ぶ正確性は疑わしい.
ビューにとって最も重要なことは、「自己意識(self aware)」であるべきかもしれません.ビューがレンダリングされると、ビューの要素はより大きなフレームワークでの役割を意識することができます.
XMLを例にとると,XMLが解析されたとき,DOM APIはこのような認知を持っていたと言えるだろうか.DOMツリーのノードは、どこにあるか、何が含まれているかを知っています.(XMLドキュメントのノードをSAXで解析する場合、そのノードを解析する場合にのみ意味があります.)
ほとんどのテンプレートスキームでは、簡単なプロセス言語とこのようなテンプレートラベルが使用されます.
<p>{some_text}</p>
<p>{some_more_text}</p>
ドキュメントには意味がありません.PHPは他のもので置き換えられるだけです.
このようなビューのばらばらな説明に同意すれば、ほとんどのテンプレートスキームがビューとモデルを効果的に分離していないことにも同意します.テンプレートラベルは、モデルに格納されるものに置き換えられます.
ビューを実装するときに、「全体のビューの置き換えは簡単ですか?」といくつか質問します.「新しいビューを実装するにはどのくらいかかりますか?」「ビューの記述言語を簡単に置き換えることができますか?(例えば同じビューでHTMLドキュメントをSOAPドキュメントで置き換える)
モデル(Model)
モデルはプログラムロジックを表します.(エンタープライズ・プログラムではビジネス・レイヤと呼ばれることが多い)
総じて、モデルのタスクは、既存のデータをビューに表示されるいくつかの意味を含むデータに変換することです.通常、モデルはデータ・クエリーをカプセル化し、いくつかの抽象データ・クラス(データ・アクセス・レイヤ)によってクエリーを実現することができます.例えば、イギリスの年間降雨量(自分で良いリゾートを探すためだけ)を計算したい場合は、モデルは10年間の毎日の降雨量を受信し、平均値を計算してからビューに渡します.
コントローラ
簡単に言えば、コントローラは、Webアプリケーションに入力されたHTTPリクエストの最初の呼び出しの一部である.GET変数などの受信したリクエストをチェックし、適切なフィードバックを行います.最初のコントローラを書く前に、他のPHPコードを書くのは難しいです.最も一般的な使い方はindexです.phpのswitch文のような構造:
<?php
switch ($_GET['viewpage']) {
case "news":
$page=new NewsRenderer;
break;
case "links":
$page=new LinksRenderer;
break;
default:
$page=new HomePageRenderer;
break;
}
$page->display();
?>
このコードはプロシージャとオブジェクト向けのコードを混用していますが、小さなサイトでは通常最適です.上のコードは最適化できますが.
コントローラは、実際にはモデルのデータとビュー要素との間のバインドをトリガするためのコントロールです.
例
ここではMVCモードを用いた簡単な例である.
まず、通常のクラスであるデータベース・アクセス・クラスが必要です.
<?php
/**
* A simple class for querying MySQL
*/
class DataAccess {
/**
* Private
* $db stores a database resource
*/
var $db;
/**
* Private
* $query stores a query resource
*/
var $query; // Query resource
//! A constructor.
/**
* Constucts a new DataAccess object
* @param $host string hostname for dbserver
* @param $user string dbserver user
* @param $pass string dbserver user password
* @param $db string database name
*/
function DataAccess ($host,$user,$pass,$db) {
$this->db=mysql_pconnect($host,$user,$pass);
mysql_select_db($db,$this->db);
}
//! An accessor
/**
* Fetches a query resources and stores it in a local member
* @param $sql string the database query to run
* @return void
*/
function fetch($sql) {
$this->query=mysql_unbuffered_query($sql,$this->db); // Perform query here
}
//! An accessor
/**
* Returns an associative array of a query row
* @return mixed
*/
function getRow () {
if ( $row=mysql_fetch_array($this->query,MYSQL_ASSOC) )
return $row;
else
return false;
}
}
?>
その上に模型を置きます.
<?php
/**
* Fetches "products" from the database
*/
class ProductModel {
/**
* Private
* $dao an instance of the DataAccess class
*/
var $dao;
//! A constructor.
/**
* Constucts a new ProductModel object
* @param $dbobject an instance of the DataAccess class
*/
function ProductModel (&$dao) {
$this->dao=& $dao;
}
//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $start the row to start from
* @param $rows the number of rows to fetch
* @return void
*/
function listProducts($start=1,$rows=50) {
$this->dao->fetch("SELECT * FROM products LIMIT ".$start.", ".$rows);
}
//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $id a primary key for a row
* @return void
*/
function listProduct($id) {
$this->dao->fetch("SELECT * FROM products WHERE PRODUCTID='".$id."'");
}
//! A manipulator
/**
* Fetches a product as an associative array from the $dbobject
* @return mixed
*/
function getProduct() {
if ( $product=$this->dao->getRow() )
return $product;
else
return false;
}
}
?>
モデルとデータ・アクセス・クラスの間で、それらのインタラクションは1行以上ではないことに注意してください.多くの行が転送されていないので、すぐにプログラムが遅くなります.同じプログラムは使用モードのクラスに対して、メモリに1行(Row)?保存されたクエリーリソース(query resource)?言い換えれば、私たちはMYSQLに結果を維持させます.
次はビュー??私はHTMLを削除してスペースを節約して、あなたはこの文章の完全なコードを見ることができます.
<?php
/**
* Binds product data to HTML rendering
*/
class ProductView {
/**
* Private
* $model an instance of the ProductModel class
*/
var $model;
/**
* Private
* $output rendered HTML is stored here for display
*/
var $output;
//! A constructor.
/**
* Constucts a new ProductView object
* @param $model an instance of the ProductModel class
*/
function ProductView (&$model) {
$this->model=& $model;
}
//! A manipulator
/**
* Builds the top of an HTML page
* @return void
*/
function header () {
}
//! A manipulator
/**
* Builds the bottom of an HTML page
* @return void
*/
function footer () {
}
//! A manipulator
/**
* Displays a single product
* @return void
*/
function productItem($id=1) {
$this->model->listProduct($id);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
//! A manipulator
/**
* Builds a product table
* @return void
*/
function productTable($rownum=1) {
$rowsperpage='20';
$this->model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
//! An accessor
/**
* Returns the rendered HTML
* @return string
*/
function display () {
return $this->output;
}
}
?>
最後にコントローラで、ビューをサブクラスに実装します.
<?php
/**
* Controls the application
*/
class ProductController extends ProductView {
//! A constructor.
/**
* Constucts a new ProductController object
* @param $model an instance of the ProductModel class
* @param $getvars the incoming HTTP GET method variables
*/
function ProductController (&$model,$getvars=null) {
ProductView::ProductView($model);
$this->header();
switch ( $getvars['view'] ) {
case "product":
$this->productItem($getvars['id']);
break;
default:
if ( empty ($getvars['rownum']) ) {
$this->productTable();
} else {
$this->productTable($getvars['rownum']);
}
break;
}
$this->footer();
}
}
?>
MVCを実現する唯一の方法ではないことに注意してください??たとえば、コントローラを使用してモデルを実装し、ビューを統合できます.これはプレゼンテーションモードの1つの方法にすぎません.
私たちのindex.phpファイルは次のように見えます.
<?php
require_once('lib/DataAccess.php');
require_once('lib/ProductModel.php');
require_once('lib/ProductView.php');
require_once('lib/ProductController.php');
$dao=& new DataAccess ('localhost','user','pass','dbname');
$productModel=& new ProductModel($dao);
$productController=& new ProductController($productModel,$_GET);
echo $productController->display();
?>
きれいで簡単です.
PHPでは、コントローラを使用するテクニックがあります.
$this->{$_GET['method']}($_GET['param']);
1つの提案は、プログラムURLの名前空間形式(namespace)を定義したほうがいいということです.これにより、次のような規範が比較されます.
"index.php?class=ProductView&method=productItem&id=4"
コントローラをこのように処理できます.
$view=new $_GET['class'];
$view->{$_GET['method']($_GET['id']);
開発速度と適応性のバランスをとるなど、コントローラを構築するのは難しい場合があります.インスピレーションを得る良い場所はApacheグループのJava Strutsで、そのコントローラは完全にXMLドキュメントによって定義されています.
関連添付ファイル:本明細書の完全な例
本文の英文原版住所:http://www.phppatterns.com/index.php/article/articleview/11/