Posts Tagged ‘cakephp’

    はてなブックマーク - CakePHP2.0で現状の問題点などまとめました。
    このエントリーをはてなブックマークに追加

    そろそろ誕生日の萩原です。誕生日プレゼントください。去年も似たようなことを言ったような気がするのは気のせいです。

    最近、CakePHP2を色々触ってまして、色々困ったことがあったので、まとめておこうかなと思います。(CakePHP2.0.4現在)
    (下でCakePHP2.xなんか知りませんと言われてますが・・・)

    AppControllerをapp/Controller以外に置く場合の注意

    CakePHP2からは皆さんご存知の通り、AppController及び、AppModelが、app直下に設置が出来なくなりました。

    CakePHP2ではAppControllerはapp/Controller以下に設置をすること、と言うことになっています。

    しかし、個人的には出来れば、直接アクセスするコントローラとはAppControllerは分けたいところです。

    そこで、AppControllerをapp/Libに設置をしようと考えまして設置を行っていました。

    app/Lib以下にAppControllerを設置後は、AppControllerを継承するコントローラにはApp::usesの記述が必要になります。

    <?php
     
    App::uses(&#039;AppController&#039;, &#039;Lib&#039;);
    
    class PostsController extends AppController {
     
    }

    しかし、作業をしていく内に、たまにAppController内のアクションが読めないというエラーが出ることがありました。(debug2でも)

    元凶はapp/tmp/cache/persistent/cake_core_file_mapのキャッシュ(こいつがなかなかの曲者です・・・)だと言うことはすぐにわかったのですが、どうにも再現性も取れず、対策がなかなかつかめない状態でした。(1ヶ月くらい悩んでいました・・・)

    結局のところ現象としては

    (1)404ページ(missing controllerなど)にアクセス
    (2)CakeErrorControllerを見に行く
    (3)CakeErrorControllerがapp/Controller以下にセットしていない場合は、CakeコアのCakeErrorControllerを見に行く
    (4)当然、コアのコントローラにApp::usesの記述があるはずもなく、継承するAppControllerの場所としてApp/Controller以下を見に行く
    (5)ないので、CakeコアのAppControllerにアクセスしに行く
    (6)さらに、キャッシュにAppControllerの位置はCakeコアにある、と記述
    (7)その後、通常のシステムのページにアクセスしても、AppControllerとして、CakeコアのAppControllerを見に行く
    (8)App/Lib以下に設置したAppConttroller内のアクションが呼ばれない

    ということが起こっていました。

    解決策としては

    ①AppControllerを素直にApp/Controller内に設置する
    ②CakeErrorControllerをApp/Controller内にコピーしてApp::usesをセットする

    ①はまずまず問題ないく動作をするはずです。

    ②についてはCakeコアでAppControllerを継承しているものが、他には通常あまり使わないであろう、PagesControllerくらいだったので、こちらでもおそらく問題なく動作すると思います。

    (2011/12/15追記)

    LibにAppControllerを置くと言う件について、Libの中にControllerのディレクトリを作ってその中に置けばいいという指摘を頂きました。
    試してみると、app/Lib/Controller/AppController.phpという形で設置をしたら、確かに問題なくusesなしでもapp/Lib/Controller/AppController.phpを見に行ってくれました。
    これならCakeErrorを書き換える必要もなくなるので、これが一番良い解決法かもしれません。

    app以下のクラス名とPlugin以下のクラス名が同名だと誤動作する

    これは具体例を挙げた方が早いと思います。

    app/Controller/PostsController.php(①)と、app/Plugin/Post/Controller/PostsController.php(②)の二つの同名のコントローラがあるとします。

    初めに①にアクセスした後、②にアクセスをしようとすると、①にアクセスをしてしまうというものです。(逆もしかり)

    これが起きてしまう原因はapp/tmp/cache/persistent/cake_core_file_mapのキャッシュがプラグインを考慮していないためです。(またお前か・・・)

    実のところ、AdminPluginを作成してそこに管理画面を実装しようとしていたところでしたので、これはかなり致命的でした。

    解消方法自体はコアを触れば出来なくもないのですが、コアのアップデートなど一切できなくなるのでお勧めはしません。

    どうしても動作させたいのであれば、lib/Cake/Core/App.phpをプラグインを考慮するように直接編集すると、動作はします。

    まぁ、ただ当分はapp以下とPlugin以下で同名のクラスが入るような実装は避けた方が良いでしょう。

    (2011/12/16追記)

    CakePHPチームにチケットを投げてみましたが、同名のクラスは現在使えない、Cake3で計画中と言われました。

    PaginatorのorderにSQLが記述できない

    CakePHP2からPaginatorがコンポーネントに分離されたことは皆さんご存知かとは思いますが、CakePHP2では現在のところPaginatorでorderにSQLがそのまま記述が出来ません。

    例えば

    $this->Paginator->settings = 
        array(&#039;order&#039; => array(&#039;`hoge` is null ASC&#039;)):

    のようなソートを行いたい時に上記のorderが無視されます。(実際に必要な場面がありました・・・)

    これは、コアのPaginatorComponentを見ればわかるのですが、352行目~の記述で

    if ($object->hasField($field)) {
    	$order[$alias . &#039;.&#039; . $field] = $value;
    } elseif ($object->hasField($key, true)) {
    	$order[$field] = $value;
    } elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
    	$order[$alias . &#039;.&#039; . $field] = $value;
    }

    とありまして、例外が全く、無視される形になっています。

    この記述自体は1.3にもあるのですが、1.3では最後にarray_mergeをしているので、SQLも取り込んでくれていたのですが、2.0では無視された状態です。

    どうしても特殊なorderをかけたい場合は現状では素書きのSQLやDBのviewなどで対応しておいた方が良いかもしれません。

    (今回私の場合は、元々orderをかけたかったテーブルがviewだったのでviewにソート用のカラムを泣く泣く追加しました・・・)

    (2011/12/16追記)

    CakePHPチームにチケットを投げてみたところ、orderを文字列で指定したら動くじゃん!って言われたので現在配列で指定したんだけど・・・と返しているところです。

    SSLページでのCookieのセキュア属性を外す方法

    SSLページがあるページとないページが混同する場合、Cookieのセキュア属性が付いていると、セッションを共有できないため、セキュア属性を外してあげる必要があります。

    1.3の場合は以下の対応が必要になります。

    app/config/core.php

    //	Configure::write(&#039;Session.save&#039;, &#039;php&#039;);
    	Configure::write(&#039;Session.save&#039;, &#039;session_custom&#039;);

    app/config/session_custom.php

    <?php
     
    if (empty($_SESSION)) {
        ini_set(&#039;session.use_trans_sid&#039;, 0);
        ini_set(&#039;session.name&#039;, Configure::read(&#039;Session.cookie&#039;));
        ini_set(&#039;session.cookie_lifetime&#039;, $this->cookieLifeTime);
        ini_set(&#039;session.cookie_path&#039;, $this->path);
    }
    ini_set(&#039;session.cookie_secure&#039;, 0);

    これは、コアのcake_session.phpの設定を強引に上書きをしています。

    CakePHP2ではcore.phpに以下の記述をすれば、対応できます。

    Configure::write(&#039;Session&#039;, array(
        &#039;defaults&#039; => &#039;php&#039;,
        &#039;ini&#039; => array(
            &#039;session.cookie_secure&#039; => 0
        )
    ));

    特に新しいファイルを作成する必要はなく、手軽です。

    CakePHP2.0ではセッションを共有するしないにかかわらず、SSLがあるページとないページが混同するサイトでは、セキュア属性は外した方が良い。

    これは、まずSSLのあるページ(①)でログインをした後、SSLのないページ(②)にアクセスし、その後、①のページにアクセスをすると、ログアウトしてしまうと言う現象のためです。(これは1.3では発生しません)

    詳しい原因についてはまだ追い切れていないのですが、①にアクセスした後、②にアクセスすると①と異なるセッションキーが振られます。(これは当然の話)

    その後①のページにアクセスすると、②で発行されたセッションキーに上書きされてしまうため、ログアウトをしてしまいます。

    以上の理由から、今のところ、SSLがあるページとないページが混同するサイトでは、セキュア属性は外して置いた方が良いと思います。

    (2011/12/16追記)

    CakePHPチームにチケットを投げてみたところ、上記の書き方でセキュア外せばいいじゃん!って言われました。

    最後に

    まだCakePHP2は駆け出しで、問題が色々と出てますが、触っている感じとしては1.3とそう大差なく使えています。そして早いです。

    きっとこれからどんどん良くなっていくと思うので皆さんどんどんさわりましょう!

    後、本当にfile_mapのキャッシュには要注意です!
    ああ・・・app.phpの750行目を消してfile_mapのキャッシュをなかったことにしたい・・・w

      はてなブックマーク - PHP Matsuri 2011に参加して得たこと(3/4)
      このエントリーをはてなブックマークに追加

      3区担当の杉本です。
      PHP Matsuri
      でのハッカソンは10/16に終わりましたが、弊社ではまだマラソンが続いています。

      「ブログを書くまでが”Matsuri”」

      ※リレーブログ形式になったのは初日の誰かさんのせいですね。

      PHP Matsuriについて

      今回、初めてPHP Matsuriに参加しました。また、ハッカソンというのも初めての経験でした。
      コアデベロッパーの方やお世話になっているライブラリの開発者の方にお会いできるのを楽しみにしていました。

      Matsuriでは過ごし方を手探りしながら、初日は講演とワークショップに参加して、日付が変わったところから開発を始めました。
      ただ、もう少しいろんな方とお話しすればよかったなと今は思っています。

      デモ大会での発表について

      ハッカソンでは「CakePHPのbakeで確認画面(添付画像付き)含めたソースを楽して一括生成する」というテーマで参加しました。

      弊社ではCMSや業務系システムなどの案件が多く、「確認画面(添付画像付き)」という要件も少なくありません。
      これが結構面倒な処理になるのですが、「TransitionComponent(hiromi2424さん)」と「FilebinderPlugin」を使うことでかなり簡単に実装ができるようになりました。ほんと感謝感謝ですm(_ _)m
      それぞれのライブラリの使い方については割愛させていただきますが、色々な方が詳しく解説されていますので是非調べてみてください。
      ※弊社ブログでも過去にTransitionComponentについての記事が書かれています。

      ただ、それでも案件毎に、モデル毎に同じ処理を書くのが面倒になってきました。

      「もっと楽に、簡単に、ミスがないように」

      実装するために、確認画面ありのCRUDをbakeを使ってソースを生成したいと思うようになりました。

      そこで、CakePHP1.3+から導入されたTemplatesを使って、コアのbakeをいじらず、実装することにしました。
      今回は即実践投入を考えて、まずはCakePHP1.3で開発。

      CakePHP Templatesについて

      Templatesはcakeディレクトリにあるtemplates/default一式をappにコピーして作っていきます。
      Controller/Modelについてはソースを見れば、修正は簡単でしたが、
      課題はCRUDの4ファイル以外のctpファイルをどう生成するか、でした。

      Matsuriに参加するまではコアのbake周りをいじらないといけないかと思っていましたが、cakephperさんに相談したところ、コアデベロッパーのグラハムさんに直接質問できる機会ができ、templatesを使って任意のctpファイルを生成するサンプルコードを教えてもらい、見事解決しました。

      ちょっと緊張しましたが、グラハムさんとお話ができたこの瞬間が一番楽しかったです。(でもやっぱり英語勉強しないといけませんね。。。)
      本当にMatsuriに参加してよかったです。

      CrudPlusPluginについて

      ブログを書きながら(思いつきで)名前を決めました。
      使い方はapp/pluginsディレクトリに置いてbakeするだけ。

      php cake/console/cake.php bake all

      該当するモデルを選ぶところはいつもと同じです。異なるのは最後にテンプレートを指定するところです。

      ---------------------------------------------------------------
      You have more than one set of templates installed.
      Please choose the template set you wish to use:
      ---------------------------------------------------------------
      1. confirm_with_file
      2. default
      Which bake theme would you like to use? (1/2)
      [1] > 1

      これでadd.ctp/edit.ctp/index.ctp/view.ctpに加えて、add_confirm.ctpも同時に生成されます。今回のハッカソンでは時間が足りず、edit_confirm.ctpまで作れませんでした。
      あと改善したいのはTransitionComponent/FilebinderPluginの存在チェックをして、なければ取得・設置できるような処理を入れたいと考えています。
      近いうちに仕上げて、GitHubで公開します。

      最後に

      今回、目標の一つにCakePHP2.0を学ぶというのを掲げていました。年内にはstableが出るだろうから年明けにはガンガン使い出すという雰囲気でしたので。
      ところが福岡に帰ってきてみると、いつの間にかリリースされているというお土産つき!
      CakePHPワークショップ中にバグを直すという(予期しない)”イベント”があったので、まるで自分が開発チームのような、一緒に2.0をリリースしたような気分に勝手になっていました。
      これはただの妄想ですが、いつも使っているフレームワークやライブラリを開発している方と直に話をすることで、さらにこのフレームワークやライブラリが好きになりました。
      これは今回得たものの中でも予想外のことでした。

      今回このような素晴らしい機会に恵まれたことに感謝しています。
      そして、PHP Matsuriのスタッフの方にはこの場を借りてお礼を言いたいと思います。本当にありがとうございました。

      さて明日は最終走者、弊社小山です。
      初日の安藤さんや吉岡さんのように、熱く”Matsuri”を語って、このリレーマラソンを締め括ってくれると思います。
      みなさん、期待しておいてください。

      それではまたどこかで。

        はてなブックマーク - PHPMatsuri参加レポート(2/4):CakePHP2.0でAndroidアプリ
        このエントリーをはてなブックマークに追加

        おひさしぶりです。
        今はWindowsPhoneがほしいFusic)櫻川です。

        さて、今回はPHP開発合宿イベントPHPMatsuriに参加してきました。

        まずはじめに

        他の方もブログに書かれていますがPHPMatsuriを表すなら
        ↓このかっこいい忍者と

        koyhogeさんの写真を使わせていただいてます。

        ↓この音楽です。
        Epic sax guy 10 hours
        忍者がバックミュージックとしてこの曲をかけ続ける中でみんな徹夜でコーディングをするカオスな空間でしたw

        ハッカソンの成果

        今回ハッカソンでやらせていただいたのは「CakePHP2.0Androidアプリ」という内容でやらせていただきました。

        CakePHP2.0bakeするとAndroidアプリ用のCRUDソースを出力する謎なPluginを作りましたw
        ※社内ではキモイといわれています。。。

        使い方

        1.どちらかでbakeをします。

        php cake.php Android.bake

        ↑実行することでネイティブなAndroid用のソース(Java)を出力します。

        php cake.php Titanium.bake

        ↑実行することでTitaniumのAndroid用ソース(Javascript)を出力します。

        2.ビルドします。

        Javaの場合はeclipseで、Titaniumの場合はTitanium Studioでビルドします。

        3.実行します。
        AndroidアプリのCRUD完成!

        結果

        結果「全ての作品の中で最も支持された作品を選出し表彰する。ハッカー賞(大賞)を頂きました!!!
        しかもiPad2まで頂いてしまいました!!!
        今自分は人生の中で一番輝いています。゚(゚≧□≦゚)゚。
        自分に投票して頂いた皆様本当にありがとうございます!!

        ソースコードなのですが現在リファクタリング中ですので完了次第githubで公開させていただきます。

        最後に

        このような楽しい祭りを開いて頂いた運営のみなさま本当にありがとうございました。
        そしてお疲れ様でした!

        来年も絶対参加します!

        それでは明日の3番手杉本にバトンタッチです。