カテゴリー : framework

数値系のValidateの違い

数字系のValidateには、以下があります


・Zend_Validate_Digits

・Zend_Validate_Int

・Zend_Validate_Float

・Zend_Validate_LessThan

・Zend_Validate_GreaterThan

・Zend_Validate_Between


この中で、下の3つはクラス名からのイメージ通りなので割愛します。

Int、Floatもクラス名からイメージ通りなのですが、Digitsも含めて、

どういう風に判定結果が変わるのかを考えると、???となりました。私は。


調べてみたところ、こんな感じです。

・Digitsは、数字のみで構成されていること

・Intは、整数であること

・Floatは、整数または小数点を含む数値であること


これだけでは、まんまだねで終わるので、例で説明します


【例1 : 09022225555】

 Digits⇒○、Int⇒×、Float⇒×


【例2 : 0.01】

 Digits⇒×、Int⇒×、Float⇒○


【例3 : -1】

 Digits⇒×、Int⇒○、Float⇒○


【例4 : 2】

 Digits⇒○、Int⇒○、Float⇒○

Zend_Validate_NotEmptyの注意点

いまさらなんですが、気づいたのでメモしておきます。


Zend_Validate_NotEmptyですが、クラスの中ではphpのemptyメソッドを利用して

判定が行われているので、判定結果もemptyメソッドの処理結果と同様になります。


以前emptyメソッドではまったところなんですが、’0’は空と判定されるのです。

empty(‘0’)は true が判定結果として返されます。


入力チェックで、0 を許容したいところには、Zend_Validate_NotEmptyは使えません。


0 の1文字を許容するところは、数値の入力欄だと思うので、

Zend_Validate_Digitsを利用するといいです。

これは、クラス内で $value === ” という判定を行ってくれますので、

正確に空を判定することができます。

Zend_Db_Tableでのinsert方法の違い

Zend_Db_Tableクラスを使った行のinsert方法は2つ。


1. createRow()を使うもの

2. insertメソッドを使うもの

※$tblは、Zend_Db_Table_Abstractを継承したDbアクセスクラスです


1. はこんな感じ


$row = $tbl->createRow();

$row->password = xxx;

$row->create_on = new Zend_Db_Exp(‘now()’);

$row->save();


2. はこんな感じ


$params = array(

 ’password’ => ‘xxxx’,

 ’create_on’ => new Zend_Db_Exp(‘now()’)

);


$tbl->insert($params);


両者の違いは、設定しなかったカラムの処理方法にあります。

値を設定しなかったカラムに対して、1.はnullを設定し、2.は何も処理をしません。


これはどういうことかというと、1.の場合は、DB設定にてdefault値を設定しても、

行をinsertした後には、カラムの値はnullになっているということです。

これは、結構不便に感じます。


1.は更新時と書き方がほぼ一緒なので覚えやすいのですが、上記default値のことを考慮すると、

insertメソッドを使う方法が、予想外の問題が発生しにくいのではないかと思います。

ログインチェックをプラグインにて行う2

今回の認証クラスでは、DBを使って認証処理を行っています。

サンプルソースは以下になります。


説明を日本語で書くと、余計にわかりづらいくなってしまいましのたで、

コードとコメントを見て理解していただけたらと思います。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Zend_Loader::loadClass('Zend_DB_Table_Abstract');
Zend_Loader::loadClass('Zend_Auth_Adapter_DbTable');
Zend_Loader::loadClass('Zend_Auth_Storage_Session');
 
class authModel
{
 private $_authStorage;
 
 public function __construct()
 {
  $config = new Zend_Config_Ini('config/system.ini', 'default');
  // ログイン情報を格納するセッションを指定
  $this->_authStorage
   = new Zend_Auth_Storage_Session($config->session);
 }
 
 public function login($post)
 {
  $db = Zend_Db_Table_Abstract::getDefaultAdapter();
  $authAdapter = new Zend_Auth_Adapter_DbTable($db);
  $authAdapter->setTableName('Accounts')
         ->setIdentityColumn('login_id')   // IDカラムを指定
         ->setCredentialColumn('password'); // 認証用カラムを指定
 
  // 上記で指定したカラムに、認証したい値を設定
  $authAdapter->setIdentity($post['login_id']) 
        ->setCredential($post['password']); 
 
  // 認証実行
  $result = $authAdapter->authenticate();
 
  if ($result->isValid()){
   // 認証OKとなったレコードから、login_idとstatusを取りだす
   $row = $authAdapter->getResultRowObject(array(login_id, status));
   // ログイン情報格納用セッションに取得した情報を設定する
   $this->_authStorage->write($row);
  }
 
  return $result;
 }
 
 public function logout()
 {
  $this->_authStorage->clear();
 }
 
 public function isAuth()
 {
  return (isset($this->get()->login_id) && isset($this->get()->status));
 }
 
 public function get()
 {
  return $this->_authStorage->read();
 }
}



ログイン情報を設定するセッションに、デフォルト(Zend_Auth)を利用したり、

セッションに設定する情報が、認証に利用したID(上記だとlogin_id)だけでいい場合は、

より簡潔に記述することができます。


デフォルトのセッションを利用する場合は、コンストラクタ内の処理は必要ありません。

セッションに設定する情報が、認証に利用したIDのみでいい場合は、

認証処理を実行してOKだった場合に、自動的に設定されていますので、

わざわざ設定する処理を記述する必要はありません。

ログインチェックをプラグインにて行う

今回は、会員サイト等でよく使うログイン状態チェックを、

プラグインで実現するためのクラスを作りました。


ログイン状態チェックは、ログイン画面以外では必ず必要で、

しかも通常の処理(データ登録、参照等)とは関連しないので、

プラグインにするのに、うってつけだと思ったのです。

サンプルソースは以下になります。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Zend_Loader::loadClass('Zend_Controller_Plugin_Abstract');
Zend_Loader::loadClass('Zend_Session');
Zend_Loader::loadClass('Zend_Controller_Action_Helper_Redirector');
 
require_once('models/authModel.php');
 
class Zend_Controller_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
 public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
 {
   Zend_Session::start();
 
   $auth = new authModel();
 
   $controller = $request->getControllerName();
   $action   = $request->getActionName();
 
   if (($controller == 'index') && ($action == 'index'))
   {
    // ログイン画面の場合は、認証情報削除
    $auth->logout();
   }else{
    if (!$auth->isAuth()){
     // 認証エラーの場合は、認証情報を削除し、ログイン画面へ
     $auth->logout();
     $helper = new Zend_Controller_Action_Helper_Redirector();
     $helper->gotoUrl('/');
    }
   }
 }
}



この例では、http://test.com/にログイン画面があることを想定しています。

そのため、コントローラー名、アクション名がindexの場合は、

一旦、保持しているログイン状態を破棄しています。


今回は、DBデータに問い合わせる方法で、ログイン認証を行い、

ログインOKの場合は、ログイン情報(login_id等)を

セッションに保持するというサンプルソースを作りました。

そのため、このプラグインの中で、Zend_Session::start()も実行しています。


authModelは、認証系の処理を集めたモデルクラスです。

これについては、また後日サンプルソースを公開します。

DBアダプタ作成処理をプラグインにて行う

Dbハンドラの生成をmodelクラスで行っていたのですが、

複数のモデルクラスを使う処理の場合もあるので、どこか1か所に

生成処理をまとめられないかなと思って、たどりついたのがプラグインでした。


ソースは、以下


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Zend_Loader::loadClass('Zend_Controller_Plugin_Abstract');
 
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Db_Table_Abstract');
Zend_Loader::loadClass('Zend_Config_Ini');
 
class Zend_Controller_Plugin_DbAdapter extends Zend_Controller_Plugin_Abstract
{
 public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
 {
  // DBアダプタ生成
  $config = new Zend_Config_Ini('config/system.ini', 'default');
  $db = Zend_Db::factory($config->database->adapter,
              $config->database->params->toArray());
  $db->setFetchMode(Zend_Db::FETCH_ASSOC);
 
  // Db Tableクラス利用DBアダプタ設定
  Zend_Db_Table_Abstract::setDefaultAdapter($db);
 }
}



こうやっておけば、どこのクラスでも


1
2
3
Zend_Loader::loadClass('Zend_Db_Table_Abstract');
 
$db = Zend_Db_Table_Abstract::getDefaultAdapter();



とすると、Dbアダプターが取得できます。

Dbアダプターを作成するモデルクラスを基底クラスとして、作っていたのですが、

こちらの方が全然いいなと思いました。


プラグインを有効にするには、フロントコントローラに登録する必要があります。

index.phpで以下の行が必要です。


1
2
3
4
require_once('Custom/Controller/Plugin/DbAdapter.php');
 
$front = Zend_Controller_Front::getInstance();
$front->registorPlugin(new Zend_Controller_Plugin_DbAdapter());



プラグインで、ログイン状態判定もできそうだなと思っています。

Zend_ViewでSmartyをラップする6

今回は、やりたいことの2つ目、3つ目に入っていた
2.プログラムが必要ない場合は、Actionコントローラーを書きたくない
 (Actionメソッドがなくても、テンプレートが表示されるようにしたい)
3.テンプレートもないURLが指定されたら、トップページなど指定のURLに遷移させたい
を実現する方法です。

Zendは、初期状態で、ErrorHandlerプラグインというプログラムが有効になっています。
これは、プログラム実行中に、エラーが発生した場合、
ErrorActionコントローラーのerrorActionというメソッドをよびだしてくれます。

そこで、コントローラークラスが見つからなかった場合、
アクションメソッドが見つからなかった場合の判別が可能です。
私が作った、ErrorActionクラスから必要な部分を抜き出したのが以下です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class ErrorController extends Zend_Controller_Action
{
 public function errorAction()
 {
  $errors = $this->_getParam('error_handler');
 
  switch ($errors->type)
  {
   case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
    if ($this->_getParam('action') == 'index')
    {
     $view = $this->getHelper('viewRenderer');
     $view->setNoController()
         ->setScriptAction($this->_getParam('controller'));
    }
 
   case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
    if (!isset($view))
    {
     $view = $this->getHelper('viewRenderer');
     $this->getRequest()->setControllerName($this->_getParam('controller'));
     $this->getRequest()->setActionName($this->_getParam('action'));
    }
 
    $template = $view->getViewBasePathSpec() . $view->getViewScript();
    if (!is_readable($template)) $this->_redirect('/');
    break;
 
   default:
    break;
  }
 }
}

Zend_ViewでSmartyをラップする5

前回で、Smartyの利用と、ViewRendererヘルパーを利用して、

Smartyを利用した画面の自動描画が有効になる方法を紹介しました。


今回は、やりたいことの1つ目にあげていた

1.テンプレートの配置をURLからイメージしやすいようにしたい

ということを実現する方法です。


この方法を実行するのは、各コントローラーのindexActionのみです。

そこで、このどちらかを記述すればOKです。


1
2
3
$this->getHeler('viewRenderer')
   ->setNoController()
   ->setScriptAction($this->getRequest()->getControllerName());



または


1
$this->render($this->getRequest()->getControllerName(), null, true);



これはどちらも同じ意味になります。


こうすることで、

http://test.com/aaa/ というURLでアクセスされた場合、

templates/aaa/index.htmlではなく、templates/aaa.htmlを読み込んでくれます。

Zend_ViewでSmartyをラップする4

前回の記事で書いたことを試してみました。

私がsmartyとZendを合わせて使う上で、実現したいのは以下


1.テンプレートの配置をURLからイメージしやすいようにしたい

 http://test.com/aaa/ の場合は、templates/aaa.html

 http://test.com/aaa/bbb/の場合は、templates/aaa/bbb.html


2.プログラムが必要ない場合は、Actionコントローラーを書きたくない

 (Actionメソッドがなくても、テンプレートが表示されるようにしたい)


3.テンプレートもないURLが指定されたら、トップページなど指定のURLに遷移させたい


1.は、renderのnoControllerがtrueのときのテンプレート作成ルールを、

コントローラー名+指定拡張子とすることで解決。

ただし、render呼び出しの際に、

$this->render(コントローラー名, null, true)

とする必要がありますが、この部分を簡略化できないかが今後の課題です。


2.はまだ試せてません。しかし、前々回の記事の方法が応用できそうです。

3.も2.と同様に前々回の記事の方法で実現できそうです。


しかし、前回と同様の方法だと、Zend_Controller_Actionのサブクラスを基底クラスとして

作成することになるので、これはできれば避けたいところです。

会員サイトとかなら、基底クラス作るのはいいのですが、Smarty使いたいだけで、

基底クラスを作るとなると、ログインセッション管理をやろうと思ったときに、

テンプレートエンジンに関わるファイルを修正することになりかねません。


index.phpにつぎたした部分は以下です。


1
2
3
4
5
6
7
8
9
require_once('Zend/Controller/Action/Helper/ViewRenderer.php');
require_once('Custom/View/Smarty.php');
 
$view = new Zend_View_Smarty(null, $smartyConfig);
 
$viewHelper = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewHelper->setViewBasePathSpec($smartyConfig['template_dir'])
      ->setViewSuffix('html');
Zend_Controller_Action_HelperBroker::addHelper($viewHelper);



$smartyConfigは、Smartyの設定値の配列です。

Custom/View/Smarty.phpは、Zend_View_Interfaceに沿って、

Smartyが使えるようにしたViewクラスです。

中身は、ここの最後の方にのっているSmartyラッパークラスと同様です。

ただ、function getScriptPaths()に誤りがあります。


1
2
3
return $this->_smarty->template_dir;
  ↓
return array($this->_smarty->template_dir);


とする必要があります。

getScriptPaths()なので、パスが配列で複数取得されることが想定されて、

Zend_Controller_Action_Helper_ViewRendererが作成されているためです。


これでより少ないソースで、smartyと連携できるようになりました。

より手間を少なくする方法がないか、もうちょっと試してみる予定です。

ViewRendererヘルパーと、ErrorHanderプラグインあたりを組み合わせると、

なんとかなりそうな気がドキュメントを読んでいるとするのですが、どうなんでしょう。

あたりがついたら、試してみます。

Zend_ViewでSmartyをラップする3

昨日、ActionコントローラのinitViewをオーバーライドが簡単って

書いたばかりですが、こんなドキュメントを見つけました。

別件でヘルパーかプラングインを作ってみようとしてたときです。


ここの【例 7.10. パスの指定方法の変更】の部分です。


テンプレートエンジンをSmartyにするだけなら、これがより簡単です。

見つけたとき、軽く衝撃でした。


Smartyを使いつつ、私がやりたいこと(現在の方法で実現していること)が

この方法を使ったときに実現できて、かつ簡単なら乗り換えようかと。


結果は、またこのブログに書きたいと思います。

%d人のブロガーが「いいね」をつけました。