2012年7月30日月曜日

[Cakephp2.2][Twitter bootstrap2.0.4]CakephpでTwitter bootstrapのサンプルサイトを作る。その4(道草)

Eclipseのテンプレート機能

Bootstrapは便利だけど面倒くさい

Bootstrapを使うと、デザイン的にはサクッとやってくれますが、コーディング量は多くなります。特にrowとかspanとはたくさん使うので面倒です。
Eclipseを使っている場合はテンプレートという機能を使えば楽になります。

設定方法

Eclopse→環境設定(Windowsはウィンドウ→設定でしたっけ?)からWeb→HTMLファイル→エディター→テンプレートを選択します。
右側の「新規」ボタンをクリックします。



名前、パターンを入力します。ここでは名前は「tb_row_span」(Twitter Bootstrapのrow、spanの意味)としてます。パターンはdivタグにクラスを指定してます。spanの後ろは数字を入れるですが、都度変更するので変数を指定してます。パターンの中に「${}」を入れて変数に出来ます。ここでは数字を入れたいので「int1」とかしてます。変数名は重複しなければ特に何でも問題ないと思います(多分)。良ければ「OK」を押して設定します。


使ってみる

「Ctrl + space」でコード補完を表示してから「tb」と打つと今設定した内容が表示されます。選択して「Enter」押します。



span後ろの各変数の位置を「tab」キーで切り替えながら入力出来ます。



後は自分の使いたいテンプレートを増やして行くだけです。簡単ですね。

環境とか

項目内容
PHPフレームワークCakephp 2.2.0
IDEEclipse 3.6
開発環境?MAMP
PCMacmini
OSMac OS Lion

2012年7月28日土曜日

CakephpでTwitter bootstrapのサンプルサイトを作る。その3

大分前ですが、駅で電車を待っていたら事故か何かでダイヤが乱れてました。その時遅れている事をアナウンスしていた(おそらく新入社員の)女性駅員さんが、アナウンスする度に駅名を噛んでました。
...駅員が駅名噛んだらマズイだろ。と思ってました。そしてついでに萌えてました(*´ω`*)

layoutを改造する

グローバルナビが欲しい今日この頃

レイアウトのguest.ctpを作ってきましたが、やっぱりナビが欲しいと思いました。しかもBootstrapのナビバーがいいなぁ~と思いました。かっこいいですよねあれ。
まあ、Bootstrap用のサイト作るなら必須だなと後から気づいた訳ですけども。
やっぱりBootstrapのサンプルページからナビバーの部分だけコピペします。

app/View/Layout/guest.ctpを変更
...
<div id="header"> <div class="navbar"> <div class="navbar-inner"> <div class="container"> <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <a class="brand" href="#">Bootstrap コピペ場</a> <div class="nav-collapse"> <ul class="nav"> <li class="active"><a href="#">Home</a></li> <li><a href="#about">About</a></li> <li><a href="#contact">Contact</a></li> </ul> </div> </div> </div> </div> </div> ...
こういうCSSフレームワークを使うとどうしても、上のような感じに入れ子&クラス名が多くなるんですよね。そこはまあ、納得してお付き合いしてかなければいけないんですけども。


助っ人

前回書いたViewこと美優さんは健気に頑張っています。あまりに大変そうなのでControllerさんが気を利かせて助っ人を付けてます。HtmlHelperです。前回美優さんの隠し玉とかいてたHelperの1つです。 HtmlHelperはすでに何回も出てきています。guest.ctpを確認すると以下の箇所があります。

$this->Html->charset()
すなわち$this(=美優さん)のHtml助っ人(=HtmlHelper)のcharset()という仕事を実行していた訳です。文字列を返し例えばcharset()なら以下の文字列返します。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
助っ人さんは他にいます。FormHelperとかですが、今は出番が無いので放置します。
助っ人さんの役目は、複数のビューやエレメント、レイアウトで共有する処理を目的別にまとめておく事です。HtmlHelperなら、htmlタグを返すメソッドがそろってます。
後でHtmlHelperのメソッドをまとめたいです。


自作の助っ人

助っ人は自作出来ます。今後Bootstrapの関連のタグをたくさん使いそうなので、Bootstrap用の助っ人を作ってみようとおもいます。
約束事があります。

  • ファイル作成場所は「app/View/Helper」の下
  • AppHelperを継承する。
  • Viewで使用するHelperはController内で設定する
取り敢えずシンプルなナビバーを返すところから始めます。以下コード。
app/View/Helper/B99TwitterBootstrapHelper.phpを新たに作成。
<?php
/**
 * Twitter Bootstrap用のヘルパー
 */
App::uses('AppHelper', 'View/Helper');

class B99TwitterBootstrapHelper extends AppHelper {
 public $helpers = array('Html');
 
 /**
  * 
  * @return String navbar tag string
  */
 public function simpleNavbar(){
  $result = <<<NAV
<div class="navbar">
 <div class="navbar-inner">
  <div class="container">
   <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
   </a>
   <a class="brand" href="#">Bootstrap コピペ場</a>
   <div class="nav-collapse">
    <ul class="nav">
     <li class="active"><a href="#">Home</a></li>
     <li><a href="#about">About</a></li>
     <li><a href="#contact">Contact</a></li>
    </ul>
   </div>
  </div>
 </div>
</div>
NAV;
  return $result;
 }
}
app/Controller/PagesControllerに追加
public $helpers = array('B99TwitterBootstrap');
そのままナビバーを表示しても見た目が変わらないのでデバッグ出力します。
app/View/Pages/index.ctpに追加
<?php 
$this->layout = "guest";
debug($this->B99TwitterBootstrap->simpleNavbar());
?>
...
ブラウザでアクセスします。

自作した助っ人がちゃんと動作しているようです。


さらに自作の助っ人

B99TwitterBootstrapHelperを作ってみましたが、固定の文字列を返すだけでこのままでは使い勝手が良くありません。下のリストのようにさらに改造します。

  • プロジェクト名を引数で渡す
  • リンク先を引数で渡す
  • 「class="active"」って所を自動で判別して差し込む
app/View/Helper/B99TwitterBootstrapHelper.phpを修正
...
 /**
  * 
  * シンプルなナビバーを作って返す
  * @param array $brand array( 'title' => 'Bootstrap コピペ場', 'url' => '/')titleはaタグに挟まれる文字列、urlはAタグのリンク先
  * @param array $links $links = array('index' => array( 'title' => 'Home', 'url' => '/'))keyは$active_strと合う文字列、titleはaタグに挟まれる文字列、urlはAタグのリンク先
  * @param string $$active_str
  * @return String navbar tag string
  */
 public function simpleNavbar($brand, $links, $active_str){
  $link_li_tag = "";
  $brand_a_tag = "";
  //このfor文の中でactiveなclassの値を設定する
  foreach ($links as $key => $val) {
   //classがあるかチェック無ければ追加する
   if (!isset($val['class'])) {
    $val['class'] = "";
   }
   //activeなliタグかチェック
   if ($key==$active_str){
    //classに「active」文字列を追加
    $val['class'] .= " active";
   }
   //配列の値を設定し直す
   $links[$key] = $val;
  }
  //liタグを作る
  foreach ($links as $key => $val){
   $link_li_tag .= "     " . $this->Html->tag('li', $this->Html->link($val['title'] , $val['url']), $val['class']) . "
";
  }
  //プロジェクト名のaタグを作る
  $brand_a_tag = $this->Html->link($brand['title'], $brand['url'], array('class'=>'brand'));
  //ナビバーの文字列を返す
  return <<<NAV
<div class="navbar">
 <div class="navbar-inner">
  <div class="container">
   <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
   </a>
   {$brand_a_tag}
   <div class="nav-collapse">
    <ul class="nav">
{$link_li_tag}
    </ul>
   </div>
  </div>
 </div>
</div>
NAV;
 }
...
  
app/View/Pages/index.ctpからコメントアウト(もしくは削除)
<?php 
$this->layout = "guest";
//debug($this->B99TwitterBootstrap->simpleNavbar());
?>
...
app/View/Layout/guest.ctpへ追加
<?php 
$brand = array( 'title' => 'Bootstrap コピペ場', 'url' => '/');
$links = array(
 'index'  => array( 'title' => 'Home', 'url' => '/'),
 'scaffolding' => array( 'title' => 'Scaffolding', 'url' => '/pages/scaffolding'),
 'base-css'  => array( 'title' => 'Base Css', 'url' => '/pages/base-css'),
 'components' => array( 'title' => 'Components', 'url' => '/pages/components'),
 'javascript' => array( 'title' => 'Javascript Plugins', 'url' => '/pages/javascript'),
 'about'  => array( 'title' => 'About', 'url' => '/pages/about'),
);

debug($this->B99TwitterBootstrap->simpleNavbar($brand, $links, $this->request->params['action']));

...

  <div id="header">
<?php echo $this->B99TwitterBootstrap->simpleNavbar($brand, $links, $this->request->params['action']);?>
  </div>
...
ブラウザでアクセスする。

オッケーのようなのでguest.ctpからdebug()メソッドを削除する。
これで晴れてグローバルで動的にactiveが変化するナビバーの出来上がり...のはず。
simpleNavbar()メソッドの第3引数が「$this->request->params['action']」となってますが、これは現在のurlからアクションに当たる文字列を格納しています。この値を渡すことでどこのliタグがactiveなのかを判断してます。

まとめ

  • 美優さんことViewには助っ人ことHelperという仕組みがある。
  • Helperを使うには色々と決まりがある。
  • 変数の中身がわからない場合はdebug()メソッドを使う

環境とか

項目内容
PHPフレームワークCakephp 2.2.0
IDEEclipse 3.6
開発環境?MAMP
PCMacmini
OSMac OS Lion

2012年7月27日金曜日

最近4歳の娘がスギちゃんのモノマネをします。何度注意しても「ワイルドだよ~」になります。

Viewの概要

Viewの仕組み

CakephpのViewは表示を担当する人です。多分日本名は美優さんです。Controllerさんからいろんな値を渡されて、その値を美優さんが一生懸命頑張って表示します。美優さんは最終的にはhtmlやXml等の文字列を返すのが責任範囲です。
美優さんは自分の仕事がしやすい様に扱う大きさにで整理しています。下の表でhtmlの時を例に説明します。

名前内容
layout一番大きな枠組みで、複数のURLにアクセスした時の共通部分です。後でビューや(時々エレメント)を差し込めるように作成しておきます。例)htmlタグ、headタグ、bodyタグの一部、グローバルナビとかを記述しておきます。
view中位の枠組みで、アクセスするURL毎に表示する内容が替わる部分です。後でエレメントを差し込めるようにもできます。例)bodyタグの主要な部分を記述しておきます。
element一番小さな枠組みで、layoutやview、果ては他のelement内で再利用可能なわりかし小さなパーツ。例)ログイン状態を表示するdivタグとか
美優さんは他にもblockとかthemeとはhelperという隠し玉を持ってますが、ややこしいので後回しです。

レイアウトを試す

早速レイアウトを試してみます。レイアウトは「app/View/Layout」フォルダに入れます。元々デフォルトでそのまま「default.ctp」ってのがあります。
ちなみにCakephpではViewの関連のファイルの拡張子は「.ctp」(CakePHP Templateの略らしい)です。
その「default.ctp」を参考に「guest.ctp」というレイアウトを作ります。

app/View/Layout/guest.ctpを新たに作成。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php echo $this->Html->charset(); ?>*1
<title>
Twitter Bootstrap 2.0.4コピペ場 : <?php echo $title_for_layout; ?>*2
</title>
<?php
echo $this->Html->meta('icon');*3

echo $this->Html->css('');*4

echo $this->fetch('meta');*5
echo $this->fetch('css');*6
echo $this->fetch('script');*7
?>
</head>
<body>
<div id="container">
<div id="header">
<h1>Twitter Bootstrap 2.0.4コピペ場</h1>
</div>
<div id="content">
<?php echo $this->fetch('content'); ?>*8
</div>
<div id="footer">
<p>copyright busyoumono99 2012</p>
</div>
</div>
</body>
</html>
guest.ctpではどのURLでも表示する内容を記述しています。headタグやヘッダー、フッター等です。あと所々にphpでechoしているのは下で軽く説明しています。
  • *1:キャラセットを指定します。この場合UTF-8です。ちなみにCakephpはutf8が基本らしいです。
  • *2:htmlのタイトルを表示します。controllerやviewで設定しないとコントローラ名がデフォルトで表示されるようです。
  • *3:ファビコンの指定をします。
  • *4:cssの指定をします。今は空です。
  • *5:設定されているメタタグがあれば表示します。
  • *6:設定されているCSSがあれば表示します。*4とかぶるような気がしますがdefault.ctpでもこうなってたのでこのまま行きます。後で調べる。
  • *7:設定されているjavascriptを表示します。
  • *8:viewがここで表示されます。今だったら「index.ctp」の中身がここで表示されます。

viewの中でレイアウトの設定をする。

レイアウトを作ってもそのままでは美優さんはレイアウトを利用してくれません。取り敢えずここでは「index.ctp」の中で設定してみます。

app/View/Pages/index.ctpを変更
<?php
$this->layout = "guest";
?>
Hello World!
これでまたブラウザで「dream-travel.boo.jp/twitter_bootstrap_2.0.4/」にアクセスしやす

Cakephpのデフォルトでは無いデザインが適用されました。なんかNote(8)とか出てますが、*4で空にしたのが原因なので気にしない。

Twitter Bootstrapの導入

Bootstrapの準備

ここからCakephpにBootstrapを取り込みます。BootstrapのHPからダウンロードしてきます。 ダウンロードしたファイルを解凍して以下のようにファイルを配置します。
app/webroot/css

  • bootstrap-responsive.min.css
  • bootstrap.min.css
app/webroot/img
  • glyphicons-halflings-white.png
  • glyphicons-halflings.png
app/webroot/js
  • bootstrap.min.js
多分下のような見え方になってるとおもいます。

Bootstrap用にファイルを修正

Bootstrapのデザインを適応するようにguest.ctpを修正します。今度はBootstrapのサンプルページを 元に作ってみる

app/View/Layout/guest.ctpを修正
<?php
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<?php echo $this->Html->charset(); ?>
<title>Twitter Bootstrap 2.0.4コピペ場 : <?php echo $title_for_layout; ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php
echo $this->Html->meta('icon') . "\n";
echo $this->Html->css(array('bootstrap.min','bootstrap-responsive.min')) . "\n";
echo $this->fetch('meta') . "\n";
echo $this->fetch('css') . "\n";
echo $this->fetch('script') . "\n";
?>

</head>
<body>
<div class="container">
<div id="header">
<h1>Twitter Bootstrap 2.0.4コピペ場</h1>
</div>
<div id="content">
<?php echo $this->fetch('content'); ?>
</div>
<div id="footer">
<p>copyright busyoumono99 2012</p>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>

</body>
</html>
cssを複数指定したい場合は上の用にarray()で渡します。
ついでにBootstrapが反映されているか分かるようにindex.ctpも編集してみる。
app/View/Pages/index.ctpを変更
<?php
$this->layout = "guest";
?>
<div class="row">
<div class="span3">サイド</div>
<div class="span9">Hello World!</div>
</div>
これで再度ブラウザでアクセスすると

OKっぽい。

まとめ

  • 美優さんには色々機能がある。
  • レイアウト使うと便利

環境とか

項目内容
PHPフレームワークCakephp 2.2.0
IDEEclipse 3.6
開発環境?MAMP
PCMacmini
OSMac OS Lion

2012年7月26日木曜日

CakephpでTwitter bootstrapのサンプルサイトを作る。その1

ウラシマ

Cakephpからしばらく離れていたらいつの間にか1.3から2.2になっていた。新しいCakephpになれる意味でも何かサイト作ろうかなと思った次第です。
よくあるブログ記事だとデータベース使った説明が入るのでしょうけど、覚える事が多いと挫折するので、まあ最初は静的Webサイトを作ればコントローラとビュー周りは分かるかなと思った次第です。

BootStrapのサイト

いいネタ無いかなと悩んでたらひらめきました。以前の記事で紹介したbootstrapのサイトも良いのですが、ちと自分に向いてないというのも

  • 現状のVerでない
  • コピペ用のサンプルがスペースでインデントしてある
そしたら自分で作るべ。Cakephpで!!

準備

日本語のcookbook見ながらインストールは完了。
今回は色々訳あって「dream-travel.boo.jp/twitter_bootstrap_2.0.4」というフォルダ構成にした。早速ブラウザで「dream-travel.boo.jp/twitter_bootstrap_2.0.4/」にアクセスする。


おお!何かおしゃれになっている!
変なとこに感激しつついつもの画面が出てきて安心する。
エラーメッセージを消す為に以下を修正。

/app/Config/core.php
Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
...
Configure::write('Security.cipherSeed', '76859309657453542496749683645');
上記はデフォルト値なので、第2引数の値を適当に変更してから再度ブラウザでアクセスする。

オッケー!赤いの消えた。
黄色のメッセージはデータベースの設定ファイルが無いという事ですが、今回データベース使わないので無視。
次にurlのルーティングを変更する。デフォルトのままだとurlが「/」の時「PagesController」の「display」メソッドを実行して「home.ctp」 を表示するという設定になっているのでこれを変更する。
/app/Config/routes.php
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));

Router::connect('/', array('controller' => 'pages', 'action' => 'index'));
また、ブラウザでアクセスする。

Cakephpさんに怒られた。(´・ω・`)
取り敢えず「routes.php」の修正は成功で、今度のエラーメッセージはアクションの「index()」メソッドがねーよ!という内容。

プログラマのサガ

無性に挨拶したくなって来ませんか?わたしは挨拶したくなりました。
そんなわけで以下を編集。

/app/Controller/PagesController.phpに以下を追加
...

public function index(){
}

...
/app/View/Pages/index.ctpファイルを新たに作成。
<?php
?>
Hello World!
またブラウザでアクセスする。

「Hello World!」が出た!と思ったらまたCakephpさんに怒られたorz。
内容はさっき無視した「データベースの設定ファイルが無い」って奴。しょうがないので修正する。
  • app/Config/database.php.defaultをコピー
  • 同じ場所に「datebase.php」で貼り付け。
内容は変更せずにそのままでOK...なはず。またブラウザでアクセスする。

今度こそOK。

まとめ

  • core.phpでセキュリティ関係のデフォルト値を2箇所変更する
  • データベースの設定ファイルのdatebase.phpはさっさと作る
  • routes.phpでホームurlの設定を変更する
  • Pagesコントローラクラスにindexメソッドを追加
  • View/Pagesフォルダにindex.ctpを作成

環境とか
項目内容
PHPフレームワークCakephp 2.2.0
IDEEclipse 3.6
開発環境?MAMP
PCMacmini
OSMac OS Lion

2012年7月25日水曜日

CSSフレームワークのTwitter Bootstarpを調べる

結論から言うと大分良い。

参考にしたサイト

気付いた注意点1つ

レスポンシブデザインを導入すると、スマートフォンやタブレットにも対応します。で以下のlinkタグ貼り付けるのですが、

<link href="css/bootstrap-responsive.min.css" rel="stylesheet">
これ以外にも
<meta name="viewport" content="width=device-width, initial-scale=1.0">
を追加しないと、PC上でブラウザでの幅を狭くして見た時にはスマートフォン用のデザインになるのですが、実際にスマートフォンで見るとPC用のデザインのままです。

その他の使い方は上のURLで良くわかります。ではでは。

会社でSymfony使う予定だったのが中止になり、その後C++とQtとjavaとspringframworkを扱う案件でてんやわんやしてました。
最近また落ち着いて来たのでまたCakephpを唐突にいじりだす。その前にtwitter bootstrapの勉強。