2010年2月22日

Zend_Controller_Router_Route_Regexで正規表現によるルーティング設定を行う

カテゴリー: ZendFramework — admin @ 1:35 AM

以下のように、Zend_Controller_Router_Route_Regexを使用する。

$front->getRouter()->addRoute(
	'page',
	new Zend_Controller_Router_Route_Regex(
		'page_(\d+)\.html',
		array(
			'controller' => 'Index',
			'action'     => 'page'
		),
		array(
			1 => 'pageid'
		)
	)
);

Actionからは以下のコードでマッチした部分を参照できる。

$this->_getParam('pageid');

2010年2月14日

ZendFrameworkでコマンドラインからアクションを実行する

カテゴリー: PHP, ZendFramework — admin @ 11:56 PM

コマンドラインにおけるオプションの設定・取得。|の後がエイリアス名、=の後の文字列で型を指定できる。

try {
    $options = new Zend_Console_Getopt(
        array(
            'help|h'        => 'help.',
            'zfm|m=s'       => 'module',
            'zfc|c=s'       => 'controller',
            'zfa|a=s'       => 'action'
        )
    );
    $options->parse();
}
catch(Zend_Console_Getopt_Exception $e){
    die($e->getMessage() . ' : ' . $e->getUsageMessage());
}

Zend_Controller_Request_Simpleがポイント。アクション、コントローラ、モジュールを引数に指定してリクエストオブジェクトを取得する。

if(isset($options->zfa) && isset($options->zfc) && isset($options->zfm)){
    $request = new Zend_Controller_Request_Simple(
        $options->zfa,
        $options->zfc,
        $options->zfm
    );
    $front = Zend_Controller_Front::getInstance();
    $front->setRequest($request);
    $front->setRouter(new Custom_Controller_Router_Cli());
    $front->setResponse(new Zend_Controller_Response_Cli());
    $front->throwExceptions(true);
    $front->addModuleDirectory(dirname(__FILE__) . '/application/modules');
    $front->dispatch();
}

Custom_Controller_Router_Cliはこんな感じ。

<?php
require_once 'Zend/Controller/Router/Interface.php';
require_once 'Zend/Controller/Router/Abstract.php';

class Custom_Controller_Router_Cli extends Zend_Controller_Router_Abstract implements Zend_Controller_Router_Interface
{
    public function assemble($userParams, $name = null, $reset = false, $encode = true) {}
    public function route(Zend_Controller_Request_Abstract $dispatcher) {}
}

基本的には以上で実行できるが

■アクセスコントロールの設定

アクセスコントロールを行っている場合は上述のコードよりも先にアクセスできるようにしなければならない。以下は一例。

$sesion = new Zend_Session_Namespace('global');
$sesion->userLevel = 'admin';
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('guest'));
$acl->addRole(new Zend_Acl_Role('admin'), 'guest');
$acl->add(new Zend_Acl_Resource('guestPage'));
$acl->add(new Zend_Acl_Resource('adminPage'));
$acl->allow('guest');
$acl->allow('admin');
$acl->deny('guest', 'adminPage');
$acl->allow('admin', 'adminPage');
Zend_Registry::set('acl', $acl);

基本的には一般ユーザが閲覧(実行)できる場所に、このファイルを配置するのは良くない。

2010年1月12日

ZendFrameworkビュースクリプトでのbodyタグ

カテゴリー: CSS, PHP, ZendFramework, ブラウザ — admin @ 2:19 AM

以下のように記述するとcssで装飾しやすい気がする。

■コントローラ

public function init(){
    $this->_view->module     = $this->_getParam('module');
    $this->_view->controller = $this->_getParam('controller');
    $this->_view->action     = $this->_getParam('action');
}

■ビュー

<body class="<?php print($this->controller); ?>" id="<?php print($this->controller); ?>_<?php print($this->action); ?>">

ちなみに以下のようになっている。

print($this->module);//モジュール名
print($this->controller);//コントローラ名
print($this->action);//アクション名

出力例

<body class="category" id="category_register">

参考

以下の例の場合を考えてみる。

<body class="<?php print($this->module); ?> <?php print($this->controller); ?> <?php print($this->action); ?>">
出力例
<body class="category" id="category_register">

一見素晴らしいが、IEが以下のセレクタに対応していないため使用できない。

body.admin.category.register {
	background-color: red;
}
body.register {
	background-color: blue;
}

上述のように記述するとIE6のみbodyの背景色がblueになるはずだ。

2010年1月10日

Zend_Exceptionのメソッド

カテゴリー: ZendFramework — admin @ 3:48 AM

以下の通り。

array(10) {
  [0] => &object(ReflectionMethod)#54 (2) {
    ["name"] => string(7) "__clone"
    ["class"] => string(9) "Exception"
  }
  [1] => &object(ReflectionMethod)#55 (2) {
    ["name"] => string(11) "__construct"
    ["class"] => string(9) "Exception"
  }
  [2] => &object(ReflectionMethod)#56 (2) {
    ["name"] => string(10) "getMessage"
    ["class"] => string(9) "Exception"
  }
  [3] => &object(ReflectionMethod)#57 (2) {
    ["name"] => string(7) "getCode"
    ["class"] => string(9) "Exception"
  }
  [4] => &object(ReflectionMethod)#58 (2) {
    ["name"] => string(7) "getFile"
    ["class"] => string(9) "Exception"
  }
  [5] => &object(ReflectionMethod)#59 (2) {
    ["name"] => string(7) "getLine"
    ["class"] => string(9) "Exception"
  }
  [6] => &object(ReflectionMethod)#60 (2) {
    ["name"] => string(8) "getTrace"
    ["class"] => string(9) "Exception"
  }
  [7] => &object(ReflectionMethod)#61 (2) {
    ["name"] => string(11) "getPrevious"
    ["class"] => string(9) "Exception"
  }
  [8] => &object(ReflectionMethod)#62 (2) {
    ["name"] => string(16) "getTraceAsString"
    ["class"] => string(9) "Exception"
  }
  [9] => &object(ReflectionMethod)#63 (2) {
    ["name"] => string(10) "__toString"
    ["class"] => string(9) "Exception"
  }
}

2009年9月28日

ZendFramework Zend_Uri

カテゴリー: ZendFramework — admin @ 10:52 PM

以下のようにすると文字列がURIとして妥当かどうか検証できる。

<?php
require_once 'Zend/Uri.php';

$uri = 'http://example.org';
if(Zend_Uri::check($uri)){
    //this is valid as a uri
}
else{
    //this is not valid as a uri
}

各メソッドについて

bool Zend_Uri::check(string $url)
与えられた文字列がURIとして適当か判定する。

2009年9月28日

ZendFramework Zend_Validate(バリデート)

カテゴリー: ZendFramework — admin @ 7:02 PM

■バリデート

IPアドレスかどうか判定するには以下のようにする。

<?php
require_once 'Zend/Validate/Ip.php';

$validator = new Zend_Validate_Ip();
if($validator->isValid('192.168.1.1')){
    //this is an IP address.
}
else{
    //this is not an IP address.
}

指定された範囲にあるかどうかを判定するには以下のようにする。

<?php
require_once 'Zend/Validate/Between.php';

$validator = new Zend_Validate_Between(10, 20);
if($validator->isValid(15)){
    //this is in the range.
}
else{
    //this is not in the range.
}

■メッセージの設定と取得

以下のようにバリデータオブジェクトにメッセージを付加することができる。

<?php
require_once 'Zend/Validate/Between.php';

$validator = new Zend_Validate_Between(10, 20);
$valiidator->setMessage('%value% is not in the range.');
if($validator->isValid(35)){
    //this is in the range.
}
else{
    $msg = $validator->getMessages();
    echo $msg[0];//35 is not in the range.
}

■バリデータチェーン

以下のようにして複数のバリデートを1つに扱うことができる。

<?php
require_once 'Zend/Validate.php';
require_once 'Zend/Validate/NotEmpty.php';
require_once 'Zend/Validate/Alpha.php';
require_once 'Zend/Validate/StringLength.php';

$validator_emp = new Zend_Validate_NotEmpty();
$validator_alp = new Zend_Validate_Alpha();
$validator_str = new Zend_Validate_StringLength(4, 10);

$validator_emp->setMessage('アカウント名が入力されていません。');
$validator_alp->setMessage('アカウント名は半角英数字のみで入力してください。');
$validator_str->setMessage('アカウント名は4~10文字で入力してください。');

$validChain = new Zend_Validate();
$validChain->addValidator($validator_emp, true)->addValidator($validator_alp)->addValidator($validator_str);

if(!$validChain->isValid($name)){
    $messages = $validChain->getMessages();
    foreach($messages as $msg){
        echo $msg;
    }
}

各コンポーネントについて

Zend_Validate_Alnum([bool $allowWhiteSpace = false])
英数字のみで構成されているか判定する。引数がtrueのときは空白を許可する。
Zend_Validate_Apha([bool $allowWhiteSpace = false])
アルファベットのみで構成されているか判定する。引数がtrueのときは空白を許可する。
Zend_Validate_Between(int $min, int $max[, bool $inclusive = true])
指定された範囲内かどうか判定する。第三引数がfalseのとき、境界値は含まない。
Zend_Validate_Ccnum()
クレジット番号として適当かどうか判定する。
Zend_Validate_Date([string $format = 'YYYY-MM-DD'[, string $locate]])
日付として正しい形式か判定する。
Zend_Validate_Int()
整数型か判定する。
Zend_Validate_Float()
浮動小数点型か判定する。
Zend_Validate_InArray(mixed $value, array $haystack[, bool $strict = false])
設定した配列の中に指定のキーが存在するか判定する。第三引数がtrueのとき型の一致も判定する。
Zend_Validate_EmailAddress([$allow[, $validateMx[, $hostnameValidator]]])
メールアドレスとして適当か判定する。標準ではDNSのホスト名として正しいアドレスであるかを調べる。
Zend_Validate_HostName([$allow[, $validateIdn[, $validateTld[, $ipValidator]]]])
ホスト名として適当か判定する。標準ではDNSホスト名として有効かのみ調べる。
Zend_Validate_Ip()
IPアドレスとして適当か判定する。
Zend_Validate_Regex(string $pattern)
設定した正規表現にマッチするか判定する。

クレジット番号のような判定には便利だがPHPの関数のエイリアスのようなものはいかがであろう。。。

各メソッドについて

Zend_Validate_[TYPE]::isValid(mixed $subject)
引数が適合しているか判定する。
Zend_Validate_[TYPE]::setMesssage(string $msg[, $error_code])
メッセージを設定する。
Zend_Validate_[TYPE]::getMesssages()
メッセージを取得する。
Zend_Validate::addValid(object $validator[, bool $stop = false])
Zend_Validateオブジェクトにバリデータを付加する。第二引数でtrueを指定すると適合しなかった場合に残りの処理を行わない。

Zend Frameworkのrequire_onceがJavaのimportみたいで気持ちいい。

2009年9月28日

ZendFramework Zend_Feed(フィード)

カテゴリー: ZendFramework — admin @ 6:05 PM

以下のようにフィードを取得することができる。

<?php
require_once 'Zend/Feed.php';

try{
    $feed = Zend_Feed::import('http://example.org/rss.xml');
}
catch(Zend_Feed_Exception $e){
    die('eror');
}
if(get_class($feed) === 'Zend_Feed_Rss'){
    $channel = array(
        'site_title' => $feed->title(),
        'site_url' => $feed->title(),
        'site_description' => $feed->description()
    );
    $entries = array();
    foreach($feed as $item){
        $entries[] = array(
            'article_title' => $item->title(),
            'article_category' => $item->category(),
            'article_author' => $item->creator(),
            'article_url' => $item->link(),
            'article_content' => $item->description(),
            'article_update' => $item->pubDate()
        );
    }
}
else{
    $channel = array(
        'site_title' => $feed->title(),
        'site_url' => $feed->link('alternate'),
        'site_description' => $feed->tagline()
    );
    $entries = array();
    foreach($feed as $item){
        $entries[] = array(
            'article_title' => $item->title(),
            'article_category' => $item->subject(),
            'article_author' => $item->author->name(),
            'article_url' => $item->link('alternate'),
            'article_content' => $item->content(),
            'article_update' => $item->modified()
        );
    }
}

2009年9月28日

ZendFramework Zend_Debug, Zend_Log, Zend_Exception(デバッグ、ログ、例外)

カテゴリー: ZendFramework — admin @ 1:04 AM

■Zend_Debug

require_once 'Zend/Debug.php';

$str = 'this is a sample!'
Zend_Debug::dump($str);

■Zend_Log

長期にわたって監視したい場合に有効である。

require_once 'Zend/Log.php';
require_once 'Zend/Log/Writer/Stream.php';

$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('/path/to/log.txt');
$logger->addWriter($writer);

DBにログを書き込みたい場合は以下のようにする。

require_once 'Zend/Log.php';
require_once 'Zend/Log/Writer/Db.php';
require_once 'Zend/Db.php';

$dbh = Zend_Db::factory(
    'Pdo_Mysql',
    array(
        'host' => 'localhost',
        'username' => 'user',
        'password' => 'pass',
        'dbname' => 'dbname'
    )
);
$dbh->query("SET NAMES 'utf8'");

$logger = new Zend_Log();
$writer = new Zend_Log_Writer_DB(
    $dbh,
    'table_log',
    array(
        'level' => 'priority',
        'priority' => 'priorityName',
        'msg' => 'message',
        'register_date' => 'timestamp'
    )
);
$logger->addWriter($writer);

上述の場合、既にDBにtable_logテーブルが存在し、カラム(level,priority,msg,register_date)が作られている前提である。

実用例

以下のようにすると警告以上のメッセージしか記録されない。

require_once 'Zend/Log.php';
require_once 'Zend/Log/Writer/Stream.php';

$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('/path/to/log.txt');
$logger->addWriter($writer);
$writer->addFilter(Zend_Log::ERR);

$logger->log('システム使用不可' , Zend_Log::EMERG);
$logger->log('至急対応が必要' , Zend_Log::ALER);
$logger->log('危機的な状況' , Zend_Log::CRIT);
$logger->log('エラー' , Zend_Log::ERR);
$logger->log('警告' , Zend_Log::WARN);
$logger->log('注意' , Zend_Log::NOTICE);
$logger->log('情報' , Zend_Log::INFO);
$logger->log('デバッグメッセージ' , Zend_Log::DEBUG);

■Zend_Exception

ZendFrameworkでは全ての例外がZend_Exceptionを継承している。

<?php
require_once 'Zend/Db.php';
try{
    $dbh = Zend_Db::factory(
        'Pdo_Mysql',
        array(
            'host' => 'localhost',
            'username' => 'name',
            'password' => 'pass',
            'dbname' => 'dbname'
        )
    );
}
catch(Zend_Db_Adapter_Exeption $e){
    //failed to connect because of invalid user or db switch in the off position
}
catch(Zend_Exception $e){
    //failed to load the class file
}

各メソッドについて

Zend_Debug::dump(mixed $variable[, string $caption[, bool $isDisplayed]])
第一引数の内容を第二引数のキャプションをつけて表示する。第三引数がfalseの場合は値を文字列として返します。
Zend_Log::__construct(void)
ログオブジェクトを生成する。
Zend_Log_Writer_Stream::__construct(string $path_to_txt);
第一引数にファイルのパスを指定し書込オブジェクトを生成する。
Zend_Log_Writer_DB::__construct(resource $dbh, string $table_name, array $dbcolumn_for_log);
第一引数にDBハンドラを、第二引数にテーブル名を、第三引数にテーブルのカラムをキーにした連想配列を指定し書込オブジェクトを生成する。
Zend_Log::addWriter($writer);
ログオブジェクトに引数の書込オブジェクトを付加する。
Zend_Log_Writer_Stream::addFilter(int $error_level)
第一引数で指定したレベルでフィルタリングする。

2009年9月27日

ZendFramework Zend_Config(設定情報)

カテゴリー: ZendFramework — admin @ 11:32 PM

symfonyのymlは個人的にはどうも…という事でZend_Configを触ってみる。

■iniファイルのconfig

;config.ini
;preference information

[global]
domain_name = example.org
ip_address = 192.168.2.2
root_path = /home/admin

[database]
database.type = pdo_mysql
database.host = localhost
database.username = name
database.password = pass
database.dbname = dbname

プログラム中での使用

<?php
require_once 'Zend/Config/Ini.php';

$config = new Zend_Config_Ini('/path/to/config.ini', 'global');
$config->domain_name;// example.org
$config->root_path;// /home/admin
$config->database->username// null

各メソッドについて

Zend_Config_Ini Zend_Config_Ini(string $path_to_config, array $sections[,array $mode])
第一引数で指定したiniファイルを読み込んで第二引数のセクションのみインスタンスに格納する。第二引数にnullを設定すると全てのセクションを読み込む。セクションが1つのときは文字列で指定することも可能である。また第三引数では書き込みを許可することもできる。

2009年9月27日

ZendFramework Zend_Acl(アクセスコントロール)

カテゴリー: ZendFramework — admin @ 11:00 PM

■Zend_Acl

リソース
アクセス制御対象オブジェクト
ロール
リソースにアクセスを要求するオブジェクト

ロールの定義

require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('guest'));
$acl->addRole(new Zend_Acl_Role('member'), 'guest');
$acl->addRole(new Zend_Acl_Role('admin'), 'member');

アクセス制御の定義

以下のようにしてロールにアクセス制御

$acl->allow('guest', null, 'view');
$acl->allow('member', null, 'entry');
$acl->allow('admin', null, array('edit', 'delete'));

アクセス制御

if($acl->isAllowed('guest', null, 'view')){
    //code
}
else{
    //code
}
if($acl->isAllowed('member', null, 'delete')){
    //code
}
else{
    //code
}

実例

require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';
require_once 'Zend/Acl/Resource.php';

$acl = new Zend_Acl();

$acl->addRole(new Zend_Acl_Role('guest'));
$acl->addRole(new Zend_Acl_Role('member'), 'guest');
$acl->addRole(new Zend_Acl_Role('admin'), 'member');

$acl->add(new Zend_Acl_Resource('myPage'));

$acl->allow('guest', null, 'view');
$acl->allow('member', null, 'entry');
$acl->allow('admin', null, array('edit', 'delete'));

$acl->deny('guest', 'myPage', 'view');
$acl->allow('member', 'myPage', 'view');

if($acl->isAllowed('guest', 'myPage', 'view')){
    //allow
}
else{
    //deny
}
if($acl->isAllowed('member', 'myPage', 'view')){
    //allow
}
else{
    //deny
}

各メソッドについて

Zend_Acl::addRole(new Zend_Acl_Role(string $rolename)[, string $inheritance])
第一引数で指定したロール名でロールを定義する。第二引数があった場合はそのロールを継承する。
Zend_Acl::allow(string $rolename, string $resource, string $restrict)
第一引数のロールに対して第三引数のアクセス制御を定義する。
bool Zend_Acl::isAllowed(string $rolename, string $resourcename, string $restrict)
第一引数のロールに対して第三引数のアクセス制御名でアクセス許可があるかをbool値で返す。
次ページへ »