Posts tagged PHP

CakePHP モデルの validation の拡張 同じ項目で違うメッセージを出す

1

CakePHP のモデルの validation の拡張のメモの続きです。

同じフォームの項目で違うエラーメッセージを出したいときがあります。
例えばユーザ登録フォームでユーザID がフォーマットエラーなのか、既に使用されているのかなどです。

models/users.php

var $validate = array(
        'loginid' => '/^[0-9a-zA-Z]{8}$/',
    );

function validates($data=array()) {
        if(empty($data)) {
            $data = $this->data;
        }

        parent::validates($data);

        // loginid のユニークチェック
        if ($this->findByLoginid($data["User"]["loginid"])) {
            $this->invalidate("loginid_unique");
        }

        if (count($this->validationErrors)>0) {
            return false;
        } else {
            return true;
        }
}

既にloginid が登録済みの場合は
$this->invalidate('loginid_unique');
としています。
invalidate に指定するのは実際に存在しないものでも大丈夫なのでそれを使用して view でエラーメッセージを分けて表示します。

views/users/regist.thtml

ID:< ?php echo $html->password('User/loginid'); ?>
< ?php echo $html->tagErrorMsg("User/loginid", "IDは英数字8文字で入力してください"); ?>
< ?php echo $html->tagErrorMsg("User/loginid_unique", "IDは既に使用されています。他のID を指定してください"); ?>

CakePHP モデルの validation の拡張

1

CakePHP のモデルの validation の拡張のメモです。

ユーザ登録フォームなどでパスワードの再確認のバリデーションを行うときの方法です。

views/users/regist.thtml

パスワード:< ?php echo $html->password('User/password'); ?>
確認用パスワード:< ?php echo $html->password('User/password2'); ?>
< ?php echo $html->tagErrorMsg('User/password2', 'パスワードが一致しません');

※users テーブルにpassword2 のカラムはなくてかまいません。

models/users.php

function validates($data=array()) {
        if(empty($data)) {
            $data = $this->data;
        }

        parent::validates($data);

        if ($data["User"]["password"]!==$data["User"]["password2"]) {
            $this->invalidate("password2");
        }

        if (count($this->validationErrors)>0) {
            return false;
        } else {
            return true;
        }
}

AppModel クラスの validation メソッドも実行する必要があるので、必ず
parent::validates($data);
を書かないといけません。

CakePHP ログ出力

2

CakePHP でログ出力させるメモです。

$this->log(ログに出力するメッセージ, ログ種別);
出力するメッセージは文字列でも配列でもかまいません。配列の場合は print_r されたものが出力されます。
ログの種別は LOG_DEBUG で debug.log 、 LOG_ERROR で error.log に出力されます。デフォルトは LOG_ERROR です。

ログファイルは LOGS で指定されたディレクトリへ出力されます。
デフォルトは /app/tmp/logs です。
ただこの定数 LOGS は cake/config/paths.php で指定されているので、app/config/core.php で定義されている定数のように気軽に変更しない方がいいかもしれません。

ログファイルが存在しない場合はファイルを作成してくれます。

出力されるログは下記のようになります。
2007-11-11 06:54:54 Error: メッセージ
LOG_DEBUG を指定するとログの “Error” の部分が “Debug” になります。

この log メソッドは Object クラスにあります。Object クラスは CakePHP の全てのクラスで継承されるクラスなので、コントローラ、モデル、ビューどこからでも $this->log() でログに出力させることができます。

CakePHP findBy での複数指定を調べたメモ

2

先のエントリで書いた「CakePHP findBy で複数条件の指定で OR も指定可能」ですが、findByHogeAndFoo などの処理がどうなっているか気になったので調べたときのメモです。

  • findByHogeAndFoo メソッドが実行されると model_php5.php ( Model クラス ) の __call メソッドが実行される
  • __call メソッドでは DboSource クラスの query メソッドに findByHogeAndFoo のメソッド名と条件の値を渡す
  • DboSource クラスの query メソッドでは、findBy または、findAllBy の後ろの文字列を取り出す
  • 取り出した文字列を小文字に変換してさらに AND を _and_、OR を _or_ に変換する
  • _or_ または _and_ で分割してフィールドを取り出す
  • AND または OR にしたがって SQL の条件を組み立てる

というようなこと処理がされていました。
まとめると

  • 複数指定はいくつでも可能
  • AND または OR は混在して指定はできない

いくつでも指定はできるようですが、たくさんの条件をこれで指定するとソースの可読性が下がりそうですし、AND と OR が混在できないので普通はそんな指定はしないでしょう。
指定する場合は2つくらいにとどめておいて、それより多くなる場合は find の $conditions で指定した方が無難だと思います。

CakePHP findBy で複数条件の指定で OR も指定可能

2

[cakephp]findByで複数条件の指定 | blog.hereticsintheworld
で紹介されていた
$this->Model->findByIdAndName( $id, $name )
が気になりソースを調べてみたところ OR も指定可能でした。
$this->Model->findByIdOrName( $id, $name )
ちなみに findAll でも同様に指定可能です。

CakePHP 管理画面を作成する方法

2

CakePHP で管理画面を作成する方法です。
管理画面も CakePHP では簡単に作成することができます。

設定

/app/config/core.php の下記のコメントアウトをはずします。
define('CAKE_ADMIN', 'admin');
これで http://www.example.com/admin/controller/action という URL でアクセスできるようになります。
CAKE_ADMIN の値を変更すれば URL の /admin/ の値が変わります。

コントローラ

管理画面で使用するコントローラに管理画面用のアクションを追加します。
管理画面用のアクション名は admin_index のように admin_ が付きます。
この ‘admin’ の部分も CAKE_ADMIN によって変わります。

ビュー

管理画面用のアクションで表示するデフォルトのビューはアクション名と同じです。admin_index.thtml のように admin_ を付けます。

レイアウト

ユーザサイドの画面レイアウトと管理画面はレイアウトが違うことが多いかと思います。管理画面用のレイアウトを admin.thtml のように views/layouts/ に作成します。

管理画面へのアクセス時の共通処理

管理画面のアクセス時の共通処理として、アクセス制限をしたり、画面レイアウトの変更などがあります。
個別にアクションに追加してもいいのですが漏れなどがあるとまずいのでコントローラの beforeFilter メソッドを使用するといいかと思います。
管理画面で使用するコントローラ全てに共通して処理させるために、 /app/app_controller.php の beforeFilter に処理を追加します。
http://www.example.com/admin/contoller/action にアクセスすると
$this->params['admin'] = 'admin'
がセットされます。管理者用URL かどうかにはこれを使用します。また、’admin’ の値は CAKE_ADMIN で指定した値になります。たとえば CAKE_ADMIN を hoge にすると
$this->params['hoge'] = 'hoge'
になります。

if (defined('CAKE_ADMIN') && !empty($this->params[CAKE_ADMIN])) {
    // 管理者用のレイアウトを指定
    $this->layout = "admin";
    // 管理者用ログインチェックなどを行う
}

CakePHP 静的なページの作成方法

2

CakePHP で静的なページを作成する方法です。
正確には CakePHP が出力するページなので静的ではなく動的なのですが、ページを簡単に作成することができます。

  • 出力するページをテンプレートとして /views/pages/ ディレクトリ以下に作成します。
  • 作成したテンプレートが hoge.thtml だとすると http://exmaple.com/pages/hoge でアクセスできます。

これだけで簡単にページを追加することができます。
コンテンツは静的なものですが、ビューなので例えばログイン状態によって表示を変更したりなどできますね。

なぜ /pages/hoge でアクセスできるかというと /app/config/routes.php
$Route->connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
と定義されているからです。
pages_controller.php/cake/libs/controller/pages_controller.php にあります。
上のルーティングで pages コントローラへのアクセスは全て pages コントローラの display アクションに渡されます。

また、/views/pages/hoge/foo/fuga.thtml というテンプレートを作成すると
http://example.com/pages/hoge/foo/fuga という URL でアクセスすることができます。

ちなみにページタイトルはテンプレートの名前が title タグに入れられます。
タイトルを指定する場合は
<? $this->pageTitle = 'ここにタイトルを指定する'; ?>
とビューでタイトルを指定します。

参考サイト:21 things I learned about CakePHP – Avatar Financial Group

CakePHP select タグの選択していないときの状態を指定する

0

Cute CakePHP Trick of the Day – GenerateList Empty Slot In List | Web Development 2.0: Web Design, CakePHP, Javascript
で select タグの選択していないときの状態の値を指定する方法が書かれていますが、この方法は間違っています。

元のエントリのコメントでも指摘されていますが、ヘルパーのメソッドの使い方が違います。コードを実際に書いて検証してみれば、動かないのがすぐに分かります。

元の紹介されている方法はそもそも PHP の文法的におかしいのでそこは適当に修正して紹介します。(変数名に $ がなかったり、generateList() を出力をどこにも保存していないかったりします。)

コントローラで下記のように generateList でリストを取得して
$state_id = $this->State->generateList();
ビューで
echo $form->input($state_id, array('empty' => '--'));
と紹介されています。

CakePHP1.1 の Formヘルパーには input メソッドがないので CakePHP 1.2 でのやり方だと思いますが、実際に Form ヘルパーの input メソッドは
function input($fieldName, $options = array())
と定義されています。上記のように書くと

で、実際にはどう書けばいいかというと
echo $form->input('Model/Field', array('empty'=>'---', 'type'=>'select', 'options'=>$state_list));
または、
echo $form->select('Model/Field', $state_list, null, null, array('empty'=>'---'));
と書けば select タグの先頭に
<option value=''>---</option>
と入ります。

CakePHP1.1 では 「CakePHP HTMLヘルパーで select タグを表示する」のエントリで書いたように結構面倒だったので新しい Form ヘルパーは使いやすいですね。

OpenPNE 管理画面を別ディレクトリにする

1

OpenPNE の管理画面の URL は

http://www.example.com/?m=admin

という URL になります。
これは SNS の URL

http://www.example.com/?m=pc

などと同じ index.php を使用しています。

このため、管理画面だけ IP アドレス制限をしたいなどという場合に、.htaccess などで制限ができません。

OpenPNE のセットアップマニュアルには 「6-3. 管理画面を別ドメインで運用する (オプション)」という内容で別ドメインで運用する方法が紹介されています。

しかし、レンタルサーバなどでバーチャルドメインなどが使用できない場合に管理画面を別ディレクトリにして .htaccess などでIPアドレス制限や Basic 認証をかけられるようにする方法です。

- OPENPNE_DIR
  ├ bin
  ├ lib
  ├ var
  ├ webapp
  ├ webapp_ext
  ├ webapp_biz
  └ config.php
- public_html
  ├ config.inc.php
  ├ index.php

の public_html 以下のファイルを public_html/admin ディレクトリ以下にコピーする

-public_html
  ├  admin  (管理画面のディレクトリ名)
    ├ config.inc.php
    ├ index.php
   ・
   ・
   ・

コピーした public_html/admin/config.inc.php を書き換える

< ?php
/**
 * @copyright 2005-2007 OpenPNE Project
 * @license   http://www.php.net/license/3_01.txt PHP License 3.01
 */

define('OPENPNE_DIR', realpath('../../'));        // ディレクトリ階層が違うので合わせるために変更する
require_once OPENPNE_DIR . '/config.php';

// 管理画面のベースURL設定
define('OPENPNE_ADMIN_URL', 'http://www.exmaple.com/admin/');

// 無効にするモジュール
$GLOBALS['_OPENPNE_DISABLE_MODULES'] = array('pc', 'ktai');

?>

これで、htt://www.exmple.com/admin/?m=admin でアクセスできるようになります。

注意点は ?m=admin をつけないとアクセスできません。
また、元の http://www.example.com/?m=admin でアクセスできないように

// 無効にするモジュール
$GLOBALS['_OPENPNE_DISABLE_MODULES'] = array('admin', 'setup');

を public_html/config.inc.php に追加してください。

また、前回のエントリで紹介した 「特定ページを SSL で接続する」 で管理画面を SSL で接続する設定をしている場合は

// 管理画面のベースURL設定
define('OPENPNE_ADMIN_URL', 'https://www.exmaple.com/admin/');

のように URL も忘れずに https にしておかないとアクセスできなくなります。

OpenPNE 特定ページを SSL で接続する

3

OpenPNE で個人情報などを送信するようなフォームや管理画面を SSL で接続する方法です。

SSL を使用するように設定を変更する

openpne/config.phpの以下の行を変更
特定ページを SSL で接続するように設定
define('OPENPNE_USE_SSL_PARAM', false);define('OPENPNE_USE_SSL_PARAM', true);に変更
これだけで特定ページが SSL で接続されるようになります。

SSL を使用したいアクションを追加する

デフォルトで SSL 接続されるようになっているページ以外も SSL 接続にしたい場合は

$GLOBALS['_OPENPNE_SSL_REQUIRED'] = array(
'pc' => array(
    'page_o_regist_prof',  'page_o_regist_prof_confirm', 'do_o_regist_prof',
    'page_o_regist_intro', 'page_o_ri', 'page_o_regist_end',
    'page_h_config_prof', 'page_h_config_prof_confirm', 'do_h_config_prof',
    'page_h_config_ktai', 'do_h_config_ktai_send',
),
'ktai' => array(
    'page_o_login', 'do_o_login', 'do_o_easy_login',
    'page_o_login2', 'do_o_update_ktai_address',
    'page_o_regist_pre', 'page_o_regist_input', 'do_o_insert_c_member',
    'page_o_regist_end',
    'page_o_password_query', 'do_o_password_query',
    'page_h_config_prof', 'do_h_config_prof_update_c_member',
    'page_h_config_easy_login', 'do_h_config_easy_login',
    'page_h_config_mail', 'do_h_config_mail_insert_c_ktai_address_pre',
    'page_h_pc_send', 'page_h_pc_send_confirm', 'do_h_pc_send_insert_c_pc_address_pre',
    'page_h_config_password_query', 'do_h_config_password_query_update_password_query',
    'page_h_config_password', 'do_h_config_password_update_password',
));

となっているところに SSL 接続したいアクションを追加していく。
例えば、携帯ではリマインダーは SSL 接続になりますが PC では SSL 接続ではありません。
そこで PC でも SSL にしたい場合は上の pc の配列にリマインダーのアクションの “page_o_password_query” を追加します。
これで http://www.example.com/?m=pc&a=page_o_password_query という URL は自動的に
https://www.example.com/?m=pc&a=page_o_password_query へリダイレクトされます。

注意点は上記の URL からフォームが送信される ?m=pc&a=do_o_password_query というURL も SSL にする必要があります。
これをしないとフォームの画面は SSL でも送信先が SSL ではなくなってしまいます。

PC 用のリマインダーを SSL にする場合は “page_o_password_query” と “do_o_password_query” の2つを追加する必要があるということです。

確認画面が入るフォームなどではフォーム画面表示アクション、確認画面表示アクション、実行アクションと3つ追加する必要があります。

ユーザに SSL を使用するか選択させるアクションの追加

ユーザが SSL を使用するか選択できるリストというのもあります。

$GLOBALS['_OPENPNE_SSL_SELECTABLE'] = array(
'pc' => array(
    'page_h_config', 'do_h_config_1', 'do_h_config_2', 'do_h_config_3',
    'page_o_login', 'page_o_tologin', 'do_o_login',
),
'ktai' => array(
    'page_h_config',
));

このリストに追加するとフォームの右上やリンクの下に SSL 用のリンクが表示されユーザが SSL の使用をするか選択することができます。

Go to Top