2011/11/30

[CakePHP] 子・孫まで。複数の入れ子になったモデルを連結して取得したい

cakePHPでデータを取得する際にhasManyなどの子のモデルに、更に孫のモデルをくっつけて取得したくなった。

・モデルで指定する場合
  1. $recursive = 2; //これで2階層目まで取得する  

・コントローラで指定する場合
  1. $this->Model->find('first'array('recursive' => 2);  
両方とも、数字を変更すれば取得しにいく階層の深さが変わる

参考:
CakePHPで3つ以上の複数テーブルを結合

[iPhone] タッチイベントとクリックイベント

iPhoneではタッチイベント→クリックイベントの順に処理されるみたい。

スマートフォン向けサイトで「ページ上部に戻る」ボタンを置いた。
クリックイベントだとAndroidでもっさりな動作に感じるので、touchendイベントで反応するようにした。

touchendイベント

ページ上部にスクロール

clickイベント

スクロールしてるから、クリックした場所にはすでに別のモノが…

その別のモノをクリック!

って感じになった。

なので今回はクリックイベントのみ処理するように変更した。

タッチエンドイベントをクリックイベントがわりにするとこまごまと引っかかる。
まあ、対処できないようなことではないのでいいんだけど…。

[CakePHP] 404ページを表示したい

CakePHPで404ページを出したい時は…

/app/view/errosディレクトリにerror404.ctpファイルを設置する。

だけ。


レイアウトを変更したい場合なんかは、app直下にerror.phpというファイルを作って、その中で色々と処理をすればいいらしい

コントローラー側では
  1. $this->cakeError('error404');  
と書く。

参考:
CakePHPで404エラー画面を作る

cakeのバージョンは1.3です

2011/11/28

ログを残すなら正常時でもログを残そう

バカみたいな話なんだけど…。

cronで毎日、データベース内で不要になったレコードを削除する処理をしていた。
処理が正常に動いているのは確認できていたので、レコードの不具合など、予想外のエラー時のみログを残すようにしていた。
それだと正常に削除されていた場合は記録が残さない。
なので、あるレコードが削除された日時を知りたいという話になって困った。

なぜ正常時のログを残さなかったのが、自分でも思い出せないんだけど…。
もしかして、ログのファイルがでかくなるのが嫌だとかそんな理由だったのかも。

一応何度も同じミスをする自分宛にメモ

2011/11/25

[JavaScript] スクロールの終了時にイベントを起動する

JavaScriptでスクロールが終わった時に、なにか処理をしたい時がある。
要はスクロールするとついてくるメニューの処理みたいな感じ
ああいうのはスクロール中もついてくるけど、今回のは終わるまで何もしない。

スマートフォン向けにブラウザの下部に出てくるバナーなんかで、スクロールすると消えて、スクロールが止まると表示されるやつ、あんな感じ。
  1. var timeId;  
  2.   
  3. window.addEventListener("scroll"function(){  
  4.   
  5.  //解除  
  6.  clearTimeout(timeId);  
  7.   
  8.  //時間をリセットしてセットし直す  
  9.  timeId = setTimeout(function(){  
  10.   //処理  
  11.  }, 500);  
  12. });  
  13.   
  14. //最初に一回動かす  
  15. timeId = setTimeout(function(){  
  16.  //処理  
  17. }, 0);  

iPhoneからのメールをデコードするとタイトルが文字化けする

メールで投稿できるブログシステムみたいなやつで文字化けすることがあるというので対応した。

文字化けするのはiPhoneからのメール
受信したメールを分解して処理しているのはPEARのMail_mimeDecode

調べてみるとiPhoneで送られるメールのタイトルと本文で文字コードが違うことが原因だった
Mail_mimeDecodeだとタイトルの文字コードは本文と同じものとして処理しているのかも。

結局Mail_mimeDecodeではなくZend_Mail_Partを使うことにした

参考:
iPhoneから送ったメールが文字化けする問題について

2011/11/24

高速化のためだけにアプリケーションキャッシュを使ってもいいのかな?

HTML5の新機能で、Webアプリケーションをオフラインでも使えるようにするための機能としてアプリケーションキャッシュってのがある。

必要なファイルをブラウザ側でキャッシュさせて、インターネットでファイルを読み込むんじゃなくて、キャッシュさせたファイルを利用する。

スマートフォン向けのサイトを作っていて、オフラインで使ってもらうことは考えてないんだけど、アイコン画像とかJavaScript、Cssファイルなんかもキャッシュさせとくと、ものすごく高速化できる。
通常の電話回線でもwifi以上の体感スピード。

でも、この高速のためにファイルをキャッシュさせるってのは、もともとのオフラインでアプリケーションを利用できるようにするための機能ってのとは全然違う使い方なんだけど…

いいのか?
うーん…わからん


参考:
[HTML5] アプリケーションキャッシュの使い方

[WordPress] 一覧ページで前後のページへのリンクを出す

記事の一覧ページなんかで、「次のページ」とか、「古い記事へ」とかのリンクを出したい。
ブログなんかには当然のあるやつ。
next_posts_linkとprevious_posts_linkを使う

  1. previous_posts_link('<<新しい記事を見る');  
  2. next_posts_link('古い記事を見る>>');  

2011/11/18

MooToolsでAjaxする方法

MooToolsでAjaxをするにはRequestを使う。
  1. //まずは設定  
  2. var req = new Request({   
  3.  url: "/sample/dir" ,  
  4.  onSuccess: function(res){  
  5.   //成功時  
  6.  },  
  7.  onFailure: function(xhr){  
  8.   //失敗時  
  9.  }  
  10. });  
  11.   
  12. //通信開始  
  13. req.send();  

■画像、JavaScrip、cssを動的に読み込む
JavaScript、css、画像などを動的に読み込みたい場合はAssetsというのもある。
これはmootools-coreには入っていないのでmoreを別途入れないと使えない
こっちはXMLHttpRequestで通信するのではなくて、エレメントを作ってる
  1. //取得するだけなのでnewしない。  
  2. //image要素が返ってくる  
  3. var myImage = Asset.image(画像へのパス);  
  4.   
  5. //script要素が返ってくる  
  6. var myJs = Asset.javascript(ファイルへのパス);  
  7.   
  8. //link要素が返ってくる  
  9. var myJs = Asset.css(ファイルへのパス);  


参考:
MooTools基礎文法最速マスター
Assetsメソッド: javascript

2011/11/16

スマートフォンのユーザビリティ

スマートフォンのユーザビリティに関して、参考になる記事があったのでメモ

スマートフォンサイトに適したユーザビリティとは?【リサーチ】

要点は

・タブは強調することで「迷わず操作できる」「見やすい」印象に
タブの文字色だけでなく、タブの高さ変えた方がよい


・アコーディオンがある場合は、左側にナビゲーションを設置した方がわかりやすい
アコーディオンを表すボタンはその枠の左側に置く
「+」と「▼」だと差はない


・複数のバナーをフリック機能を用いて見せる場合、一度に表示させるバナーの数は1つが「操作しやすく」「押しやすい」
フリックよりも「次」「前」ボタン
次のバナーが小さく出てたり…よりも1つだけ出てるほうがよい


・小バナーは順次見せるよりも、セットで切り替わる方が「文字が見やすく」「負担を感じない」
ヤフーのスマートフォンサイトのバナーみたいなやつかな
バナーが3つ出てる状態で、「次へ」ボタンを押した時に3つとも入れ替わるほうがよい


・サブウィンドウを表示させる場合、スライド形式によって表示するよりもモーダルウィンドウ形式の方が支持されている
jQuery Mobileは横スライドで、iPhoneは下から系が多いイメージだけど、モーダルがいいのか。
PCのイメージと近いのかも


・サブメニューを表示させる場合、アコーディオン形式で表示した方が「リンク・ボタンが押しやすく」「操作しやすい」
コンテンツの上にかぶせて表示させるよりも、コンテンツをずらして、メニューを表示させる枠を作ったほうがよい


うーむ。参考になった
PCよりも直感的な動作になる分、わかりづらいとか使いづらいがストレスになりそう

[CakePHP] コントローラー内で共通の処理をまとめる

コントローラー内で共通の処理をまとめることができる

1.beforeFilter()
それぞれのアクションが実行される前に呼び出される

2.beforeRender()
アクションを実行した後に呼び出される

3.afterFilter()
レンダリングも終了した後で呼び出される


呼ばれる順番は
beforeFilter()

アクション

beforeRender()

レンダリング

afterFilter()

[PHP] file_get_contents でタイムアウトする時間を設定する


file_get_contentsでhttp://から指定したURLを読み込む時に、読み込みたいページからレスポンスがないと、プログラムがそこで止まってしまう。

デフォルトの設定だと60秒とかになってるんで、まあ、待つ人おらんよね。

今回はタイムアウトする時間を変更して対応した。
  1. //後で戻せるように設定を取得しておく  
  2. $org_timeout = ini_get('default_socket_timeout');  
  3.   
  4. //5秒以上かかったらタイムアウトする設定に変更  
  5. $timeout_second = 5;  
  6. ini_set('default_socket_timeout'$timeout_second);  
  7.   
  8. $data = file_get_contents($url);  
  9.   
  10. //設定を戻す  
  11. ini_set('default_socket_timeout'$org_timeout);  


ini_set以外の方法を教えてくれているページがありましたので、参考に↓
[PHP]file_get_contentsのタイムアウトの制御とかレスポンスヘッダのバッドノウハウ

2011/11/15

jmeterでモバイルサイトのセッションを使う

スマートフォン移行が進んで、最近はずいぶん少なくなって来たのかもしれないけど、モバイル向けサイトでは、cookieが使えない機種に対応するため、URLにセッションIDを付けてページ遷移させることも多い

http://sample.com/?sid=***************

みたいなやつ。


こういう仕様のサイトをjmeterでテストする場合。
「HTTPクッキマネージャー」を使ってもセッションが切れてしまう。
セッションIDを前もって指定できれば楽なんだけど、それってできない…よね?
なので、リダイレクトなどするページを使ってセッションIDを取得する。
どこかリダイレクトするページを「HTTPサンプラー」で読み込む
リダイレクトされると、セッションIDがついているので、「正規表現抽出」でセッションIDを取得して、その後セッションを使うページを読み込む時にパラメータでセッションIDを追加すればOK。

[CakePHP] urlで渡されたクエリパラメーターの値を取得する

CakePHPでURLで渡されたパラメーターの値をコントローラーで取る方法

http://sample.com?value=100
↑の100って値を取得したい場合

$this->params
にいろんなパラメーターが入っている

URLで渡されたデータは
$this->params['url']
で取れる

上の場合だと
$this->params['url']['value']; //100


他にもう一つ
http://sample.com/10/12
みたいに値だけ渡すことも可能

その場合は

  1. public function action($param1$param2){  
  2.  //ここで処理  
  3. }  
というふうにコントローラーのメソッドの引数で受け取れる

2011/11/14

[Android] Androidのuseragent一覧

Androidのブラウザはバージョンによって、細かく違いがあって、なかなか大変だ…
ある動画サービスを使ってみたんだけど、2.3だと動画が見れるけど、2.2だと再生できない。
もとの動画はmp4なので、再生できそうなんだけど、コントローラーが表示されない。

自前でコントローラー作らないとだめかもなー。

useragent switcherなどでAndroid用画面を見る用に、Androidのユーザーエージェントをまとめてくれてる人がいたのでリンク↓↓

参考:
http://team-pag.interprism.co.jp/member/noguchi/data/
http://pwiki.awm.jp/~yoya/?Android/UserAgent

2011/11/11

[JavaScript] スマートフォンでのselectのchangeイベントのタイミング

スマートフォンのフォームのselectタグのUIって選びやすくていい。
iPhoneだと画面下から選択項目がでてくるやつね。

で、それを変更した時のonchangeイベントのタイミング

iPhoneの場合
項目を選択して、決定を押した時


Android 2.3の場合
項目を選択した時 (決定?完了?ボタンを押す前)

なのでAndroidの場合、画面下部に選択項目が出てる状態でonchangeイベントが起きる。

「決定」を押した時のイベントはなんになるんだ?

2011/11/10

[JavaScript] 配列の中から最大値を取得する

phpのmax()みたいな関数が必要になったので調べてみたらあった。

  1. var data = [3, 9, 1 , 4];  
  2. var max = Math.max.apply(null, data);  
  3. //max = 9  

applyってのは関数の中で第1引数をthisとして、第2引数を引数として処理してくれる。
Math.maxの中ではthisは使わないので、何でもいい。簡単なのでnull。
第2引数の配列を引数として処理するので、

Max.max(3,9,1,4);
と同じ処理になる


参考:【javascript】配列の値の中から、最大値、最小値を求める(配列を引数に展開する)

2011/11/08

[JavaScript] querySelectorAllなどで取得するNodeListと配列を判定する

jQueryなんかのライブラリを使ってる場合は必要ないかも…

自作でjQueryとかのeach関数みたいなやつを作った時にちょっとひっかかったのでメモ

instanceof Arrayだけで判定するとquerySelectorAllで取得できるNodeListはfalseになる。

配列 or NodeListを判定するには
if(valinstanceof Array || (val.item !== void 0 && val.length !== void 0))




ちなみに自作のeach関数みたいなやつ

  1. var each = function(val, fnc){  
  2.   if(val instanceof Array || (val.item !== void 0 && val.length !== void 0)){  
  3.   
  4.   
  5.     //配列 or NodeListが渡された時の処理  
  6.     
  7.     for(var i = 0, len = val.length; i < len; i++){  
  8.       //処理  
  9.       fnc(val[i]);  
  10.     }  
  11.   }else{  
  12.   
  13.   
  14.     //単数で渡された時の処理  
  15.     fnc(val);  
  16.   }  
  17. }  

Twitter で複数の条件で検索した結果を表示する

最近、制作するページにTwitterを表示したいって話があった
できればハッシュタグでやりたかったんだけど、あまり使われんかった…

なので、複数のキーワードのどれかにひっかかった結果を表示することになった
やり方は…

キーワード1 OR キーワード2 OR キーワード3

って書くだけ。

参考:これだけは覚えておきたい、Twitter検索で使える便利なオプションまとめ

Twitterウィジェットでも同じように使えた
Twitterウィジェット

2011/11/04

[SQL] WHERE句ではSELECT句でつくったカラム名は使えない

深く考えたことなく使っていたので、言われてみれば、ああそうなんだという感じ。

SELECT句で命名したカラムはWHERE句で使えない

SELECT id, end - start AS diff
FROM table
WHERE diff > 3; //ここでエラー

↑だとエラーになる。

なんでかというと…
SQLには各句の解釈される順番があって
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY
という順序だから

WHEREでカラム名を指定しても、SELECTはまだ解釈されてないから、そんなカラムないよってことになる

上の例でいうと

SELECT id, end - start AS diff
FROM table
ORDER BY diff DESC;

は可能

考えたことなく使ってたなー


参考:

2011/11/02

[JavaScript] 配列かどうか判定する

JavaScriptで、ある変数が配列かどうか判定することがよくある。
判定は[ instanceof Array ]でできる


  1. if(val instanceof Array){  
  2.   //配列だった場合  
  3. }else{  
  4.   //配列じゃなかった場合  
  5. }  


渡された引数が単数でも配列でも同じように処理できるようにする時とか

  1. function fnc(val){  
  2.   val = (val instanceof Array) ? val : [val];  
  3.   
  4.   
  5.   for(var i = 0, length = val.length;  i < length; i++){  
  6.      //処理  
  7.   }  
  8. }  


querySelectorAllなどで取得できるNodeListも判定したい場合は「querySelectorAllなどで取得するNodeListと配列を判定する


参考:
JavaScriptパフォーマンス改善(3) オブジェクトが配列かどうか判定する方法

[JavaScript] 確認用のダイアログを出す

なぜかいつも忘れてしまうのでメモ

何かボタンなどをクリックした時に「○○してもいいですか?」というダイアログが出てきて、「OK」を押すと、その処理を行なって、「キャンセル」を押すと何もしないというアレ。

  1. if(window.confirm(確認用メッセージ)){  
  2.   //OKの場合の処理  
  3. }else{  
  4.   //キャンセルの場合の処理  
  5. }  


スマートフォンのダイアログの外観は味気ないものじゃないのでありがたい


参考:
確認ダイアログを表示する