今回は jQuery についての章です。私も以前 CakePHP のための jQuery ヘルパーを探したことがありますが、結局作者と同じく、直接 jQuery を使う方が楽だという結論に至りました。
翻訳とは関係ないのですが、最後のJavaScriptのコード例は下記のようにすべきではないかと思います。
$("#scoresUpdate").click(function() {
$.ajax({
url: this.href,
success: function(html) {
$("#divId").html(html);
}
});
});
jQuery 註
- solid
-
「手堅い」とか「実績のある」といったイメージだろうか。
- The JavascriptHelper used
-
この文以降、形式的には過去形と現在形が入り交じっている。正直なところ、何を意図しているのかよく分からない。少なくとも仮定法を使った文はないと思うのだが、特に would が過去なのか現在なのか、区別し切れない。
-
とりあえず JavascriptHelper について語っているこの文と次の文については、著者の意識としてはヘルパーを使う方法は古いやり方だから、過去形になっているのもまあ理解できる。ということで訳文でも過去形にした。
- This would fire an alert with …
-
この段落以後の would は単なる弱い推量?
- Notice that this is PHP code that
-
「PHPのコード」であることに力点があるので、訳文には括弧を追加した。
- This is pure JavaScript code and can be …
-
この and は「したがって」「だから」といった意味。
- you’re not just stuck using a DOM ID
-
stuck は stick の過去分詞形。なんとなく意味は伝わってくるのだが正確な訳はよく分からない。訳文はごまかし。辞書には be stuck with doing … で「〜することを押し付けられる」といった訳が載っている。同じような意味か。
- a special link that, when clicked, sends off an XMLHttpRequest, rather then redirecting the browser.
-
この文は理解できなかった。お手上げ。(1) rather then は rather than の typo なのか (2) もしそうだとしたら、rather の前のカンマは何を意図しているのか (3) 仮にカンマを無視するとしたら後半は sends off redirecting the browser という文を想定することになるが、それで意味が通るか (4) もし then が than の typo でないとしたら、一体どういう文になるのか。
-
訳文では次のような文を「訳」した: a special link that, when clicked, sends off an XMLHttpRequest rather than redirects the browser.
- made
-
「行う」「する」といった意味の make
- you would …
-
この段落の you は明確に読者を意識しているわけではなく、なんとなく「一般の人」を主語においているだけだろう。
……
Super Awesome Advanced CakePHP Tipsの翻訳3回目です。まさにアイデアの勝利、といった内容ですね。
Stupid Easy URL Slugs 註
- Stupid Easy
-
直訳は「愚かで簡単な」。たぶん決まり文句だろうと思ってGoogleで検索したところ、「非常に簡単な・初歩的な・容易な」という意味で用いられているようだ。それら用例を見る限りでは、必ずしも(字面から想像されるような)否定的な意味とは限らないらしい。ということで、日本語に置き換えるなら「バカでも分かる」がぴったりだと思うのだが、翻訳でそこまでキツイ語を使う勇気はなかったので、もう少しマイルドに「呆れるほど簡単な」としておいた。
- Slugs
-
Wikipedia-en Slug(typesetting)によれば元々は活字組みでスペースを空けるために用いられる部品?のことらしい。現代のDTPソフトウェアでも補助情報を印刷するための領域(最終的には裁断され捨てられる)の名前として使われているとのこと。ちなみにInDesign CS4の日本語版マニュアルでは「印刷可能領域」という見出しで説明されている。
-
それが、どういう経緯があったのかは知らないが、最近ではURLの中に埋め込むページ見出しの呼称として使われるようになった。日本語では適当な訳語もないし、WordPress等のブログツールで使われてそれなりに広まっているので、片仮名の「スラッグ」で良いだろう。
- I’ve seen this idea floated on a bunch of different blogs.
-
この章に限ったことではないのだが、章の冒頭の文章はけっこう格好つけた感じの文が多くて、そのまま日本語に訳して意味が通るようにするのは難しい。なので訳文はある程度雰囲気重視で作っておいた。
-
ここでの float は「提案する」という意味で、this idea は当然「URLスラッグを(CakePHPで)作る」という「考え」だろう。スラッグの作り方について、いろいろなブログでいろいろな提案がされているのを見てきたよ、ということ。
- Many offer more complicated methods …
-
この文もちょっと凝っている。「複雑な方法」か「単純にするためのビヘイビア/ヘルパー」だから、どちらも本質的には複雑だ、という含意がある。
- you’re using a standard action for your view
-
この view がよく分からない。「viewアクション」のことなのか、それとも「項目の表示」という意味なのか、あるいは両方を同一視しているのか。訳文では迷った末に view のまま放っておいた。すいません。一応前者のつもりということで。
- It is safe to create URLs
-
定冠詞なしの URLs だから、ここは一般論。日本語では何か接続詞が欲しくなるところ。
- With this method
-
後に続くのが this method なので、この With は「(道具を)使って」という意味かと思えるのだが、それだと意味が通らない。ここは「〜について、〜に関して」という意味だろう。
- Consistency And SEO Improvements
-
「一貫性とSEO」を改善するのか、それとも「一貫性」および「SEOの改善」を話題にしているのか。どちらとも取れるような訳文にしておいた。 Improvements が複数形だから、「一貫性とSEO」を改善するのだろう。初歩的な見落としをしてしまった。
- and
-
ここと次の文の and は「しかし、にも関わらず」といった意味だろう。
- cakephp_sucks_and_so_does_your_site
-
「CakePHPはクソだしお前のサイトもクソだ」。もし日本語で入力したとしても表示されるはずなので、訳してもよかったかも知れない。
- happily
-
日本語で言う「おめでたい」というやつか。
- It’s easy enough
-
特に訳文には反映していないが、この enough は「十分簡単なので(ご安心ください)」というニュアンスが込められているかもしれない。
MarkupHelperを更新しました。他のヘルパーの中から使いやすくするために、popContext が直前のコンテキストのバッファの内容を返すように変更されました。
メソッド全体を pushNewContext と popContext で囲むことで、「生成したHTMLをバッファ変数に溜めておいて、最後にreturnする」という典型的なヘルパーの処理を代替できます。こんな感じです。
<?php
class YourHelper extends AppHepler
{
var $helpers = array('markup');
/**
* 定義リスト
<dl>..</dl>
を作るヘルパーメソッド
*/
function defList($data)
{
$this->Markup->pushNewContext->dl->nl;
foreach($data as $term => $desc) {
$this->Markup
->dt->text($term)->end
->dd->html($desc)->end->nl;
}
return $this->Markup->endAllTgs->popContext;
}
}
/* 使用例 */
echo $your->defList(aa('用語1', '<strong>説明1</strong>', '用語2', '説明2'));
/* 出力(改行もこの通りになります)
<dl>
<dt>用語1</dt>
<dd><strong>説明1</strong></dd>
<dt>用語2</dt>
<dd>説明2</dd>
</dl>
*/
以前のページも更新しておきました。
- 原題: Automatically Tracking Created/Modified By
- 日本語訳トップページ
……
Super Awesome Advanced CakePHP Tipsの翻訳2回目です。内容的には前回の続きになっています。
Automatically Tracking Created/Modified By註
- Created/Modified By
- この章に出てくる created/modified by は、そのままでは日本語に訳すことができない。ある程度説明的に訳すしかない。
- establish
- 細かいことだが現在形。つまり著者はこの本が先頭から読まれるものだとは必ずしも想定していないということになる。
- the previous section
- 翻訳上は全く問題無いのだが、この the previous section が具体的に何を指しているのかはちょっと興味深い。というのも、この本の中で見出しが付けられた内容のまとまりを何と呼ぶべきかに関わるからだ。
- もしこの section が『Getting the Logged In User from Anywhere』全体を指すのであれば(文脈からはそれが最も自然だろう)、この本の中で最も大きなまとまりは「section = 節」と呼ばれていることになる。しかし個人的には、節では少し小さく感じる。「章 = chapter」と呼んだ方が相応しいような気がする。そして実は作者もブログの中で「Chapter」という呼び方をしている。
Check out Chapter 2: “How to Learn CakePHP”
. だがもし『Getting the Logged In User from Anywhere』や『Automatically Tracking Created/Modified By』を章と呼ぶのであれば、ここの the previous section は何を指すのだろうか?前の章の最後の節である『Full Source』だろうか?意味の上ではあり得なくもないが、ちょっと変に感じる。
- Now we can apply this to setting the created by …
- この文はうまく訳せなかった。わずかな単語にいろいろな意味が圧縮されているので、日本語だと説明的になりすぎて文にならない。created by and modified by fields で「誰が作成・更新したのか記録するためのフィールド」、setting は他の用例から考えれば「(フィールドに)値を設定する」という意味。for various database records は構造の異なる様々なレコード(テーブル)に対して、という意図だろう。
- Model beforeValidate Callback
- この段落全体は著者の勝手な仮定によるお遊びで、それゆえ仮定法が用いられている。「こんな文を書くくらいなら素直に beforeValidate コールバックの例を書けば良いじゃないか!」と読者に思わせるための、ツッコミ待ちの文章。
- make this into a behavior
- もちろん「これをビヘイビアの中に入れる」と直訳しても意味は通じるが、「ビヘイビア化する」という日本語がぴったりだろう。
- Then
- この Then は「すぐに」の意味だろうか。
- feel mildly foolish
- feel foolish で「きまりが悪い」「ばつが悪い」といった意味。
- justified in believing …
- be justified in doing … で「…は正当である」「…するのももっともである」といった意味になるのだが、主語と動詞が欠けている。文脈からすれば主語は多分 you だろう。
- So I won’t insult your intelligence …
- 最後のこの文は仮定法ではない。「あくまで仮定」という装いで散々書いておきながら、最後に「私はそういうことはしないよ」と言っている。読者からのツッコミ待ち。
- We’re making a bit of a leap here, in believing that …
- 非常に訳しにくいので訳文はごまかした。すいません。leap はここでは多分「論理の」飛躍という意味で、段落冒頭の The logic と対応している。「『idが設定されていれば更新だ』と考えるのは論理が飛躍している」ということで文脈にも合う。さらに進行形なので、「今論じているこのロジックの中で、論理の飛躍を犯しつつある」といった感じか。また前置詞 in は時間または状況の中という意味にとって、「このロジックの中の、具体的には…と考えているところで、論理の飛躍を犯しつつある」という風に解釈するのが最も自然だろうか。
- If you wanted to be diligent
- 仮定法。その前の文の outside possibility と対応しており、著者はidの偽装が問題となる可能性は非常に低いと見ている。そもそも「誰が作ったか」を自動追跡することが必要になるアプリケーションというのは、かなり限られたユーザだけが使うログイン制のシステムだから、だろうか?
- less
- この less は excluding と同じ意味で、「〜を除いて」。
- 原題: Getting the Logged In User from Anywhere
- 日本語訳トップページ
……
Matt Curry氏が無償公開されている電子書籍『Super Awesome Advanced CakePHP Tips』の翻訳を始めました。既にbobchin氏が全体を翻訳完了されている(と公開直前に知った)のですが、私自身の勉強も兼ねて、なぜそう訳したのかという註釈を含めて拙訳を公開していきます。原文を読まれる際にお役立てください。また間違いや疑問などありましたら教えていただけると嬉しいです。
第一弾は16ページからの『Getting the Logged In User from Anywhere』です。私が興味を持った順に訳していきます。とても時間がかかるので、翻訳完了時期は今のところ未定です。
Getting the Logged In User from Anywhere註
クリックすると該当行をハイライトして表示します。
- from Anywhere
- 日本語で「どこからでも」と言うと譲歩の意味が強過ぎるので、ちょっと堅苦しい表現だが「任意の場所から」とした。
- This is a problem that comes up often.
- This はタイトル「Getting the Logged In User from Anywhere」の内容を指し、それが「よく生じる問題である」、ということで「よく問題となる」といったところか。
- modified user
- 素直に読めば「修正されたユーザ」としか読めないのだが、それでは意味が通らない。文脈からすればこれは次章「Automatically Tracking Created/Modified By」の内容を示していることは明らかなので、modified user ひとまとまりで「修正を行ったユーザ」と理解するのが正しいのだろう。Web検索でも同様の用例が見つかる。
- beforeFilter
- モデルには beforeFilter コールバックは存在しない(次章の内容からすれば実装上正しいのは beforeValidate)。なぜここで beforeFilter と言ったのか。(1)コントローラの beforeFilter を指す。(2)単なる間違い。(3)主処理の前に実行されるコールバックを抽象的に beforeFilter と呼んでいる。多分(3)?
- It would be great if you could …
- 前の文は単なる仮定だが、この文は仮定法。つまり handle 以下は現実には不可能だと認識している。「なぜ不可能なのか」に相当する内容は書いていないが、前段落までビューとコントローラからセッションにアクセスする方法について述べているのだから、ここではモデルからセッションにアクセスする方法が”無い”ことを仮定法によって暗示していると見なせる。
- You can always cheat …
- always が悩ましい。本当に「いつでも」という意味だと理解すると、ビューでもコントローラでも使えばいいじゃないか、という話になって次の文とのつながりが苦しくなる。「必要ならいつでも」くらいに訳すべきか。さらに次の文の註参照。
- Plus, now we are using three …
- この文は翻訳では何か言葉を補わないとうまく繋がらない。まず文頭の Plus が何に対して「加えて」いるのかが問題になる。always の註に書いた通り、前の文に対する付加だとすると意味が通じない。これは冒頭の problem に対する付加と見なすべきだろう。
- つまり作者の問題意識は2つある。一つ目は Model からセッションに直接アクセスする方法がないこと。二つ目はアクセスする方法がバラバラであること。よってこの2つを同時に解決する方法を提示するのがこの章全体の主題となっている。章の冒頭のこの節ではまず前者について述べ始めたのだが、最後になって後者を付け加えた。あるいは書いている途中で自分の2つ目の問題意識に気付いたのかも知れない。
- but for the User::get syntax to work it has to …
- but は単なる接続詞。for は不定詞 to work の主語を示す。語順を変えると「but it has to go in the model for the User::get syntax to work.」
- Deal with it.
- 「うまく対処してくれ」→「なんとか我慢してくれ」くらいの意味になるようだ。参考。直訳だとちょっと様にならないので意訳を採用。
- instance
- これ以後 instance という語が頻繁に使われるのだが、その意味は日本語オブジェクト指向用語の「インスタンス」とは厳密には一致しない(必ずしも何らかのクラスに属するオブジェクトではない)。しかしWikipediaを参照する限り英語オブジェクト指向用語の「instance」も日本語の「インスタンス」とほとんど変わらない意味だから、やはりこの文章における用例とは一致しない。多分、instance が元々持っている「具体事例」というような意味と、オブジェクト指向用語 instance が持つ語感とを混ぜ合わせたような意味で用いられているのだと思う。
- Before you can access … you need to …
- 「…するためには…しなければならない」「…して初めて…することができる」
- get the instance and pull out a specific piece of information from the user array.
- この and を単純な並列にとると意味が通じない(User::get は $path パラメータが必須で、「インスタンス」を取得するためのものではない)。やはり the instance と the user array は同じ物を指していると考え、「インスタンスを取得して、そして一部を取り出す」というように前後関係を表していると見るべきだろう。
- inspired
- 敢えてカタカナで「インスパイア」の方が雰囲気が出ると思う。パクリじゃない、インスパイアだ!
- the syntax isn’t as appealing.
- 後ろに「as that of User::get()」が省略されている。
- Why not just use the same setup for …
- 意味は鮮明だが訳しにくい。「Why not A …, but B …」なぜBを除きAしないのか(すれば良いではないか)。思いっきり分かりやすく言うと、 User::get() を Configure に対する Wrapper にすれば良いじゃないか、ということ。
- Again, certainly an option.
- うまく訳せなかった。 短い文は難しい。 an option は「User::get() を Configure に対する Wrapper にする」という(読者からの想定)提案を指し、Again はその前の「Configure クラスをそのまま使う」という案に対するもの。だと思うのだが、自信がない。
- withing
- within の typo だろう。
XREAが重過ぎて使い物にならなくなったので、エックスサーバーに移転した。ここを選んだ理由は
- PHP5, MySQL5が使える
- 比較的値段が安い(X10プランで月額1050〜1260円)
- ネット上の口コミでは速度に対する評価が高い
- “ハズレ”を引いたときの救済措置簡単サーバ移動機能がある
- SSHが使えないので、派手なことをするヤツは少ないだろうという希望的観測
今のところ速度には満足。サーバの管理画面も使いやすい(若干パワーユーザ向けだが)。WordPressも問題なく移転できた。
WordPressの移転にはいろいろな方法があるようなので、私の方法も紹介しておく。最も原始的かつ確実な方法で行った。
エックスサーバーでの下準備
- 管理画面「MySQL設定」で新しいMySQLデータベースとMySQLユーザを作る
- 「ドメイン設定」で独自ドメインを登録する
- できればここで /etc/hosts ファイルを書き換えてきちんとアクセスできることを確認しておく。WebサーバのIPアドレスは「DNSレコード設定」で確認できる
旧データのバックアップと修正
- XREAの管理画面「データベース」で「保存」ボタンを押してバックアップを作成する
- 作成されたmysql.dumpおよびサイトの全ファイルをローカルにコピーする
- wp-config.php を開き、データベース設定をエックスサーバーのものに書き換える
エックスサーバーにアップロード
- 管理画面からphpMyAdminにログインして、mysql.dumpを実行
- ドキュメントルートに全ファイルをコピー
- 例によって /etc/hosts を書き換え、WordPressが正常に動くことを確認
あとはDNSを変更すればOK。
CakePHPのModelが備える recursive 機能は分かりにくい上に効率が悪い。代わりにContainableビヘイビアを使うべき。今後新たに作り始めるならAppModelに次のように書いても良いくらい。
class AppModel extends Model {
var $recursive = -1;
var $actsAs = array('Containable');
}
このビヘイビアは、一言で言えば ActiveRecord(Rails) の include オプションのようなもの。一度の find で取得する関連を明示的かつ再帰的に指定することができる。
/*
Group hasMany User
User hasOne Profile
*/
$rows = $this->Group->find('all', array('contain' =>
array('User' => 'Profile')))
他にも取得する field を指定したり conditions を指定したりすることもできる。詳しくはCookbook(和訳)参照。
ちなみにrecursiveの値そのものは、大まかには「(CakePHPのモデル実装が)追加で必要とするクエリの回数」を表しているものと思われる。そのルールそのものは Containable ビヘイビアを使ったとしても変わらない。すなわち belongsTo や hasOne のデータは基準となるテーブルにjoinして取得されるので追加のクエリは不要、よってrecursive=0。hasMany と hasAndBelongsToMany は追加で1回必要になるのでrecursive=1。recursive=2以降は…正直よく分からない(参考。2以降はルールが違うらしい)。Containableを使った方が絶対に良い。
joinやサブクエリ、集合演算などを含む複雑な検索を行う場合、
- まず検索条件にマッチする全行のidを求め、
- Model.id IN (1で求めた全id) という条件で一覧表示に使うデータを取得する
という手順を踏んだ方が合理的なことがある。
この場合、1の段階で「検索条件にマッチする全行数」が判明するため、Paginationのために改めてCOUNTクエリを発行するのは完全に無駄である。CakePHP 1.2のPagination機能でこの無駄を回避するには、コントローラの $paginate プロパティに適当なキー(下例では numberOfRows)で件数を保存しておき、
$allIds = $this->Foo->find('all', array('fields' => 'DISTINCT Foo.id',
'conditions' => $complexCond));
$this->paginate['numberOfRows'] = $this->Foo->getNumRows();
対象となるモデルの paginateCount メソッドでその数値をそのまま返すようにする。
class Foo extends Model
{
function paginateCount($conditions=null, $recursive=0, $extra=array()) {
if(isset($extra['numberOfRows'])) {
return $extra['numberOfRows'];
}
$parameters = compact('conditions');
if ($recursive != $this->recursive) {
$parameters['recursive'] = $recursive;
}
return $this->find('count', array_merge($parameters, $extra));
}
}
$paginate の中で認識されないキーは、Model::paginate や Model::paginateCount の最後の $extra 引数として渡ってくる。
メソッドチェーンを用いて複雑なHTMLを組み立てることができるMarkup Helperを公開しました。(実用上)PHP 5.2以上が必須です。
cakephp-markup-helper – GitHub
例1:単純なdiv,pタグを出力
echo $markup->div('section')->p->text('これは<テスト>です')->end->end;
/*
出力されるHTML:
<div class="section">
これは<テスト>です
</div>
*/
例2:HtmlHelperと併用し、「ユーザ一覧」テーブルを構築
echo $markup->div('list')
->table
->thead
->html($html->tableHeaders(a('id', 'ユーザ名', '操作')))
->end
->tbody->nl;
foreach ($users as $user) {
echo $markup->tr
->td->text($user['User']['id'])->end
->td->text($user['User']['username'])->end
->td('actions')
->html($html->link('編集',array('action'=>'edit', $user['User']['id'])))
->end
->endtr->nl;
}
echo $markup->endAllTags;
使い方は上の例からほとんど想像がつくだろうと思います。特徴は次の通りです。
- ほとんど全てのメソッドがインスタンス自身を返すので、延々メソッドチェーンを繋げていくことでどんな複雑なHTMLも構築することができます。
- 内部で「どのタグがまだ閉じられていないか」という情報を管理しているため、タグ名を明示しなくてもタグを閉じることが出来ます。逆に敢えてタグ名を明示して、構造が正しいことを確認することもできます。
- 生成されたHTMLは内部のバッファに蓄えられ、__toString で文字列として返却されます。PHP 5.2以降ではオブジェクトが文字列として使用される際に自動的に __toString が呼ばれるため、違和感なく echo(またはその他の関数)で出力することができます。
省略記法の種類
できる限り短く、書きやすくするため、__get と __call を活用した省略記法が多数用意されています。
| |
省略記法 |
実際のメソッド呼び出し |
| プロパティ |
$markup->{method_name}; |
$markup->{method_name}(); |
| メソッド |
$markup->{tag_name}(arg1, arg2, …); |
$markup->startTag({tag_name}, arg1, arg2, …); |
| $markup->end{tag_name}(); |
$markup->endTag({tag_name}); |
| $markup->nl(); |
$markup->newline(); |
| $markup->end(); |
$markup->endTag(); |
これらの省略記法を用いることで、例えば次のような記述が
$markup->div('css-class')->p->end->enddiv->nl;
次のようなメソッド呼び出しに変換されます。
$markup->startTag('div', 'css-class')
->startTag('p')->endTag()->endTag('div')->newline();
主要なメソッド
細かい動作についてはユニットテストも参考にしてください。
| startTag($tag, [$attrs, $content $escapeContent]) |
$tagの開始タグを生成してバッファに追加します。$contentが与えられた場合は終了タグも追加します。
| $tag |
string |
必須 |
タグ名 |
| $attrs |
string or array |
null |
HTML属性。文字列が与えられた場合はclass属性の値と見なされる |
| $content |
string |
null |
要素の内容 |
| $escapeContent |
boolean |
true |
trueの場合は$contentをHTMLエスケープする |
|
| endTag([$tag]) |
終了タグを生成してバッファに追加します。$tagが与えられなかった場合は最も内側のタグを、$tagが与えられた場合は最も内側の$tagタグとその内側の全てのタグを閉じます。$tagが与えられ、かつ閉じるべき$tagが存在しない場合はE_USER_WARNINGとなります。
|
| endAllTags() |
全てのタグの終了タグを生成してバッファに追加します。 |
| text([arg1, arg2, ...]) |
任意の数の文字列をHTMLエスケープしてバッファに追加します。 |
| html([arg1, arg2, ...]) |
任意の数の文字列をそのままバッファに追加します。 |
| newline() |
改行(0x0A)をバッファに追加します。 |
| renderElement([arg1, arg2, ...]) |
エレメントをレンダリングしてバッファに追加します。下記の説明を参照してください。 |
エレメントのレンダリング
エレメントをレンダリングするための専用メソッドとして、renderElement が用意されています。
echo $markup->div('search-result')->renderElement('search/result')->end;
もちろん html メソッドを使って、View の elementメソッドの戻り値をそのまま埋め込むこともできます。
echo $markup->div('search-result')->html($this->element('search/result'))->end;
ただしこの方法では MarkupHelper が内部で保持している文脈情報がそのままエレメント内に引き継がれます。エレメント内で endAllTags メソッドなどを呼んだ場合、意図しないタグまで閉じられてしまうことがあります。
MarkupHelper には文脈情報を隔離するために pushNewContext/popContext メソッドが用意されています。renderElement メソッドでは自動的にそれらのメソッドを呼び出し、エレメントのレンダリングが独立した文脈の中で実行されるようになっています。
echo $markup->div; //
<div>
$markup->pushContext();
echo $markup->p->strong->text('foo')->endAllTags; //
<strong>foo</strong>
$markup->popContext();
echo $markup->end; //</div>
他のヘルパーの中から使う
この pushNewContext/popContext メソッドを活用することで、他のヘルパーの中でも安全に MarkupHelper を使用できます。「生成したHTMLをバッファ変数に溜めておいて、最後にreturnする」という典型的なヘルパーの処理は、全て MarkupHelper が肩代わりしてくれます。
<?php
class YourHelper extends AppHepler
{
var $helpers = array('markup');
/**
* 定義リスト
<dl>..</dl>
を作るヘルパーメソッド
*/
function defList($data)
{
$this->Markup->pushNewContext->dl->nl;
foreach($data as $term => $desc) {
$this->Markup
->dt->text($term)->end
->dd->html($desc)->end->nl;
}
return $this->Markup->endAllTgs->popContext;
}
}
/* 使用例 */
echo $your->defList(aa('用語1', '<strong>説明1</strong>', '用語2', '説明2'));
/* 出力(改行もこの通りになります)
<dl>
<dt>用語1</dt>
<dd><strong>説明1</strong></dd>
<dt>用語2</dt>
<dd>説明2</dd>
</dl>
*/