読者です 読者をやめる 読者になる 読者になる

yiiでJSONを返すAPI的なものを作る

いいいーーー。


はい。yiiってのがあるらしいです。php のframeworkです。


Yii Framework: Best for Web 2.0 Development
初めに: Yii とは何か | The Definitive Guide to Yii | Yii Framework


軽量で使いやすそうで、MVCらしいので、とりあえず使ってみる事に。
やりたい事は、param受け取ったら、処理して、結果をJSONで返すAPI的なもの。

install

こっからダウンロード
Download Yii Framework | Yii Framework
そして、解凍すれば準備は完了。


コマンドで雛形を呼び出してみます

% cd WebRoot
% php YiiRoot/framework/yiic.php webapp testdrive

apacheでも何でも良いですが、Webから見れる箇所をWebRootと便宜上記述してます

http://hostname/testdrive/index.php

これで見れるはず。
どうですかね?

ちなみに自分の場合は、php errorが出ました。

date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead

これは、単純に、date関数使うなら、timezone指定せー、と言っているだけなので、指定すると解決する。
index.php

date_default_timezone_set('Asia/Tokyo');

で、直ります。


この状態で、問い合わせメールも飛ぶし、ログイン機能も使えます。便利ね。

JSONを返す

基本的に全部render()的な関数が自動で呼ばれてしまうので、json返そうとすると、ちょいっといじらないといけません。


controllerの基本的な使い方を見ると、メソッドの最後にrender関数を呼んでます。

 28     public function actionIndex()
 29     {
 30         // renders the view file 'protected/views/site/index.php'
 31         // using the default layout 'protected/views/layouts/main.php'
 32         $this->render('index');
 33     }

今回の修正には関係ないですが、処理フローを理解するためも、render関数を探してみましょう。


APIの記述を、

testdrive/protected/controllers/ApiController.php

に書く事にします。
controllerの継承は

yii/framework/web/CBaseController.php

yii/framework/web/CController.php

testdrive/protected/components/Controller.php

testdrive/protected/controllers/ApiController.php

というような感じになっていて、render関数は、CController.phpにあります。

grep 'function render' framework/web/CController.php | grep -v '\*'
        public function render($view,$data=null,$return=false)
        public function renderText($text,$return=false)
        public function renderPartial($view,$data=null,$return=false,$processOutput=false)
        public function renderClip($name,$params=array(),$return=false)
        public function renderDynamic($callback)
        public function renderDynamicInternal($callback,$params)

frameworkの中身を変えたくはないので、components/Controller.php 内で render関数を overrideするか、renderJSON関数を作ってあげましょう。


今回は後者の対応にしました。

renderJSON関数

    /** 
     * json用render
     *
     **/
    public function renderJSON($data)
    {   
        $this->layout=false;
        header('Content-type: application/json');
        echo CJavaScript::jsonEncode($data);
        Yii::app()->end(); 
    }

まずはlayoutをfalseに設定しつつ、json用のheaderを吐きます。


jsonへのencodeは、標準関数で

json_encode($arr);

としても良いですが、frameworkがCJavaScriptというクラスを用意してくれているので、その関数を使ってみました。


最後に、endで、よけいな処理が続かないようにします。