スクロールに合わせて移動

Posted by muchag | CSS | 2011-05-31 (火) 20:54:53
状況

ネットサーフィンをしていると
縦スクロールに合わせて
メニューやら広告やらが移動するページがある。
 

システム

というか、移動しているのはスクロールしている本体の方で
メニューやら広告は、それに合わせて移動せずに
定位置を保っている、というのが現実。

要は、そのオブジェクトを
ウィンドウに対して絶対位置で固定 している。
 

設定

よって

  1. <div id="sidebar">hoge</div>

に対して

  1. div#sidebar {
  2.     position: fixed;
  3. }

これで実現可能。

CSS | 2011-05-31 (火) 20:54:53 |

HTML 5 & CSS 3 ブラウザ対応状況

Posted by muchag | CSS3,HTML5 | 2011-05-31 (火) 19:18:55

FindMeByIP:HTML5 & CSS3 Support

CSS3,HTML5 | 2011-05-31 (火) 19:18:55 |

URL 取得

Posted by muchag | CakePHP | 2011-05-30 (月) 13:55:27

【環境】
[CakePHP] 1.3.8
前提

開発環境(XAMPP) localhost にて
myapp プロジェクト
◇┣ webroot
◇┣ app
◇┗ cake
というディレクトリ構成。

コントローラ
user_lists_controller.php

ビュー
list.ctp

引数
1
 

ビュー
  1. // webroot から見た webroot の相対 URL
  2. echo $html->webroot;
  3. echo $html->url('/');
  4. // /
  5.  
  6. // webroot から見た 現在のページ の相対 URL
  7. echo $this->here;
  8. echo $html->url('');
  9. // /user_lists/list/1
  10.  
  11. // webroot の絶対 URL
  12. echo $html->url('/', true);
  13. // http://localhost/
  14.  
  15. // 現在のページ の絶対 URL
  16. echo $html->url('', true);
  17. // http://localhost/user_lists/list/1
  18.  
  19. // ドメイン
  20. echo env('HTTP_HOST');
  21. // localhost
  22.  
  23. // IP アドレス
  24. echo env('REMOTE_ADDR');
  25. // 127.0.0.1
  26.  
  27. // webroot ディレクトリのパス
  28. echo env('DOCUMENT_ROOT');
  29. // J:/myapp/webroot
  30.  
  31. // FULL_BASE_URL
  32. echo FULL_BASE_URL;
  33. // http://localhost
  34.  
  35. // コントロール名
  36. echo $this->name;
  37. // UserLists
  38. echo $this->params['controller'];
  39. //user_lists
  40.  
  41. // アクション名
  42. echo $this->action;
  43. echo $this->params['action'];
  44. // menu

※ $html->url に関しては、Helper::url を利用しているため
$form->url, $ajax->url 等でも同様の結果を得る。
 

コントローラ
  1. // webroot から見た webroot の相対 URL
  2. $this->webroot;
  3. h( Router::url('/');
  4. // /
  5.  
  6. // webroot から見た 現在のページ の相対 URL
  7. $this->here;
  8. h( Router::url('');
  9. // /user_lists/list/1
  10.  
  11. // webroot の絶対 URL
  12. h( Router::url('/', true) );
  13. // http://localhost/
  14.  
  15. // 現在のページ の絶対 URL
  16. h( Router::url('', true) );
  17. // http://localhost/user_lists/list/1
  18.  
  19. // ドメイン
  20. env('HTTP_HOST');
  21. // localhost
  22.  
  23. // IP アドレス
  24. env('REMOTE_ADDR');
  25. // 127.0.0.1
  26.  
  27. // webroot ディレクトリのパス
  28. env('DOCUMENT_ROOT');
  29. // J:/myapp/webroot
  30.  
  31. // FULL_BASE_URL
  32. FULL_BASE_URL;
  33. // http://localhost
  34.  
  35. // コントロール名
  36. $this->name;
  37. // UserLists
  38. echo $this->params['controller'];
  39. //user_lists
  40.  
  41. // アクション名
  42. echo $this->action;
  43. echo $this->params['action'];
  44. // menu
CakePHP | 2011-05-30 (月) 13:55:27 |

helpers

Posted by muchag | CakePHP | 2011-05-30 (月) 1:55:20

【環境】
[CakePHP] 1.3.8
メソッド
  1. $html->url();

こんな記述を見かけたので

cake\libs\view\helpers\html.php

を覗いてみたが、どこにも url メソッドがない。
 

url メソッドの場所

あれれ、と思って継承を逆に辿ってみるとめっけた。

cake\libs\view\helper.php
  1. function url($url = null, $full = false) {
  2.     return h(Router::url($url, $full));
  3. }

最終的には

cake\libs\router.php
  1. function url($url = null, $full = false) {

からのパクリだったわけだけど
詰まるところ、url メソッドは、HTML ヘルパーではなく
ヘルパーの大元のメソッドだった。
 

表記の揺れ

んだば、と思い

  1. $form->url();

と記述してみたが、無事に同じ結果を出した。

なるほどねぇ。

みなさんには当たり前のことなのかもしれないけど
私にはちょっぴり楽しかった♪

そして、あちこちで見かける表記の揺れの原因もやっと理解できた。

CakePHP | 2011-05-30 (月) 1:55:20 |

$this->flash でリダイレクトしない

Posted by muchag | CakePHP | 2011-05-30 (月) 1:24:13

$this->flash にリダイレクト先を設定したのに
リダイレクトされずに困った。

【環境】
[CakePHP] 1.3.8
問題点
  1. $this->flash('削除しました', '/index');
  2. または
  3. $this->flash('削除しました', array('action => 'index') );

コントローラのアクション内でこのような設定をしてやると
ブランクページに「削除しました」とメッセージを表示し
index アクションへリダイレクトしてくれるはずであった。

ところが、何度試してもリダイレクトしない。
 

解決策

そこでグーグル先生に聞いてみたところ

app\config\core.php
  1. Configure::write('debug', 2);

これが 0 以外だとリダイレクトしないそうな。

確かに 0 にしてみたら、ちゃんとリダイレクトしてくれた。

でも、メッセージ表示時間が短すぎる・・・。
 

0 以外の場合

この情報を得てよく見てみたら
リダイレクトしないときは
「削除しました」
というメッセージに index アクションへのリンクが付いていた。

マウスオーバーしてみたら、確かに青文字下線付きになった。
けど・・・わかりにくいでしょ・・・。

CakePHP | 2011-05-30 (月) 1:24:13 |

save 後に id を得る

Posted by muchag | CakePHP | 2011-05-29 (日) 21:47:27

新規メンバーを登録直後に、当該メンバーの id を知りたいことはままある。

【環境】
[CakePHP] 1.3.8
  1. $this->(モデル名)->getLastInsertID();

で、取得可能。

User モデルに保存する作業と組み合わせて

  1. if ($this->User->save($this->data)) {
  2.     $this->set('id', $this->User->getLastInsertID() );
  3. }

こんな風に利用可能。

CakePHP | 2011-05-29 (日) 21:47:27 |

エラーメッセージとその対処法

Posted by muchag | CakePHP | 2011-05-29 (日) 21:34:25

相変わらずしょーもないことで時間を食う。。。
同じ間違いを繰り返したくないものですな。 😐

エラーメッセージを見てピンとこないものと記事にしたものをピックアップ。

【環境】
[CakePHP] 1.3.8
Notice (8): Array to string conversion [CORE\cake\libs\model\datasources\dbo_source.php, line 749]
Warning (512): SQL Error: 1054: Unknown column ‘Array’ in ‘field list’ [CORE\cake\libs\model\datasources\dbo_source.php, line 684]
状況

会員制のサイトでユーザプロフィール登録編集画面。

今まで問題のなかった登録編集処理で突然上述のメッセージが出
処理ができなかった。

今までと異なったのは、プロフィール画像を指定しなかったこと。
 

原因

ファイルが存在しないときの記述が抜けていたのが原因。

ファイルのアップロード処理をフォームに設置すると、当該項目には

  1. Array
  2. (
  3.     [name] =>
  4.     [type] =>
  5.     [tmp_name] =>
  6.     [error] =>
  7.     [size] =>
  8. )

これだけの情報が渡される。

ところが

  1. echo $form->file('image');

上記のようにフィールド指定でモデルと連携した登録処理をする場合

  1. $this->data['(モデル名=フォーム名)']['(フィールド名)'] =;

となるはずなので、ファイルアップロードのところを放置しておくと

  1. $this->data['(モデル名=フォーム名)']['image'] = 配列;

となってしまい、前述のような警告が出て、処理が止まる。

今まで稼動していたのは、ファイルが存在するときの処理は記述していたから。
つまり、ファイルが存在しないときの記述が抜けていたのが原因。
 

対処

ファイルが存在しないときの処理を付加。

CakePHP | 2011-05-29 (日) 21:34:25 |

paginator.php -> 検索条件の引継ぎ(GET)

Posted by muchag | CakePHP | 2011-05-29 (日) 15:10:27

paginator は便利なんだけど
検索条件は引き継げない。

そこで、検索条件を引き継いで paginator を利用する手法。
今回は、GET 送信にて条件を引き回す手法。

【環境】
[CakePHP] 1.3.8

なぜ GET 送信を選んだかというと
paginator では、ページ番号リンクやソート用リンクでは
条件を URL に名前付き引数として付記する手法が用いられているため
GET 送信にすれば、全部まとめて処理できると考えた。
 

経過分析

コントローラ内の処理では

  • 検索フォームから入力があった時
  • paginator からのページ遷移時
    • ページ番号もしくは「前へ」等の場合
    • ソートの場合

のように場合に分けて考えないといけない。
 

検索条件の取得
大前提
  • フォームの GET 送信は、URL に引数が付記される
    • CakePHP では、GET 送信時 $this->params[‘url’] に引数が格納される
  • paginator が作成するリンクは名前付き引数である
    • paginator が自動作成する引数は $this->passedArgs に格納される

上記より、検索条件は

  • $this->params[‘url’]
  • $this->passedArgs

のいずれかをチェックすればよいことになる。
 

具体例
list.ctp
  1. echo $form->create('User', array('type'=>'get'));
  2.  
  3. //「名前」で検索するテキストボックス
  4. echo $form->input('name');
  5.  
  6. echo $form->end('抽出');
  7.  
  8. /* リスト出力 */

今、上記のようなビューが存在するとする。
 

検索条件の設定

この場合、下記のようにすることで
フォームからもリンクからも条件を取得し
paginator に条件を引き渡すことができる。

users_controller.php
  1. // フォームからの送信があった場合
  2. if ( !empty($this->params['url']['data']['User']['name']) ) {
  3.     $this->paginate['conditions']['User.name LIKE'] = '%'.$this->params['url']['data']['User']['name'].'%';
  4. }
  5. // patinator が作成したリンクからきた場合
  6. elseif ( !empty($this->passedArgs['name']) ) {
  7.     $this->paginate['conditions']['User.name LIKE'] = '%'.$this->passedArgs['name'].'%';
  8. }

参考元サイトを初め、いくつか見たサイトでは6行目を if としていたが
今のところ elseif で問題はない。
 

サニタイズ

ユーザが指定する検索文言は、もちろんエスケープ処理をしないといけないので
サニタイズをかます。

ここで書くと面倒なので、完成例参照。
 

検索条件の引き継ぎ
$this->passedArgs

後述するが、$this->passedArgs はビューでも利用するので
フォームからのページ遷移でも $this->passedArgs の設定が必要。

そこで、上記例にその設定を差し込む。

users_controller.php
  1. // フォームからの送信があった場合
  2. if ( !empty($this->params['url']['data']['User']['name']) ) {
  3.     $this->paginate['conditions']['User.name LIKE'] = '%'.$this->params['url']['data']['User']['name'].'%';
  4.     $this->passedArgs['name'] = $this->params['url']['data']['User']['name'];
  5. }

4行目を追加。

参考元サイトを初め、多くのサイトで4行目を

  1. urlencode($this->passedArgs['name'] = $this->params['url']['data']['User']['name']);

としていたが、ここで urlencode を実行すると
paginator の WHERE 句のパラメータが、エンコードされた文字列になってしまうため
データ抽出が上手く作動しなかった。
 

テキストボックス

検索文言をテキストボックスに配置。

array(‘url’=>$this->passedArgs) に引き継いだ情報が入っているので

  1. echo $formEx->input('code', array('default'=>$this->passedArgs['name']) );

としてやればよさそうなものだが、
これをすると、検索文言がセットされていないときに

Notice (8): Undefined index: name

となってしまう。

そこで、予め変数を用意して初期化し代入することで
この Notice を回避できる。

list.ctp
  1. // 変数を作成し初期化
  2. $name = '';
  3.  
  4. // 引き継ぎ変数から情報を取得
  5. extract($this->passedArgs);
  6.  
  7. // 検索用テキストボックスを初期値を設定して配置
  8. echo $form->input('code', array('default'=>$name) );

 

urlencode

引き継いだ検索条件は、再び URL 付記の形で受け継がれていくので
検索文言を urlencode しておく。

list.ctp
  1. foreach ($this->passedArgs as $key => $val) {
  2.     $this->passedArgs[$key] = urlencode($val);
  3. }

 

ページ番号リンク

検索条件のページ番号リンクへの引き継ぎは、ビューの先頭で

list.ctp
  1. $paginator->options( array('url' => $this->passedArgs) );

としてやることで実現する。
 

ソートリンク

paginator は、ソート用のリンクを sort メソッドにて自動作成してくれるが
そこへ更に array(‘url’=>$this->passedArgs) を付加することで
検索条件をもリンクへ自動付記してくれる。

list.ctp
  1. echo $paginator->sort('▲▼', 'name', array('url'=>$this->passedArgs) );

としてやることで実現する。
 

完成例

上述の基本以外に、サニタイズ処理をし
1ページ当たりの表示行数を設定するドロップダウンを追加してある。

users_controller.php
  1. App::import('Sanitize');
  2. class UsersController extends AppController {
  3.  
  4.     function list()
  5.     {
  6.         // 1ページ当たりの表示行数情報の取得&設定
  7.         if ( !empty($this->params['url']['limit']) ) {
  8.             $this->paginate['limit'] = $this->params['url']['limit'];
  9.             $this->passedArgs['limit'] = $this->params['url']['limit'];
  10.         }
  11.         elseif ( !empty($this->passedArgs['limit']) ) {
  12.             $this->paginate['limit'] = $this->paginate['limit'];
  13.         }
  14.         $this->set('limit', $this->paginate['limit']);
  15.  
  16.         // 1ページ当たりの表示行数ドロップダウンのリスト
  17.         $options = array(20 => '20', 50 => '50', 100 => '100');
  18.         $this->set('options', $options);
  19.  
  20.         //「名前」フィールドでの検索文言取得&設定
  21.         if ( !empty($this->params['url']['data']['User']['name']) ) {
  22.             Sanitize::clean($this->params['url']['data']['User']['name']);
  23.             $this->paginate['conditions']['User.name LIKE'] = '%'.$this->params['url']['data']['User']['name'].'%';
  24.             $this->passedArgs['name'] = $this->params['url']['data']['User']['name'];
  25.         }
  26.         elseif (!empty($this->passedArgs['name']) ) {
  27.             $this->paginate['conditions']['User.name LIKE'] = '%'.$this->passedArgs['name'].'%';
  28.         }
  29.         $this->set('users', $this->paginate('User') );
  30.     }
  31. }

 

list.ctp
  1. // 変数を作成し初期化
  2. $name = '';
  3.  
  4. // 引き継ぎ変数から情報を取得
  5. extract($this->passedArgs);
  6.  
  7. // 検索用テキストボックスを初期値を設定して配置
  8. echo $form->input('code', array('default'=>$name) );
  9.  
  10. // 引き継ぎ検索条件を urlencode
  11. foreach ($this->passedArgs as $key => $val) {
  12.     $this->passedArgs[$key] = urlencode($val);
  13. }
  14.  
  15. // paginator に検索条件を引き継ぎ
  16. $paginator->options( array('url' => $this->passedArgs) );
  17.  
  18. echo $form->create('User', array('type'=>'get'));
  19.  
  20. // 1ページ当たりに表示する行数(件数)ドロップダウン
  21. echo $form->select('limit', $options, $limit);
  22.  
  23. //「名前」で検索するテキストボックスを初期値を設定して配置
  24. echo $form->input('code', array('default'=>$name) );
  25.  
  26. echo $form->end('抽出');
  27.  
  28. // ソートリンク設置
  29. echo $paginator->sort('▲▼', 'name', array('url'=>$this->passedArgs) );
  30.  
  31. // ページャーリンク設置
  32. echo $paginator->prev('前へ');
  33. echo $paginator->numbers();
  34. echo $paginator->next('後へ');
  35.  
  36. /* リスト出力 */

 

最後に

今回の設定では検索対象を「名前」フィールドとしたが
テキストボックスをフィールド毎に複数設置すれば
それぞれのフィールドに検索文言を設定でき
AND 検索となる。

ただし、1つのフィールド内でのスペース区切り AND 検索には対応していない。
これは今後の課題。
 

参考元サイト

WebTecNote:Pagination + Search ページ遷移時に検索条件を維持させる
でじうぃき:CakePHP Paginate Sort の使い方
きままな日記帳:CakePHPで名前付きパラメータを受け取る

もしかして、とってもシンプルな手法を見つけたかも・・・。
futuremix:CakePHP の Paginator に独自にパラメータを追加する
今度時間があるときに試してみよう。

CakePHP | 2011-05-29 (日) 15:10:27 |

リクエストパラメータ

Posted by muchag | CakePHP | 2011-05-28 (土) 15:45:36

ページ遷移する際に受け渡される値。

【環境】
[CakePHP] 1.3.8
受け取り方

コントローラ内で受け取る。

  1. // コントローラー名
  2. $this->params['controller']
  3.  
  4. // アクション名
  5. $this->params['action']
  6.  
  7. // パラメータ(引数)
  8. $this->params['named']
  9.  
  10. // POSTのフォーム送信内容
  11. $this->params['form']
  12.  
  13. // GETのフォーム送信内容
  14. $this->params['url']
  15.  
  16. // ヘルパーによって生成された要素
  17. $this->params['data']
  18.     or
  19. $this->data

まぁ、後は $this->params をダンプしてみればわかる。

CakePHP | 2011-05-28 (土) 15:45:36 |

ロールオーバー時の画像切り替え

Posted by muchag | CSS,JavaScript | 2011-05-28 (土) 13:33:34

画像の切り替えは JavaScript でやっていたけど
CSS でもできることを知り
更には、切り替え用の2枚の画像を1枚の画像にする手法を見つけ
ビックリした。
 

CSS

タグ毎に様々な手法があるようで
以下に記したのはその中のごく一部。
 

一般画像(2枚)
  1. <div id="menu_top"><a href="index.html"></a></div>
  1. #menu_top {
  2.     width: 180px;
  3.     height: 50px;
  4.     background: url(out.png) no-repeat;;
  5. }
  6.  
  7. #menu_top a {
  8.     width: 180px;
  9.     height: 50px;
  10.     display: block;
  11. }
  12.  
  13. #menu_top a:hover {
  14.     background: url(over.png) no-repeat;;
  15. }

 

一般画像(1枚)
  1. <a href="index.php" id="menu_top">TOP</a>
  1. a#menu_top {
  2.     width: 300px;
  3.     height: 34px;
  4.     display: block;
  5.     background: url(menu_top.png) left top no-repeat;
  6.     text-indent: -9999px;
  7. }
  8. a:hover#menu_top {
  9.     background-position: 0 -34px;
  10. }

参考元サイト:nplll CSSだけでマウスオーバーして画像に色を付ける(RobGoodlatte.comの場合)
 

input タグ画像(2枚)

マウスオーバー時の画像を背景画像として配置し
マウスオーバー時にはマウスアウト時の画像を透過処理し
背景画像を見えるようにする手法。

  1. div.over {
  2.     background:url("over.png") no-repeat left top;
  3. }
  4. input:hover {
  5.     opacity: 0.0;
  6. */
  7.     /* IE */
  8.     /* filter: alpha(opacity=0); */
  9. /*
  10. }

参考元サイト:WebCreator Note inputボタンのロールオーバーをCSSで指定
 

button タグ画像(2枚)

button タグでもできるようだ。
参考元サイト:パソコンQ&A 現在最良の画像置換法(IR[Image Replacement]法)
 

JavaScript
2枚の画像

一般画像でも

  1. <img src="out.png" onmouseout="this.src='out.png'" onmouseover="this.src='over.png'" alt="メニュー1" />

ボタン画像でも

  1. <input type="image" src="out.png" onmouseout="this.src='out.png'" onmouseover="this.src='over.png'" value="submit" alt="送信" />

簡単♪

CSS,JavaScript | 2011-05-28 (土) 13:33:34 |
次ページへ »