Web

Front Controller

  1. Rewriteエンジン
    httpd.conf(Winのみ)で設定
    LoadModule rewrite_module modules/mod_rewrite.so
    .htaccessで設定
    RewriteEngine on
    RewriteBase /zend/controller/ #対象パスを指定
    RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php #ルール
    http://www.example.com/zend/controller/~配下のリクエストはすべて対象となりindex.phpに寄せる。もし公開フォルダ配下をすべてを対象としたい場合は
    RewriteBase /
    とする
  2. index.phpにリクエストがくるので、振り分け処理を設定する
    define('APP', './application'); #application dirのパス
    require_once 'Zend/Controller/Front.php';
    
    $front = Zend_Controller_Front::getInstance(); #Zend_Controller_Front オブジェクト生成  newではない
    $front->setControllerDirectory(APP.'/controllers'); #action controllerの配置先
    $front->dispatch(); #実行。frontcontrollerはactioncontrollerへの委譲(処理の引渡し)を行う

Zend_Controller_Request_Http(リクエストオブジェクト)

呼び出す際は Zend_Controller_Action::getRequestメソッドを呼び出す。

リクエストデータを取得するメソッド

getQueryクエリ情報(〜?key=value)$_GET
getPostポストデータ$_POST
getCookieクッキー情報$_COOKIE
getServerサーバ変数$_SERVER
getEnvサーバ環境変数$_ENV
getUserParam?ユーザパラメーター(~/param1/value1/..)n/a
getParamクエリ情報->ポストデータ->ユーザデータ$_GET->$_POST

※スーパーグローバル変数などを使いたい場合はリクエストオブジェクト経由でアクセスする
※getParamは使わないように心がける
※SESSIONに関してはZend_Sessionを使う

リクエスト時に使用されたHTTPメソッドを取得/判定する

getMethod()使用しているHTTPメソッドを取得
isGet()HTTP GETによる要求か?
isPost()HTTP POSTによる要求か?
isPut()HTTP PUTによる要求か?
isDelete()HTTP DELETEによる要求か?
isHead()HTTP HEADによる要求か?
isOptions()HTTP OPTIONSによる要求か?
isXmlHttpRequest?()AJAX要求か?

isXmlHttpRequest?()はX-Requested-Withヘッダの値がXMLHttpRequest?かどうか判定する->ヘッダを付与しないJavaScriptライブラリもあるので要注意。

コンテンツ追加/削除する

setBodyコンテンツを設定
appendBODYコンテンツを追加
prepend既存セグメントの先頭にコンテンツを追加
insert指定セグメントの末尾にコンテンツを追加
clearBody指定セグメントを削除
getBody指定セグメイントを取得

コンテンツをいくつかのセグメイントとして分けて管理している。

  1. header
  2. insert
  3. setBody
  4. appendBody
  5. insert
  6. append

getResponse後、実際に出力するのはsendResponse(<-Front Controllerはdispatch後に自動的にコールするので明示的に呼び出す必要はない)

応答ヘッダを操作する

setHeader指定されたヘッダを設定
canSendHeaders?ヘッダが送信されているかどうか
getHeaders()すべてのヘッダを取得
clearHeaders()すべてのヘッダを破棄
getRawHeader?()生のヘッダを設定
clearRawHeaders?()生のヘッダをすべて破棄
clearAllHeaders?()通常のヘッダと生のヘッダ双方をすべて破棄

※header/headers_sendなどは使わない

Action Controller

Front Controllerから処理を委譲されてリクエストに応じた処理を行うクラス

require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action {
 public function indexAction(){
   $this->view->result = 'Hello World!';
 }
}

命名規則

命名規則
ファイル名クラス名.phpIndexController?.php
クラス名コントローラ名ControllerIndexController?
メソッドアクション名ActionindexAction

Zend_Controller_Action

  • Zend_Controller_Action クラスがRequest/Response処理に関する処理を行う
  • 使用する場合は継承する

処理順序

  1. __construct method(*Zend Frameworkが使用、初期化にはinit methodを使用)
  2. init method
  3. preDispatch method (action実行前の処理)
  4. Action method(XXXXAction) 個別のアクション
  5. postDispatch method(action実行後の後処理)

Error Controller

  • 不正なコントローラ/アクションが指定された場合の挙動を定義する
  • エラーコントローラのコントローラ名/アクション名はerrorである必要あり

エラーページを出力する

#ErrorController.php
require_once 'Zend/Controller/Action.php';
require_once 'Zend/Controller/Plugin/ErrorHandler.php'; #ErrorHandler plugin をインポート
require_once 'Zend/View.php';

class ErrorController extends Zend_Controller_Action {
  public function errorAction(){
   $errs = $this->_getParam('error_handler');
  switch($errors->type){
   case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: #コントローラが存在しない場合
   case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: #アクションが存在しない場合
    $this->view->msg = '存在しないコントローラ/アクションです';
    break;
  default:
    $this->view->msg = $errs->exception->getMessage();
    break;
  }
 }
 public function throwAction(){ #例外を処理する
  throw new Exception('例外が発生!');
 }
}
error.phtml
<html>
 <head>
  <title>Error page</title>
 </head>
 <body>
 <?php print($this->escape($this->msg)); ?>
 </body>
</html>

発生した例外情報は以下のようにして取得(error_handler object)

Zend_Controller_Action::_getParam('error_handler')

error_handler objectのtypeプロパティ

EXCEPTION_NO_CONTROLLER コントローラが存在しない
EXCEPTION_NO_ACTIONアクションが存在しない
EXCEPTION_OTHERその他の例外

Redirect

  1. Clients-> request page A
  2. Server -> return result of page A to client(which is Page B)
  3. Clients -> request Page B automaticaly
  4. Server -> return resutl of page B to client

_redirectメソッドがリダイレクトを行う

Zend_Controller_Action::_redirect($url, $option)~

オプション

exitリダイレクトのタイミングで処理を終了するTrue
prependBaseベースURIを引数$urlの先頭に付与するかtrue
codeリダイレクト時に使用するコード(301-306)302

コントローラ・アクションが存在しない場合にディフォルトコントローラにリダイレクトする

#ErrorController.php
public function errorAction(){
 $type = $this->_getParam('error_handler')->type;
 switch($type){
  case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
  case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  $this->_redirect('index/index);
  $this->view->msg = '存在しないコントローラ/アクションです。';
 break;
 ~略~
 }
}

Forward

  1. Client -> request page A
  2. Server -> return result of page B

_forwardだと内部処理になるため、アドレスバーには間違ったままのものが使われる

#FowardController.php
<?php
require_once 'Zend/Controller/Action.php';

class ForwardController extends Zend_Controller_Action { 
	public function indexAction(){ #forwad/indexアクションの定義
		$req = $this->getRequest();
		$req->setParam('greeting', 'こんにちは');
		$this->_forwad('result');
	}
	
	public function index2Action(){
		$req = $this->getRequest():
		$req->setParam('greeting', 'こんばんは');
		$this->_forwad('result');
	}
	
	public function resultAction(){
		$req = $this->getRequest();
		$this->view->result = $req->getUserParam('greeting').', '.$req->getQuery('lang').'!';
	}
}
#result.phtml
<html>
	<head>
		<title>forward</title>
	</head>
	<body>
	<?php print($this->escape($this->result)); ?>
	</body>
</html>

http://www.example.com/zend/controller/forwad/index2?lang=hoge などでアクセスする

Zend_Controller_Action::_forward($action, $ctrl, $module, $params);
  • $action -> アクション / $ctrl -> コントローラ名 / $module -> モジュール名 / $params -> パラメータ名

Module

モジュール単位で分割して管理するとよい

  • /appliction
    • /modules
      • /default
        /controllers
        ../IndexController?.php
        /models
        /views
      • /usr
        ../controllers
        ../models
        ../views
      • /sendmail
        ../controllers
        ../models
        ../views
      • other...
  • /html
    • .htaccess
    • index.php

モジュールを使用する場合、モジュール名と対応するモジュールフォルダのパスをフロントコントローラに設定する必要がある

setControllerDirectory? method

モジュール名=>コントローラフォルダの連想配列として指定

$front - Zend_Controller_Front::getInstance();
$front->setControllerDirectory(
 array(
  'default'=> APP.'/modules/default/controllers',
  'usr'=> APP.'/modules/usr/controllers',
  'sendmail' => APP.'/modules/sendmail/controllers'
 )
);

addControllerDirectory? method

すでにコントローラフォルダが指定されている所に追加でコントローラフォルダを追加できる

$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory(APP.'/modules/default/controllers');
$front->addControllerDirectory(APP.'/modules/usr/controllers', 'usr');
$front->addControllerDirectory(APP.'/modules/sendmail/controllers', 'sendmail');

第一引数にコントローラフォルダを、第二引数にモジュール名を入れることが出来る

adModuleDirectory? method

モジュールフォルダ命とモジュール名が同じな場合はaddModuleDirectory?メソッドを使うことも出来る

$front->addModuleDirectory(APP.'/modules');

これでmodules以下に配置されているmodules(usrやsendmailなど)はフォルダ名と同じモジュール名として登録される

アクションコントローラの命名規則

ファイル名クラス名.phpIndexController?.php
クラス名モジュール名_コントローラ名ControllerUsr_IndexController?
メソッド名アクション名ActionindexAction

View Controller

view 変数

$this->view->変数名 = 値;~

Zend_Viewによって書かれたView Scriptは拡張子が.phtmlになる
index.phtml

<html>
 <head>
  <title>View</title>
 </head>
 <body>
 <?php print($this->escape($this->result)); ?>
 </body>
</html>

※View変数経由で動的に出力する場合は、エスケープ処理を行う
Zend_Viewが持つescapeメソッドを使うとよい
view scriptファイルの配置場所は

application/views/scripts/コントローラー名/アクション名.phtml

実行URI

http://www.example.com/Zend/Controller/ctrl/action/param1/value1/param2/value2...
http://www.example.com/Zend/Controller/コントローラー名/アクション名/パラメータ名/値/
http://www.example.com/Zend/Controller/index/index
->index controllerのindex action
http://www.example.com/Zend/Controller/index/post
->index controllerのpost action

Zend_Db

共通

  • Zend_Db : Zend_Dbコンポーネントの中核

基本:

  • Zend_Db_Adapter_Abstract : データベースへの直接の操作を担当
  • Zend_Db_Statement : 発行するSQL命令を管理
  • Zend_Db_Select : SELECT 命令を動的に構築するための機能を提供

O/R マッピング

  • Zend_Db_Table : テーブルクラスの基底クラス
  • Zend_Db_Rowset : テーブルに属する行の集合(行セット)を管理
  • Zend_Db_Row : テーブルの各行の管理

その他

  • Zend_Db_Profile : 実行されたSQL命令、またその実行時間のプロファイル
PHP application  -> Zend_Db 
 ->Pdo_Mysql adapter -> MySQL
 ->Pdo_Pgsql adapter -> PostgreSQL
 ->Pdo_Oci adapter -> Oracle 
 ->その他 -> other..

Zend_Db対応しているデータベース

データベースアダプタ名依存モジュール
DB2Pdo_Ibmpdo_ibm
Db2ibm_db2
MySQLPdo_Mysqlpdo_mysql
Mysqlimysqli
SQL ServerPdo_Mssqlpdo_mssql
OraclePdo_Ocipdo_oci
Oracleoci8
PostgreSQLPdo_Pgsqlpdo_pgsql
SQLitePdo_Sqlitepdo_sqlite
<?php
require_once 'Zend_Db.php';

try {
	$db = Zend_Db::factory(
		'Pdo_Mysql',
		array(
			'host' => 'localhost',
			'username'=>'hoge',
			'password'=>'hogepw'
			'dbname'=>'zend'
		)
	); #この時点ではまだ接続は確定されていない

		$db->getConnection();
		print('データベース接続に成功しました');
	} catch (Zend_Exception $e) {
		die($e->getMessage());
	}
	$db->closeConnection(); #通常はスクリプト終了時に切断処理が行われるので書く必要はない
}

DB接続に関しての注意事項

  1. 接続に必要なモジュールが有効になっているか?
  2. データベースは起動しているか
  3. 対象のデータベースはあるか?

データベース接続情報を外部ファイルとして保持する

#hogehoge.ini
[database]
adapter = Pdo_Mysql
params.host = localhost
params.dbname = book
params.username = hoger
params.password = hogepw
#connect_ini.php
<?php
	require_once 'Zend/Config/Ini.php';
	require_once 'Zend/Db.php';
	try{
	$config = new Zend_Config_Ini('../hogehoge.ini', 'database');
	$db = Zend_Db::factory($config);
	$db->getConnect();
	print('データベース接続に成功しました');
	} catch (Zend_Exception $e ) {
		die($e->getMessage());
	}
	$db->closeConnection();
?>

Last-modified: 2012-03-12 (月) 17:05:33 (166d)