CakePHPでjQueryをそのまま書く際に使えるパス補完メソッドをjQueryオブジェクトに追加する。

CakePHPではHtmlHelper::script()を使いJavaScriptファイルを読み込むscriptタグを生成します。これはこれで使うんですが、jQueryプラグインを使う場合は、ロード完了のコールバックで動かしたいところです。また、内部に置いてあるJSONとか画像とかを読み込んで、コールバックで処理するような場合に、パスの書き方で困りました。なのでjQueryオブジェクトにひとつ、メソッドを追加拡張するヘルパーメソッドを作ってみました。

なお、CakePHPは1.3系からJsHelperで、Prototype.jsだけだったのがjQueryにも対応しました。けど、Cookbookをざっと眺めた程度だと、jQueryで出来る事の一部をphpで書けるようにしただけの様に思えます。jQueryに慣れてるなら、むしろ書き方が違うだけでめんどくさいだけの様に見えました。そんな訳で、JsHelperは使ったことがまだ無いです。また、jQueryを使ってる事前提となります。

<?php $this->Html->script('jquery.example'); ?>

HtmlHelper::script()を使ってjQueryプラグインを読み込むなら、単純にこうなります。これはこれで良いんですけど、ロード完了時のコールバックというのが書けません。

出来る事

$(function(){
  $.getScript($.webroot('js/jquery.example.js'), function(){
    $('#foo').exampleMethod();
  });
});
$.getJSON($.webroot('data/foo.json'), {}, function(data, status){
  $.each(data.results, function(i, item){
    console.log(item.text);
  });
});

こんな感じで、webrootのパス以下から書くことが出来ます。HtmlHelper::script()と違ってjsフォルダから書かないとですけど。開発環境などで、ディレクトリ切って動かしていても、そのアプリのwebrootのパスまで補完してくれます。まぁわざわざコールバックにしなくっても、headタグ内でプラグインを読むように書いとけば、$(document).ready()時にはほぼ確実にロードできてるとは思いますけど、JSONとかの場合は便利になるんじゃないかと。

$.getJSON('<?php echo Router::url(); ?>data/foo.json', {}, function(data, status){
  $.each(data.results, function(i, item){
    console.log(item.text);
  });
});

元々Router::url()を使えば出来るんですが、JavaScriptのコード中にphpタグとかとても見づらいです。なら全部javascriptにしてしまおうというものです。

事前準備

<?php
echo $this->Html->script('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');
echo $this->ExHtml->setWebroot(); //jQueryを読んだ後に呼ぶ

コード

<?php
/**
 * Extended HtmlHelper
 * @author kanonji
 */
class ExHtmlHelper extends HtmlHelper {
    /**
     * $.webroot() for jQuery
     * 
     * To get webroot path when using jQuery.
     * This is a little closer to Helper::webroot().
     * 
     * $.getScript($.webroot('js/jquery.example-plugin.js'), function(){//callback});
     * 
     * @param array $options
     */
    public function setWebroot($options = array()){
        $url = $this->url('/');
        return $this->scriptBlock("
            $.extend({
                webroot: function(path) {
                    if(! path)
                        path = '';
                    return '{$url}'+path;
                }
            });"
        , $options);
    }
}
ex_html.php · GitHub


https://gist.github.com/798322/7de6b301f10efafdd658b90bba376f35fd5e8738
コードに間違いがあったので修正しました。@nojimage さんありがとうございます。

環境

Mac Mac OS X 10.5.8(Leopard)
MAMP 1.7.2
CakePHP 1.3.6
php 5.2.6