Posts tagged HTML

CakePHP ヘルパーの出力を echo を使わずに出力する方法

2

※この投稿の方法はバージョン1.1 までしか使用できないようです。1.2 のソースを確認したところ、$html->input の$return パラメータはなくなっていました。/app/config/core.php に AUTO_OUTPUT という定数もなくなっていました。ご注意ください。

Cakephp のヘルパーを使用していて
<?php echo $html->input('Model/filed', array()); ?>と書くところを
<?php $html->input('Model/field', array()); ?>と echo を使用せずに出力するには
/app/config/core.php
AUTO_OUTPUT = true;にすれば、自動的に出力するようになります。

私はつい echo を書き忘れてしまうので助かります。

ヘルパーのメソッドの $return パラメータを true にするとこの AUTO_OUTPUT を無効にすることもできます。
ただ、各メソッドによって、$return パラメータの位置がバラバラなので、書くときにはヘルパーのソースを確認する必要があるかと思います。

ちなにみに input の場合は
<?php $html->input('Model/field', array(), true); ?>とすると自動出力を抑止できますので、上記は何も表示されなくなります。

CakePHP 日本語マニュアル
10章 ヘルパー

CakePHP アソシエーションのまとめ(4)

0

まとめ(1) では1対1のアソシエーション hasOne でしたが、
今回は1対多のアソシエーション hasMany です。

例えば、一人のユーザに複数のコメント投稿があるような場合です。
データベースは

CREATE TABLE users(
    id int unsigned auto_increment primary key,
    nickname varchar(30) NOT NULL,
    created datetime default NULL,
    modified datetime default NULL
);

CREATE TABLE posts(
    id int unsigned auto_increment primary key,
    user_id int unsigned unique,
    comment text,
    created datetime default NULL,
    modified datetime default NULL
);

のような場合、アソシエーションの定義は下記のようになります。

< ?php
class User extends AppModel
{
    var $name = 'User';
    var $hasMany = array('Post' =>
                    array('className' => 'Post',
                          'conditions' => '',
                          'order' => '',
                          'foreignKey' => 'user_id',
                          'dependent' => true,
                          'exclusive' => false,
                          'finderQuery' => ''
                    )
                  );
}
?>

これで、
$this->User->findById($id);
とすると下記のようにデータを取得できます。

Array
(
    [User] => Array
        (
            [id] => 1
            [nickname] => boze
        )
    [Post] => Array
        (
            [0] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [comment] => コメント1です
                )
            [1] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [comment] => コメント2です
                )
            ....
        )
);

また、hasOne などと同様に CakePHP の命名規約に従っていれば、foreignKey は指定しなくても大丈夫ですので、最低限
var $hasMany = array('Post');
でもアソシエーションを定義できます。

また、hasMany で指定する配列の意味は下記の通りです。

className
関連付けたいモデルのクラス名

conditions
hasMany で取得したいデータの条件を指定する。 SQL の条件文。

order
関連するモデルのデータの並び順。SQL の ORDER 句の指定方法。
Post.created DESC
テーブル名をカラム名の前に付けないと、User.created と区別できません。

limit
Cake が取り出す関連モデルのデータの最大数。
‘limit’ => 5 のように数字で指定。

foreignKey
関連しているモデルを指している外部キーの名前。
Cake の命名規約に従っている場合は省略可能。従っていない場合はここで指定する。

dependent
true に設定すると、モデルのデータの削除時に関連しているモデル側のデータも削除される。

exclusive
true に設定すると、関連しているすべてのオブジェクトが一つの SQL ステートメントで削除される。

finderQuery
アソシエーションを取り出すために、完全な SQL ステートメントを指定する。

CakePHP 日本語マニュアル
6.4. アソシエーション

PHP の便利な関数 output_add_rewrite_var

1

PHP から出力する HTML に最終的に a タグや form タグを見つけ出し、自動で指定した変数をクエリストリングや hidden 属性で挿入してくれる関数です。

PHP4.3 から追加されたようなのですが知らなかったです。
昔から、session.use_trans_sid というセションID を a タグや form タグの hidden 属性に追加してくれるのはありましたが、それをセションID 以外にも使用できるように関数化したもののようです。

URL リライト機構に新しい名前/値の組を追加します。 名前および値は、URL (GET パラメータとして) およびフォーム (hidden フィールドとして) で追加されます。これは、session.use_trans_sid で透過的 URL リライティングが有効になっている場合に セッション ID が渡される方法と同じです。 絶対 URL (http://example.com/..) はリライトされないことに注意しましょう。

- PHP マニュアルより

userid の値 $userid を全てのリンクに付与したい場合は、
output_add_rewite_var('userid', $userid);と書くことにより
<a href="index.php">TOP</a>
<a href="index.php?userid=1">TOP</a>と出力されます。

form タグも
<form action="index.php" method="post">
<input type="hidden" name="userid" value="1">となります。

注意点としては絶対URLはりライトされないことです。
これがないと他サイトにまで、セションID などを渡してしまいますからね。

PHP マニュアル
output_add_rewrite_var

CakePHP アソシエーションのまとめ(3)

1

今回は belongsTo です。
CakePHP アソシエーションのまとめ(1) で hasOne をやりましたが、belongsTo はその逆です。

まとめ(1) で使用したテーブルで説明すると、Profile モデルにUser モデルを関連付けるのが belongsTo になります。

profile.php

<?php
class Profile extends AppModel {
    var $name = 'Profile';
    var $belongsTo = array('User' =>
                        array('className'  => 'User',
                              'conditions' => '',
                              'order'      => '',
                              'foreignKey' => 'user_id'
                        )
                      );
}
?>

配列のそれぞれの意味は CakePHP アソシエーションのまとめ(2) に説明があります。

これで、
$this->profile->findById($id);
とかすると、Profile モデルの該当するID のデータ内容とそのProfile モデルの元の User モデルのデータが取得できます。

もちろん、CakePHP の命名規則に従っていれば、

profile.php

<?php
class Profile extends AppModel {
    var $name = 'Profile';
    var $belongsTo = array('User');
}

?>

でもいけます。

6.4. アソシエーション

顔チェキを試してみた

1

最近話題の顔チェキを試してみました。

知らない方のために簡単に説明すると携帯から自分の顔写真を送ると有名人で誰に似ているか判定してくれるというケータイサイトです。

で、結果は

  1. 濱口優 63%
  2. 平泉成 61%
  3. 山口智充 60%

どれも言われたことないなぁ。平泉成さんって知りませんでした。

ちなみにウチの相方は

  1. 沢尻エリカ 51%
  2. 観月ありさ 48%
  3. 紺野まひる 48%

でした。こちらもどれも言われたことないそうです。

で、これって本人だったらどうなんだろう?と思い、濱口の写真で試してみました。
使った写真はこちらです。
結果は

  1. 濱口優 71%
  2. 森山未來 46%
  3. 小林隆 43%

でした。やっぱり本人は本人でした。確かに濱口優と森山未來は似ていると思う。

CakePHP アソシエーションのまとめ(1)

1

CakePHP のアソシエーションのまとめです。
タイトルに (1) とつけたので多分何回か続けます。

アソシエーションとはモデル間のつながりのことです。

例えば、下記のような2つのテーブルがあると

CREATE TABLE users(
    id int unsigned auto_increment primary key,
    nickname varchar(30) NOT NULL,
    created datetime default NULL,
    modified datetime default NULL
);

CREATE TABLE profiles(
    id int unsigned auto_increment primary key,
    user_id int unsigned unique,
    blog_url varchar(256),
    hobby varchar(256),
    created datetime default NULL,
    modified datetime default NULL
);

CakePHP では2つのモデルになります。
User モデルと Profile モデルです。
この2つのモデルは1対1の関係になります。
「一人のユーザは1つのプロファイルを持つ」とういことです。

この2つのモデルの関係を CakePHP に指示するには次のようになります。

< ?php
class User extends AppModel
{
    var $name = 'User';
    var $hasOne = array('Profile' =>
                    array('className' => 'Profile',
                          'conditions' => '',
                          'order' => '',
                          'dependent' => true,
                          'foreignKey' => 'user_id'
                    )
                  );
}
?>

これで、
$this->User->findById($id);とすることにより、

Array
(
    [User] => Array
        (
            [id] => 1
            [nickname] => boze
        )
    [Profile] => Array
        (
            [id] => 1
            [blog_url] => http://www.syuhari.jp/blog
            [hobby] => 読書
        )
);

のようにUser モデルだけでなく、Profileモデルの情報も同時に取得することができます。

CakePHP の命名規則を守っていれば、
var $hasOne = array('Profile');だけでもいけるようです。
※外部キーはモデル名+_id

CakePHP 日本語マニュアル
6.4. アソシエーション

PHPフレームワークのベンチマーク

0

PHPベンチマーク: Zend Framework vs Symfony vs CakePHP vs CodeIgniter vs PHP on TRAX – 徒然なるままにBlog

  • Zend-Framework
  • Symfony
  • CakePHP
  • Codelgniter
  • PHP on TRAX

のベンチマーク結果が載っています。

ただ、

モデル作成を行わないはずなのにCakePHPだけモデルが生成されるようになっていました。
PHPベンチマーク CakePHPでモデルを使用しない | Shin x blog

なので、是非CakePHP もモデル使用しないソースで実行した結果を見てみたいですね。

実行環境が元エントリとは異なるので絶対的な数値にはあまり意味が無いですが、両者を比べるとモデル生成なしの方が20%ほど速いようです。
PHPベンチマーク CakePHPでモデルを使用しない | Shin x blog

モデル使用しないと20% ほど早いそうです。

[マイ ドキュメント] フォルダのデフォルトの保存場所を変更する方法

1

[マイ ドキュメント] フォルダのデフォルトの保存場所を変更する方法
ITmedia Biz.ID:「マイドキュメント」整理法

コマンドラインを使用するときなどは不便で許せないマイドキュメントのパス。。。
C:\Documents and Settings\username\My Documents
大文字はまだいいけど、スペースとかは。。。だいたい長すぎます。tab キーで補完はできるけど。

しかし、このマイドキュメントの場所を移動できるのは知りませんでした!
これで少しは快適になるかな。

移動方法のメモ

  1. マイドキュメントのアイコンを右クリックしてプロパティを表示
  2. ターゲットタブの「移動」ボタンを押す
  3. 移動先を選択するウィンドウが出るので移動先を選択する
  4. 移動先にマイドキュメント内のファイルを移動するか聞かれるので必要なら移動させる

Windows Vista では
C:\Users\username\
に変更したらしいです。

CakePHP HtmlHelper::tagValue のHTMLエスケープ処理

1

view でモデルの値などを出力する際に
$html->tagValue("Model/hoge");
とすれと、HTMLエスケープ処理をしてくれるので便利です。

ただ、
CakePHP 1.1.15.5144以降はHtmlHelper#tagValueに注意 | Shin x blog
に書かれているように、CakePHP のバージョン1.1.15.5144 からエスケープするかのフラグが追加されたようです。

以前はエスケープしないを選択できなかったので、それはそれで不便な点もありました。
MOONGIFT ブログ ? CakePHP覚書(HTML Helpler)

しかし今回の変更で注意しなければいけないのは、デフォルトでエスケープされていたのがデフォルトでエスケープ処理されなくなったことです。

cake/libs/view/helpers/html.php
function tagValue($fieldName, $escape = false)

以前のようにエスケープ処理させるには
$html->tagValue("Model/hoge", true);
とする必要があります。

また、

ちなみに1.2.0.5147ではtagValueがdeprecatedになっており、代わりにvalueメソッドを使うようになるようです。

ということになるようです。

CakePHP flash メソッドでレイアウトを指定する

2

コントローラ毎にレイアウトを変えていていると flash メソッドは使えないなあと思っていたのですが、下記のようにすることによりレイアウトをコントローラで指定できますね。

/app/app_controller.php に下記の flash メソッドを追加

function flash($message, $url, $pause = 1) {
    $this->autoRender = false;
    $this->autoLayout = false;
    $this->set('url', $this->base . $url);
    $this->set('message', $message);
    $this->set('pause', $pause);
    $this->set('page_title', $message);

    if (file_exists(VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml')) {
        $flash = VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml';
    } elseif ($flash = fileExistsInPath(LIBS . 'view' . DS . 'templates' . DS . "layouts" . DS . 'flash.thtml')) {
    }
    $this->render(null, false, $flash);
}

これで、
/app/views/layouts/指定したレイアウト名_flash.thtml
というレイアウトファイルがあれば、それを使用して
なければ、デフォルトの flash.thtml を使用します。

やっていることはすごく単純でコントローラクラスの flash メソッドをオーバライドして、使用するレイアウトファイルを選択するところで

if (file_exists(VIEWS . 'layouts' . DS . 'flash.thtml')) {
    $flash = VIEWS . 'layouts' . DS . 'flash.thtml';
}

となっていたところを

if (file_exists(VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml')) {
    $flash = VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml';
}

に変更しただけです。

他にいい方法があれば教えてください。

Go to Top