とんでもブログ ~ プログラマのWeb開発メモ (PHP, CSS, JavaScript) -4ページ目

CakePHP / DirectryIndexっぽいことを実現

CakePHPフォーラムで以下のような記事を見つけました。


参照元: http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=246&forum=3&post_id=409

> 「/pages/dir/」で、「dir」内の「index.thtml」を表示させたいのですが可能でしょうか?
> 現状では、エラーが表示されるようです。


確かにこれで困っていました。

解決方法をメモします。


---

今回のソースを利用すると以下のような仕様となります。


「/pages/」でアクセスした場合

→「/pages/index.ctp」があればそれを表示、なければ404エラー


「/pages/dir/」でアクセスした場合

→「/pages/dir.ctp」があればそれを表示、なければ「/pages/dir/index.ctp」を表示、なければ404エラー


「/pages/index/」でアクセスした場合

→「/pages/index.ctp」があればそれを表示、なければ404エラー


---


(1) routes.phpの設定


CakePHPの設定でのmod_rewrite風な設定ファイルを変更します。

つまり、ブラウザからたたかれたURLを、サーバーのファイルにどう結びつけるのかを記述する設定ファイル。


そのファイルは、cakeroot/app/config/routes.php にあります。

まずはその中をまっさらにして、全コメントアウト。


次に以下を記述します。

Router::connect('*', array('controller' => 'pages', 'action' => 'display'));

意味は、http://サイトのURL/* でアクセスされた全ての場合に、PagesController::display()がアクセスされるということです。



(2) PagesControllerを新規作成


/cakeroot/app/controllers/pages_controller.php を新規作成します。

新規作成することで、Cakeであらかじめ用意されたPagesController、 /cakeroot/cake/libs/controller/pages_controller.php を上書きしたのと同じ効果が得られます。

新規作成したPagesControllerは以下の通り。



class PagesController extends AppController{
	public $uses = array();
	
	public function display()
	{
		$path_list = array();
		
		// URLから実際のアクセスファイル名を作成、$path_listに候補を入れる
		if (!$this->params['pass']) { // Webルートの場合
			array_push($path_list, VIEWS.'pages'.DS.'index.ctp');
		}
		else {
			array_push($path_list, VIEWS.'pages'.DS.implode(DS, $this->params['pass']).'.ctp');
			
			// URL末尾がindexで終わっていない場合はindex.ctpも試す
			if(array_slice($this->params['pass'], -1) !== 'index') {
				array_push($path_list, VIEWS.'pages'.DS.implode(DS, $this->params['pass']).DS.'index.ctp');
			}
		}
		
		// 作成したURLをもとにレンダリングを試みる
		if (!$this->tryRender($path_list)) {
			$this->cakeError('error404');
		}
	}
	
	// $path_listのテンプレートファイルが存在するかチェックし、あればレンダリングする。レンダリングが成功するとtrueを返す。
	private function tryRender($path_list)
	{
		foreach ($path_list as $path) {
			if (file_exists($path)) {
				$this->render(null, null, $path);
				return true;
			}
		}
		return false;
	}
}


---


ミスがあったら教えていただけると助かります。

【参考URL】

http://book.cakephp.org/ja/view/46/routes

http://cakebaker.42dh.com/2008/06/18/an-alternative-approach-for-static-pages/

24インチDELL液晶が39800円。8月4日まで

Eメール会員用ページで通常価格の5000円引き、39800円で売られています。送料込みで41375円。

相場的にだいぶお得です。購入を検討してみては。


http://configure.apj.dell.com/dellstore/config.aspx?c=jp&cs=jpdhs1&l=ja&oc=5113OE248WFPKT3&s=dhs


CSS / スタイルシートで高さを合わせる、高さ100%を実現する

スタイルシートのfloatによる段組で、メニューと本文を2段に分けるっていうシチュエーションはよくあると思います。

そのとき、メニューを本文の長さにあわせようとして、スタイルシートに height:100% を書いて、うまくいかなかったことはありませんか?



それで、その対策を調べてみました。スタイルシートだけでうまく実現できないのかなーということです。



結論から言うと、スタイルシートだけではできません。残念。

テーブルを使うか、JavaScriptを使うしかありません。


そんなわけで、JavaScriptを使用してみました。その記録です。




(1) 以下の記事からコード部分をコピーして .js ファイルとして新規作成します。HTMLヘッダ内で、作成した外部javascriptファイルを読み込むようにします。


指定した要素の高さを取得し、全部を一番高いやつに合わせるスクリプト

http://totora.jpn.org/archives/2005/07/box.html




(2) HTMLヘッダのJavaScript部分に以下のコードを書き足します。idは高さを合わせたい要素のidを列挙。


window.onload = function(){
syncBoxHeight("id_01", "id_02");
}



(3) これでIEでは動きますが、Firefoxでは動かなかったです。コードにミスがあるので修正します。


objNode.style.height = maxWidth;

objNode.style.height = maxWidth+'px';



(4) JavaScriptをOFFにしているユーザーさんのために、高さの記述をします。


.foo {
min-height:100px;
height: auto !important;
height: 100px;
}


詳細は以下の記事参照
http://blog.creamu.com/mt/2008/03/cssminheighteasiest_crossbrows.html




【関連リンク】

http://norisfactory.com/stylesheetlab/000001.php

http://oshiete1.goo.ne.jp/qa3357598.html


【2008.08.26追記】

スタイルシートだけでできる方法(ハック)をこちらで発見しましたが、コメント欄を見る限り致命的な不具合があるようですので使えません。

http://coliss.com/articles/build-websites/operation/css/558.html

こちらでも同じようなライブラリを発見しました。

使ってみたところ、こちらのほうが使い勝手が良かったです。

http://blog.webcreativepark.net/2007/07/26-010338.html


CakePHP / URLの相対パス置換まとめ

CakePHP導入による「相対パス→汎用の絶対パス」変換がややこしいのでまとめてみました。


---

普通のアンカータグによるリンク


<a href="abc.html">テスト</a>

<?php echo $html->link("テスト","abc.html") ?>

または

<a href="<?php echo $html->url("abc.html") ?>">テスト</a>


---

画像


<img src="./img/abc.jpg" alt="テスト" />

<?php echo $html->image("abc.jpg", array("alt"=>"テスト")) ?>

または

<img src="<?php echo $html->webroot(IMAGES_URL."/abc.jpg")" alt="テスト" />


---

画像リンク


<a href="abc.html"><img src="./img/abc.jpg" alt="テスト" /></a>

<?php echo $html->link($html->image("logo.gif", array("alt"=>"テスト")),"abc.html",null,null,false) ?>


---


この作業は非常にめんどくさいのですが、これをやっておくことで、どこに設置してもリンク切れの心配がなくなります。

テスト環境と本番環境のパスの差を気にする必要もなくなります。




【参考サイト】

http://blog.livedoor.jp/k1LoW/archives/54654684.html


CSS / スタイルシートでマウスをのせたときに画像を切り替える

マウスを乗せたときに画像が切り替わるというあれを実現したいと思いまして、

普通ならJavaScriptで実現するところをCSSに記述したらどうなるのか調べてみました。


問題が2つありました。

なのでそれを記録しておきます。


--



<問題その1>

マウスをのせたときに画像を切り替える処理はどうすれば実現できるか

(ロールオーバー処理、マウスオーバー時のスワップ処理)


<問題その2>

ロールオーバー時に画像の読み込みが発生してしまう。画像の先読みはどうすれば実現できるか

(イメージのプリロード処理)



---


解決方法。




<問題その1>


CSSファイルのa:hoverを利用すればよい


#image a {
    background:url("image.jpg");
}

#image a:hover {
    background:url("image_swap.jpg");
}


<問題その2>


#preloadImages {
    display: none;
    background-image: url("image_swap.jpg");
}

上記に加え、HTML中に <div id="preloadImages"></div> を記述


この他に、切り替え前後の2画像を連結して1つのファイルにしてしまい、a:hover時に画像の表示範囲をずらすというテクニックがありました。

表示範囲をずらすテクニックを使用するときは画像ファイルが1つになるので先読みは必要なくなるというメリットはあるのですが、1ファイルに2つの画像が入っているのは正攻法ではないと思うので、こちらのやり方を推奨します。


---

【参考サイト】

http://hac-design.com/css/rollover.html

http://phpspot.org/blog/archives/2006/04/css_2.html

http://www.masahiko.info/blog/archives/000793.html