ruby最近、仕事でRailsを使い始めたので、今までよく使っていたCakePHPとどこが一緒でどこが違うのかをざっくりまとめてみました。Railsは勉強中なので、理解が不十分だったり間違っている箇所もあるかと思いますが、それらの点についてはコメントなどでご教授いただければ幸いです。ように、URLで「/」で区切られているものは、アクション以降の文字列も勝手に引数に分けてくれます。$name)のように引数を分けて定義しておいてあげれば、勝手に値が割り当てられることになります。Railsの場合はconfig/routes.rbで振り分け方法を定義しておいてあげる必要があります。'show'こんな感じになるでしょうか。actionなどを含むURLを作成することなんかできたりします。'miyabi')で呼び出すと、http://localhost:3000/berryz/show/miyabiを意味することになります。param[:hoge]のシンボル指定で取得できるのも特徴でしょうか。"application.rb"の名前で設置され、その場所と名前が微妙に異なります。この名前については、これ規約からも外れてるよなぁ。2.3.0からは"application_controller.rb"に名前が変わるようですね。詳しい話はこちらに書いてました。そのレイアウトのHTMLを記述します。Railsの場合は、views/layouts/application.rhtmlに記述することになり、その名前は異なります。統一性の観点から言うと、Railsのこの名前の方が個人的には好きです。名前で保存しておきます。Railsの場合は、特定のcontroller内での共通テンプレート、全controllerでの共通テンプレートとそれぞれ別に分けることができます。ように、"views/controller名/_{部分テンプレート名}.rhtml"の形式になります。:partialで指定する値が"shared/header"のようになります。この点については、Railsはここまで細かい指定がなくてもいいのにな、、と思います。Cakeの方が直感的な規約だし、呼び出し方も簡単かな、と。FilterCake,Railsともにcontrollerにおいて、その前後にフィルタをかけることが可能です。afterFilterですね。Cakeでは特定のController、またはApplicationControllerにおいてbeforeFilter/afterFilterアクションを定義しておくことで、そのフィルタを通すことが可能です。Railsの場合、フィルタにはメソッドはもちろんですが、クラス、ブロックの3つのレベルで指定可能です。複数のフィルタが定義されている場合は、その定義された順番にフィルタが適用されます。このRailsの細かな指定は凄い、としか言いようがないかんじ。ブロックで渡すことができる柔軟性は使いこなせばすごく便利そうな印象です。以下に設置しておけばOKです。ディレクトリに設置することになり、そのディレクトリ名が異なっています。これについては、Railsを意識しまくったCakeとしては、どうしてここの名前だけ変えたのかはよく分かりません。まとめざっと目につきやすい相違点をまとめてみました。Railsについてはまだまだ触り始めたばかりなので、相違点はまだまだあるでしょうし、注意して理解を深めて行きたいと思います。今回こうやって相違点を考えていくことで、むしろお互いの理解が深まるんじゃないかな、とも思っています。ちなみに、チュートリアルについて、book.cakephp.orgは日本語化されてるわけですが、guides.rubyonrails.orgは日本語化されてないんでしょうか??すごくよくまとまってそうなので、できれば日本語で読んでみたいのですが。00:32phpCakeでキャッシュ周りの調査をしていたら、モデルのメソッドの実行結果をキャッシュさせるbehaviorがあるのを見つけました。Behaviorでモデルのメソッドキャッシュを行うこれが相当いい感じなので、その利点や導入方法についてまとめておきたいと思います。コントローラのスリム化MVCモデルでキャッシュを利用しようという話になると、大抵Controllerでキャッシュヒットの有無を確認して、ヒットしない場合キャッシュをリセットする、というロジックがまず頭に浮かぶと思います。$posts);}ただ、コントローラで毎回このようなキャッシュヒットを確認していると同じようなコードがあちこちに散らばることになるので、保守性が悪くなります。いうキャッシュ周りの処理はできるだけモデルに振ってしまったほうがよいです。基本的なフロー以外の余計なロジックを考えなずにくてよいので、可読性も格段に上がると思います。$this-&gt;Post-&gt;find('all');PaginationもキャッシュできるCakePHP1.2から導入されたPaginationですが、実態はfind('all')+ページ情報をセットする処理を隠蔽したものとなっています。ポイントは、$controller->paginate()メソッドの中で、これらの処理を全部行いつつも、returnで戻ってくるのはfind('all')の結果なので、paginate()の結果だけキャッシュさせていても、ページ情報がキャッシュされずにView側でエラーになる、ということです。/controller/controller.phpの1056行目あたりにあります)この理由から、controller側でpaginateの結果をキャッシュさせる作戦はうまくいかないので、Paginationは毎回遅くなります。そこで、controller側ではなく、Model側でキャッシュを行わせます。paginate()内で行われるfind以外の処理、つまりページ情報の処理についてはその処理時間は高々知れているので、結局findの処理をキャッシュさせておくことでpaginate()の高速化が期待できます。今回は、モデルキャッシュをmemcachedにキャッシュさせるようにしました。コードは上記リンクから入手できるので、app/models/behaviorにcache.phpで保存しておきます。app/config/core.phpのCache::configを次のようにFileエンジンの設定をコメントアウトし、Memcacheエンジンを利用します。'File'));そして、キャッシュを利用したモデルにおいてactsAsで設定します。array('Cache');findをオーバーライドします。}こんなかんじで、第一引数のタイプをcase文で振って、return文では素のfind('all')を通らせることで必ずdefaultに処理を落とすようにさせ、そこでキャッシュをかけるようにさせます。これでシンプルでスッキリした構成にできました。まとめ1つ思ったのは、このビヘイビアではcacheMethodメソッドにおいて第一引数ではキャッシュ時間を指定させるのですが、この時間は第三引数にしてオプション扱いにしてほしかったかなぁということ。$cache_timeであるから。組み込みのエンジンを利用できるのだからcacheのexpireもCache::configのduration値を標準で見てくれてもいいのかな、と思います。いえ、これでコントローラ側では普通にfindを呼び出すだけでキャッシュ付きの処理を行うことができるので、非常に有効なライブラリかと思います。saveが起こるようなModelでは、あまりキャッシュが有効にならない場合も多いかと思うので、その点はご注意を。faultでコケることが数回あったので、原因を探るためにdebugを有効にしたPHPに入れなおすことにしてみました。mysqldはyumで入れていたものをそのまま使うことを想定しています。既存のPHPを削除もともとyumで入っていたので、そのまま素直にyumで削除します。php\*ソースコードの入手PHPの最新のソースコードを入手します。ソースコードはここから入手できます。2009.01.06時点での最新バージョンは5.2.8です。Configureの準備Configureにあたって、多くのツールをインストールしておく必要があります。僕は次のものを入れる必要がありました。libtool\*configureyumで入れていたころのPHPのconfigure結果をできるだけ再現させてます。そこからサポートされていないオプションは外して、mysqlのprefixを変更、apxs2のオプションを追加させています。PHPがインストールされます。やりなおしたらうまくいくかもしれません。php.inimakeするとカレントディレクトリにphp.ini-recommendedができているので、これを/etcにコピーして必要な項目を修正します。installするとhttod.conf(/etc/httpd/conf/httpd.conf)に次の1行が追加されています。modules/libphp5.soただ、できるだけhttpd.confは素のままにさせておいて追加項目は書きたくない主義なので、さっきの1行は削除してしまいます。かわりに/etc/httpd/conf.d/php.confを次の内容で作成します。.phpsこれでhttpdを再起動すると--enable-debugなPHPで再起動します。素のCakePHPなんかはこれで動作させることができます。まとめなかなかconfigureを通すことができなかったり、mysqlとの連携がうまくいかなかったりしたのですがなんとかビルドすることができました。yumにお世話になっているとゼロからbuildするのもすごく苦労しますね。まーでもいい勉強になりました。01:10phpCakeではgettextを利用して多言語化(国際化対応)が簡単にできる仕掛けが用意されています。実際は、こんな流れになります。詳しくは次のサイトなどが非常に詳しい情報が掲載されています。Codeさて、この国際化対応のときに盲点となるのが「検索エンジン対応」です。Languageを調べてそこで切り替えが行われています。(ブラウザでの優先する言語で設定できるやつですね。Requestが投げられると、意図しないページを収集されてしまうことがあります。Languageが設定されてない(ケースが多い)ので、上記サイトのような構造にした場合、標準言語である英語サイトの情報がクローラに収集されてしまいます。その場合、当然「海外サイト」と見なされ、いくらmeta要素でキーワード設定をしていても検索結果になかなか引っかからずにSEO的に残念な結果になってしまう、なんてことになりがちです。クローラ固有の対策をするじゃぁどうすればいいか、となると話は単純でクローラのUAを見て利用する言語情報を切り替えればOKです。CakeだとAppControllerにこんなコードを入れておくとよさげ。'GOOGLEBOT')){Configure::write('Config.language',"ja");}GOOGLEBOTは当然GoogleのクローラのUAです。他のエンジンにも対応したい場合は、同じようにUAを調べて条件分岐に追加すればOKです。言語切り替えの方法はConfig.languageを設定することになります。問題になるのが、検索エンジンがクロールした内容と大きく変わる内容を、サイトアクセス時に返して検索結果を汚す、なんて話がありますが、今回のように表示言語を切り替えるくらいだと問題にはならないはずです。23:56phpレコードサイズが大きくなってくるとhasOneやbelongsToのアソシエーションでかなり時間を食うときがあります。<Table>して、結合した結果を舐めて時間が食われます。Joinになってるんですね。クエリ凝視するまで気づかなかった。Join)にするだけでレスポンス速度は大きく変わります。方法はModelでアソシエーション対象Model名のtypeを"INNER"にするだけ。);}?&gt;こういうテクはもちろんケースバイケースですけど、意外に盲点なチューニング方法かもしれません。23:50php文章中のキーワード抽出を行いたくなっていろいろ調べていて、次の組み合わせで実現することができました。MecabLingua::JA::SummarizePecl/PerlMecabは文書の形態素解析に。Lingua::JA::Summarizeはサイボウズラボ奥さんのキーワード抽出CPANモジュール。これをCakePHPに組み込みたかったのでPeclのPerlライブラリ(PHPからPerlのコードをダイレクトに呼べる)。導入も特に難しくないので、その導入メモを残しておきます。MecabFedora系Linuxだとyumで辞書ファイルも一緒にさっくりインストールできます。Perlのモジュールも入れておきます。installします。あと、実行時エラーも出たので、次のようにインストールすると回避できました。shell'と、しています。Lingua::JA::SummarizePecl/PerlこれもpeclコマンドでOKです。次のものをインストールしておいたほうがいいかも。perl-\*」はちょっと強引すぎる気が自分でもしてるのですが、何かしらのperl系モジュールがないとpecl/perlのインストールにコケてしまったことは確か。(このあたりの詳細のメモを失念。pecl/perlまた、extensionにperl.soを登録します。/etc/php.d/perl.iniで、次の1行を追加。extension=perl.soこれで、Apacheを再起動するとPHPでキーワード抽出が可能になります。Lingua/JA/ディレクトリを作成し、そこにSummarize.phpを作成します。$maxNum));}}?&gt;これをapp/config/bootsrrap.phpで読み込ませます。次の1行を最後に追加。'Summarize.php'));これでキーワード抽出用のモジュールSummarizeが読み込まれるので、たとえばControllerで次のような処理を行うことができます。$num);$wordは抽出対象の文章、$numは抽出キーワード数です。$keysは抽出されたキーワードの配列が返ります。返ってくるキーワードの抽出に違和感があれば、Summarize.phpのdefault_cost、singlechar_factorあたりをチューニングしてみましょう。このあたりのパラメータについては奥さんのドキュメントが最も分かりやすくまとまっていると思います。18:29php1.2だとBasic認証対応ページを作るのも超簡単です。対応させたいControllerにSecurityコンポーネントを適用まずSecurityコンポーネントを利用します。}認証情報を追加beforeFilterに認証に必要な情報を追加します。Pass:katsukatsuの認証情報で、全アクションで認証を必要とさせています。認証を特定のアクションのみに限定させたいときは、requireLoginメソッドで、認証を実行するアクション名のリストを指定します。基本的には必要なことはこれだけです。事項としてFormを必要とするView、たとえば何らかのPostを実行するようなFormのViewがあるときに、そのFormを構成する要素はすべてFormヘルパを利用する必要があるということです。array('action'=>'add')))?&gt;じゃなければダメです。(こうしないと認証がかからない)これはどうもヘルパを利用すると、Tokenのようなものを全要素に対して自動的に追加して、このTokenがちゃんと追加されていないとSecurityコンポーネントが働かないようです。「formタグくらいどうでもいいだろー」とタカをくくってて、痛い目にあったので皆さんもご注意ください。00:40php少し遅れましたが、先週末にトライコーンさんで開かれたCakePHP勉強会に参加してきました。PHPな方々のコミュニティに参加するのは初めて。JSerと比べると割とおとなしめ?でも、勉強会が定員オーバーになるまでの時間が回を重ねるごとにものすごい勢いで短くなっているので、皆さん静かな中に熱いものがある様子。以下、簡単なレポートです。使った効率的なPC・モバイルサイト構築について画像認識エンジンを組み合わせたWebサービス「フェイス女学院」ができるまでの話。携帯サイトの構築ネタは今後かなり盛り上がってきそうな気がします。そんな中、フェイス女学院はlayoutでキャリアごとのHTMLを切り分ける、というテクで乗り切ったとか。以前に自分が携帯サイト作ったときはCakeのようなフレームワークは使わずにSmartyでオレオレフレームワークを作って乗り切ったのを思い出しました。画像認識エンジンのOpenCVとやらも気になりました。これか!あと、TVの影響はかなり大きいんだな、と再確認。TVてやっぱまだまだ一番のメディアですね。CakePHPでの失敗談バッドノウハウというか、世間では笑い話(常識?)なのかもしれないけども、普通に初めて知ったこともかなりありました。Setクラス,な下りはよく分かっていないので復習。ホッテントリメーカー@CakePHP(仮)まわりがCakeCake言ってるので流れに乗ったそうな。そんな僕も同じクチです。最初は勉強会に行っても全然分からなかったけど、そのうちに使えるようになったとか。サービスに特化した苦労話やら、工夫点なんかを聞かせていただけたらなぁとも思いました。「stableがstableじゃない」に笑った。Editor周りの話でEmacsか、Vimか?な話になってVImが一番多かった。秀丸派はぜんぜんいないのが意外。僕は普段LLはもっぱら秀丸なんですけどね。Ustreamのチャットでakiyanさんが「僕、秀丸派ですよ!」みたいな主張をされてたのがちょっとツボに。AuthComponentをOpenID対応CakeでOpenID導入。OpenIDの統合は前からかなり興味ある話だったので結構惹かれる話でした。LTでかなりまとめて話されてたかと思うのですが、結構簡単に導入できそうな感じ。ソース公開されているので、あとでチェック。CakeでTestちゃんとしたテストコードはなかなか書けていないので、普通に役立ちました。SimpleTestを使えばよさそう。あと本家のテストコードを読んだ方がうやむやにされてるAPIとか関数の使い方をうまく理解できそうです。実際1.2のvendor周りの仕様がよくわかんなくて、このあたりはテストコードで理解できました。CakePHPとsymfonysymfonyの公式アプリ?のaskeetをCakeに移植する話。Cakeでは複合PKが使えないけど、Symfonyはそうじゃない。Cakeではクラスごとにいろんなメソッドが用意されているのに比べてSymfonyではグローバルな関数がいろいろ用意されてある、Cakeは配列ベースでSymfonyはオブジェクトベース、Cakeは細かいクエリを投げまくってSymfonyはまじめにJOINする、など、Symfonyの話はまったく知らなかったので、比較対象としていい話でした。Cake1.2みたい。この辺り、速度向上ネタも、今後は聞いてみたいですね。まとめShibuya.JSなんかは「なんですかそれw」みたいなネタが結構多いのですが、Cake勉強会では「あるある」と思えるネタも多くて分かりやすい話も多かったのが印象的でした。全般的に「どう使うか?」と「どう使いこなすか?」のネタの割合が半々くらいだった気がしたので、今度は後者の話をもっと聞きたいな、とも思います。パフォーマンス関連のネタとか。(他力本願)あと、CakePHPのディベロッパのgwooさんも次回は参加したいとの表明をされているようで、そのあたりの動向も気になるところです。質の高いインプットが多かったので次回もぜひ参加してみたいですね。01:07phpCakePHPも1.2になって、findAllが非推奨になってfind('All')に置き換わったように、findHoge系なメソッドは全部findに集約して、第一引数でそのselectタイプを指定するように仕様が変更になりました。最初はこの流れはちょっと面倒くさいなぁとも思ったのですが、実際は自分の都合のいいようなタイプをどんどん追加しやすくなっているので、この仕掛けはうまく使えばすごく便利。タイトルのようなもの。あるUserテーブルの中からランダムに50人分のレコードを取り出すfind('random')とか実装したいときはこんな感じ。$queryData);}}}?&gt;$typeで追加したいタイプを指定してswitchで振り分け、defaultのタイプについては親クラスのfindにそのまま処理を丸投げすることで、シンプルな機能拡張ができます。rand()"でランダムに並び替えができるので、これを利用して先頭50件を取得しています。単純にランダムにするだけだとlimitはもちろんなしでOK。これ見たら分かると思いますけど、すごく簡単に機能拡張できるのがいいかんじ。最新20件を取得する「find('latest')」や、人気の20件を取得する「find('popular')」みたいなメソッドとか作っておくと、使い回し効きそう。ところで上で例で挙げたレコードのランダム取得とか、ついfind('All')でとりあえず全件取得してからcontrollerでごちゃごちゃした処理をかいたり、find('All')の第二引数で技巧的なオプションをつけてみたりしがちだけども、あらかじめメソッドを追加しておいたModelに丸投げしておくとcontrollerがすっきりシンプルになって、結果的に可読性もあがってよさげ。自分もfindの後でごちゃごちゃした処理をよく書いていたので、これを機にModelに処理を任せるようにいろいろリファクタリングしようと思います。C7Y)」がすごくいい話で、さらにSooeyさんがこれを和訳してくださってるのが素晴らしくいい感じ。Cakeに限らずMVCモデルなフレームワークの一般的な話としても通じる話だとお思うので、このあたりに携わる人とすれば一度目を通しておいて損はないと思います。23:38php(追記:2008/06/20)この内容は表現に不十分な点があります。文末に情報を追記しています。CakePHPではControllerがみつからない、Viewが無い、なんかのエラーページは、CakePHP1.1ではapp/views/errorにmissing_action.thtmlmissing_controller.thtmlmissing_view.thtmlなんかを用意しておけばカスタムエラーページを表示することができて、露骨に「loginのviewがありません><」みたいなエラーが表示されてセキュリティホールになりうることを回避できます。このviewの命名規則はCakePHP1.2も同じでmissing_action.ctpmissing_controller.ctpmissing_view.ctpを用意しておけばOKです。共通処理についての仕様変更さて、これらのviewに共通の変数を利用する場合、たとえばログインしているときのログイン名をヘッダに表示するなんてことをエラーページにも適用したい、という場面は当然あると思います。その場合、app/app_controller.phpを用意しておいて、beforeFilterで変数をセットしておけばありとあらゆるviewで適用できます。こんな形にしておけば全viewで$my_nameで名前の表示が行えます。set('my_name',$my_name);}}?&gt;ところが、1.2ではこの方法ではエラーページにかぎって名前が取得できません。他のAppControllerを継承したコントローラのページでは取得できるので、どうやらエラーページではAppControllerを継承していないor処理がスルーされている様子。いうわけでエラーページの仕様が変わっているようなので、いろいろと調べてみるとエラーページはcake/libs/error.phpをコピーしてapp/error.phpに配置してあげると、エラー発生時に独自のハンドリングが行える模様。ファイルをコピーしてからapp/error.phpを開いてみるとこんな感じの記述が。'errors'));...そう、app_controllerをimportして、そのコンストラクタを作成しているような様子です。関わらずbeforeFilterが適用されていないようなので、強制的に呼び出してあげればよさそうです。上のコードに次の1行を付け加えます。'errors'));$this-&gt;controller-&gt;beforeFilter();...これでエラーページでも名前を表示することができました。書き終わりました)2008.06.18現在、CakePHP1.2のrc版がリリースされてあり、1.1でアプリケーションを作っていた人もそろそろ1.2に上げようかな、、なんて思っているんじゃないかと思います。最近仕事でさくっとCakePHP1.1で作ったサイトがあったのですが、リリースが落ち着いた瞬間を狙って一気に1.2に上げてみました。そのときのメモを残しておきます。RC1を利用しています。この移行作業は「とりあえず警告が出ないレベルで正常動作する」ことを目的にして作業を行っています。実際は非推奨の方法も混ざっていることもあるかと思いますが、ご注意ください。cakeディレクトリここは全部丸ごと入れ替えます。オリジナルのcakeディレクトリ丸ごと削除→1.2のcakeディレクトリをコピー。viewファイルの拡張子を変更1.1のときのviewのファイルの拡張子は.thtmlでしたが、1.2になって.ctpに変わっています。1ファイルづつ変更していても疲れるのでこんな感じで一気に変換します。?&gt;に変わっています。ここで、とりあえず$htmlから$formにだけ変更しておきます。RC1現在、$html変数を利用すると警告が出ますが、$html->inputの引数のフォーマットは1.1のままでも怒られないようです。これは秀丸のgrep置換などを利用して一気にやってしまいましょう。app/config/routes.phpconfig系も記述の仕方が変更になっている点が多いです。routes.phpはRouteオブジェクトがRouterクラスに変更になっています。元のapp/config/routes.phpを次のように変更します。'home'));app/config/core.phpcore.phpはdefineで定義していたものがConfigureクラスを利用するようにします。元のapp/config/core.phpを次のように変更します。0);ただし、基本的にはcore.phpに関しては1.2で内容がかなり変わっているので、実際は変更作業を行うよりも、1.2オリジナルのものを利用した方がよさそうです。アプリケーション固有の定数アプリケーション特有の定数宣言はどうするのがベストプラクティスなのか分かっていませんが、僕は1.1の時にはapp/config/app.phpと専用のファイルを作成して、defineで定義していたものを用意していたので、これをそのまま流用するためにbootstrap.phpからincludeさせています。Configure::writeで定義させる方法を利用した方がいいのかもしれません。(ご存知の方は教えていただければ幸いです)Vendor系ライブラリサードパーティなライブラリはapp/vendorsに配置させてapp/config/bootstrap.phpからロードさせると思うのですが、ここでのロード方法も変更になっています。僕はdBugライブラリを利用しているので、これをapp/vendors/dBug/dBug.phpに配置しているのですが、このロード方法について、次のように変更になっています。);どうも1.2になってキャメルケースの名前を発見すると自動的にアンダースコアをつけて解釈しちゃうようです。'SMTP');と、書いた場合はapp/vendors/s_m_t_p.phpを見に行ってしまうようです(超厄介。)サードパーティ製のライブラリについてはこのキャメルケースの解釈は勘弁してほしいんですけども、そうは言っていられないので、上でかいたほうに、arrayでフルパスを指定することでこの仕様を回避しています。まとめ手元の環境ではこんな感じの移行作業で動作しました。ある程度予想はしていたものの、やっぱり実際に作業してみると結構時間がかかりましたね。定義系の表記法法の仕様変更を追いかけるのに苦労しました。実際に移行作業をしてみると1.2の方が圧倒的に多機能で拡張性も豊かなので、移行のメリットは充分にあるかと思います。追記)タイトルのスペルが間違っていたので訂正しました。パーマリンク名も間違ってる。これは仕方なくこのままにしておきます。orz最近memcachedを使うことがあったので、使えるようになるまでの個人的メモです。peclコマンドだけでインストールは可能です。対象OSはFedora8です。memcahceこんな感じでインストールはOKです。あとはmemcache.soをロードするように設定します。php.iniを直接編集してもいいのですが、extension系は/etc/php.d/に別途iniファイルを用意しておいた方が管理しやすいかもです。/etc/php.d/memcache.iniで、extension=memcache.soの1行だけ書いたファイルを作成して、保存。onで、デーモンとして登録しておくと便利です。ラッパクラスpeclの関数をそのまま利用してもいいのでしすが、ラッパ関数を作成してもいいかもです。僕はこんな感じのものを作成しました。MEMCACHED_SERVER_PORTは適当な値に置き換えてください。11211番ポートになるはず。}?&gt;そうした後で、こんな感じで使います。'jkondo'このMemcacheManagerみたいなクラスを用意しておくと、memcachedが公式にはサポートされていないCakePHP1.1なんかでもvendorsディレクトリあたりに入れておくと、そのまま使えてしまうので結構便利。13:42php個人的なメモです。モジュールのインストール方法。手元のテスト環境でphpのバージョンをupgradeさせるのが面倒そうだったのでPECLでインストールしました。標準でロードするextension=json.so上書きしたらhttpdを再起動するとOK。json_decode($str)の関数が標準で使えるようになります。02:03php「そんなのできたらOS毎に分けたHTMLを出力するとき、無駄なdocument.write()だらけにならずに便利なのに、、、」と思ったのですが、よくよく考えたらUserAgent見たらできそう。いうわけでPHPで書いてみました。Windows!');}?&gt;超簡単。UA送ってくれてたらブラウザ判定もいけます。「UA偽装されたら、、」とかな話もあるけど、JSに頼らず"そこそこの信頼度"で知れることも大事かな、と。あと、サーバサイドで判定していたらSmartyなんかのテンプレートシステムでコード分けがものすごくシンプルになります。User&lt;/h1&gt;{/if}こんな感じでtplファイルに書けます。User&lt;/h1&gt;');}こんな感じですかね。クライアントサイドでの判別方法の実装側の問題点として、ソース内のHTMLの実体が文字列ばっかりになっちゃって何だか分からなくなること多いこと。タグが入れ子になってきたらよくミスっちゃうことも多いはず。いうわけで、ずっとクライアントサイドに振るべきだと思われてた仕事も、サーバ側に振れる仕事は振っちゃってもいいのかな、と思いました。23:47php最近、新規プロジェクト案件で携帯サイトの構築についていろいろ調査をしています。最初から携帯サイトの構築については、かなりいろいろな点で懸念はしていたのですが、蓋を開けてみると「やはり、、」と、いうかハマる点がかなり多いです。そもそも、今回のプロジェクトにおいていろいろなサイトを調査していたのですが、まだまだPCサイト(XHTML+CSS+JavaScriptなサイト)に比べて、有益な情報がまとまっていないなぁ、、という感想です。ウノウラボさんは本当に素晴らしい情報を開示してくださっていると思いましたが、かゆいところに手が届くような情報はまだまだ世の中に広がっていないようですので、僕が調べた点や、実装を進める上で得たTipsなどを共有していきたいと思います。そこで、今回はPHPで携帯サイトを実装する上でのTipsを記しておきたいと思います。02:32phpWeb屋泣かせの話として、ユーザの入力文字を表示する際に、ユーザがありえないような長い文字を入力してページレイアウトを崩れさせる、な話があるかと思います。全角文字の場合はCSSで表示ブロック要素に対してwidthをちゃんと定義しておくと崩れることはそうそう無いと思うのですが、問題は半角英数文字の場合。イジワルをしなくても長いパラメータが付いたURLなんかの場合は、意図せずともこんな場面に出くわすことになるかと思います。そこで超便利なタグでwbrというタグがあります。仕様には無い拡張仕様なんですけども、そこが目をつぶれる場合ならかなり有効です。01:52phpWebアプリケーションにおいてffmpegを利用してメディアファイルをゴニョゴニョ操作する、なんて場面がここ最近増えてきていると思います。そんな中、ハマるポイントとして、ログの扱いがあると思います。barこれで変換できます。(Codecの指定なんかはここでは割愛します。)なので、これをPHPから実行する場合はこんな形になります。外部プログラムを実行するのでexec関数を利用します。$out);?&gt;では、ここで実行時のログを保存したい、とします。execは第二引数に標準出力の結果を配列で受け取ることができるので、普通に考えると次のようになります。logvar_dump($log);?&gt;さて、どうでしょうか?実はこれでは正しい結果は出力されません。試してみると分かるのですが、実は上記のコードを実行すると、結果の冒頭2行分しか$logには格納されていません。次のような文字列が出力されたと思います。3.2.3-56.fc5)これはffmpegを利用した際に必ず出力されるログです。「いや、本当に俺が必要なのはその次からのコードなんだよ!!」と叫びたくなるのですが、なぜか微妙なところで出力は終わってしまいます。19:50phpPHPで公開鍵暗号を利用する場合、PEARのCrypt_RSAが利用できます。関数があるのですが、手元の環境では動きませんでした。原因はundefinedな配列を操作しているみたいで。いうわけで以下、修正方法。ArchiveAboutこのBlogはクックパッドに勤めるWebエンジニアがLLネタや情報技術について直感で思ったことを何も考えず発信するサイトです。コメントやお問い合わせ、執筆依頼などは@ryo_katsuma宛のmention、またはメールなどでお待ちしています。