元ネタ知ってる人は毎週タイムボカンシリーズ1時間前からテレビつけてた人だろうね。
んなことたぁどうでもいい。早速始めてみようか。
実はもう少し早めに2回目を書こうと思ってたんだけど、いろいろ生活上の理由があって、とうとう一週間も経ってしまったよ。
連載はなるべく数日後には続きを書きたいんだけどね。次回からは念頭において、ローラの画像探すのに時間かけないようにするよ。
さて、今回はすでにほぼデプロイが終わってるであろう、CakePHP、Bootstrap、各種プラグインを、実際にビューファイルを作って試してみようと思う。
前回の通りに正しく順序通りにやれば、すでに環境は整ってるはずだ。早速行ってみよう。
■まずはサンプル
今回は/app/Controller/AppController.phpにauthコンポーネントを入れてあるので、普通にブラウザでアクセスすると、自動で/users/loginにリダイレクトするようになっているので、まずここのビューを作ろうと思う。前回はtouchコマンドで空のlogin.ctpを作ったので、一応レイアウトビューファイルはいじってないので、上下にヘッダとフッタは表示されて入るものの、ブラウザでみてみたら真っ白だったはず。
本来ここにはログイン画面として、ユーザID、パスワード、そしてログインボタンであるサブミットボタン何かを表示するのが良さげなんだけど、まずは一度、CakePHPでBootstrapを簡単導入できる、BoostCakeを試してみようじゃないか。
その前に、このWinodws95の背景みたいなレイアウトビューをどうにかしよう。
眠くなるんだよな、この配色。
って、俺だけかな?
各種ビューを配置する土台のような役目を果たす、レイアビューを、極力シンプルに、BoostCake向けにしておくことにしよう。
$ vi addp/View/Layout/default.ctp最初はこのファイルには色々とごちゃごちゃと書かれていると思うけど、俺は全部消してしまってるよ。なにしろ一旦消すことにより、もう後戻りできない自分を軽く演じることができ、誰にでも激壁背水掌を雲のジュウザばりに繰り出すことができるようになるかもしれないからね。
そんなことはまるで無いんだけどね。
そして以下のコードは、俺が最低限必要だと思われるものだけ残した、シンプル且つはなくそみたいなコードだ。
何がはなくそかというと、せっかくダウンロードしてきたbootstrap.min.jsをローカルじゃなくてリモートから呼んでたりして、整合性といういみは若干キモち悪さの残る、いかにも俺らしく有機的な解決法になってる点だね。さすがだね。
というよりむしろ、面倒くさいから編集してないだけ。まぁ細かいことはいいんだよ。修正したかったらどうぞご自由に。
<html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Bad And Ass"> <meta name="author" content="Bad And Ass Company"> <link rel="shortcut icon" href="favicon.ico"> <title>BadAss</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="/js/html5shiv.js"></script> <script src="/js/respond.min.js"></script> <![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> </head> <body> <?php echo $this->fetch('content'); ?> </body> </html>
html5shiv.jsとrespond.jsはここから落として、app/webroot/jsの中に入れておいてね。
※この2つは別に使わなくてもいいと思うけど念のため。
BoostCakeのページにはサンプルコードが記述されているので、まずは一旦、それをそのまま、app/View/Users/login.ctpに貼り付けてみよう。
BoostCake
一応抜粋しておくと、以下になるよ。
<?php echo $this->Form->create('BoostCake', array( 'inputDefaults' => array( 'div' => 'form-group', 'wrapInput' => false, 'class' => 'form-control' ), 'class' => 'well' )); ?> <fieldset> <legend>Legend</legend> <?php echo $this->Form->input('text', array( 'label' => 'Label name', 'placeholder' => 'Type something…', 'after' => '<span class="help-block">Example block-level help text here.</span>' )); ?> <?php echo $this->Form->input('checkbox', array( 'label' => 'Check me out', 'class' => false )); ?> <?php echo $this->Form->submit('Submit', array( 'div' => false, 'class' => 'btn btn-default' )); ?> </fieldset> <?php echo $this->Form->end(); ?>これを貼り付けたら保存して、早速ブラウザで観てみよう。
こんな風になるはずだ。
あれ?一箇所、checkboxがおかしいね。
この部分、
<?php echo $this->Form->input('checkbox', array( 'label' => 'Check me out', 'class' => false )); ?>ってなってるけど、
<?php echo $this->Form->input('checkbox', array( 'type' => 'checkbox', 'label' => 'Check me out', 'class' => false )); ?>にしたら正しく表示されたよ。"type"属性を追加したってことね。
これはサンプルが原因なのか、プラグインが原因なのか、俺の環境が原因なのか、はっきり言ってわからない。
こうやって回避策があるなら、使えるということでいいと思う。
サンプルページだとちゃんと動いているような気がするんだけど、何が違うのか、まだちゃんと調べてないのでよくわからん。
動くならこれですすめるよ。
ちょっと見やすくするために、グリッドシステムを入れてみよう。
グリッドは横方向に12列あるので、8セル分の表示にして、左右2セル開けてみる。
オフセット機能があるので、8セル指定と同時に、2セル分ずらしてみよう。
以下のタグで挟むだけだ。楽ちん。
<div class="row"> <div class="col-md-8 col-md-offset-2"> ~ </div> </div>だたこれだけだと、横スクロールバーがでてしまったりして不具合が出るので、ちゃんとBootstrapの説明通り、『div.container』クラスで囲わないといけない。
結果的に全体を以下のように囲もう。
<div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> ~ </div> </div> </div>これで綺麗に表示できたはずだ。
ブラウザサイズを変えるとすでにレスポンシブになってるのに気づくと思う。
楽ちんだよね。
■他の要素も追加してみよう
そう、他の要素だよ。BoostCakeのページには他にも幾つかサンプルが乗っているので、いろいろ追加してみようじゃないか。
まずはログインに使えそうな、Inline-Form(平行配置)だ。
<div class="row"> <div class="col-md-8 col-md-offset-2"> <?php echo $this->Form->create('BoostCake', array( 'inputDefaults' => array( 'div' => false, 'label' => false, 'wrapInput' => false, 'class' => 'form-control' ), 'class' => 'well form-inline' )); ?> <?php echo $this->Form->input('email', array( 'placeholder' => 'Email', 'style' => 'width:180px;' )); ?> <?php echo $this->Form->input('password', array( 'placeholder' => 'Password', 'style' => 'width:180px;' )); ?> <?php echo $this->Form->input('remember', array( 'type' => 'checkbox', 'label' => 'Remember me', 'class' => false )); ?> <?php echo $this->Form->submit('Sign in', array( 'div' => false, 'class' => 'btn btn-default' )); ?> <?php echo $this->Form->end(); ?> </div> </div>これを『div.container』内に追記してみよう。
このソースも、checkboxにはtype属性を追加してあるよ。
表示されたね。
ここで一発、BoostCakeじゃなくてBootstrap3を直接記述してみよう。
つまりCakePHPのヘルパーじゃなくて素のHTMLで書いてみたってことね。
以下のコードを『div.container』内に追記してみたよ。
<div class="row"> <div class="col-md-8 col-md-offset-2"> <form class="well form-inline" role="form"> <div class="form-group"> <label class="sr-only" for="exampleInputEmail2">Email address</label> <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Enter email"> </div> <div class="form-group"> <label class="sr-only" for="exampleInputPassword2">Password</label> <input type="password" class="form-control" id="exampleInputPassword2" placeholder="Password"> </div> <div class="checkbox"> <label> <input type="checkbox"> Remember me </label> </div> <button type="submit" class="btn btn-default">Sign in</button> </form> </div> </div>そしてブラウザでみてみた。
うん、見事に同じだね。
もうね、素晴らしいね、BoostCake。
若干inputのサイズが違うのは、BoostCakeはスタイルでピクセル指定がはいってるんだよね。でもまぁ違和感無いでしょ。スタイルなので後から継承させてどうにでもなると思うし。
ちなみにここまでのファイルの内容はこうなってるよ。
app/View/Users/login.ctp
<div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <?php echo $this->Form->create('BoostCake', array( 'inputDefaults' => array( 'div' => 'form-group', 'wrapInput' => false, 'class' => 'form-control', ), 'class' => 'well', )); ?> <fieldset> <legend>Legend</legend> <?php echo $this->Form->input('text', array( 'label' => 'Label name', 'placeholder' => 'Type something…', 'after' => '<span class="help-block">Example block-level help text here.</span>' )); ?> <?php echo $this->Form->input('checkbox', array( 'type' => 'checkbox', 'label' => 'Check me out', 'class' => false )); ?> <?php echo $this->Form->submit('Submit', array( 'div' => false, 'class' => 'btn btn-default' )); ?> </fieldset> <?php echo $this->Form->end(); ?> </div> </div> <div class="row"> <div class="col-md-8 col-md-offset-2"> <?php echo $this->Form->create('BoostCake', array( 'inputDefaults' => array( 'div' => false, 'label' => false, 'wrapInput' => false, 'class' => 'form-control', ), 'class' => 'well form-inline', )); ?> <?php echo $this->Form->input('email', array( 'placeholder' => 'Email', 'style' => 'width:180px;' )); ?> <?php echo $this->Form->input('password', array( 'placeholder' => 'Password', 'style' => 'width:180px;' )); ?> <?php echo $this->Form->input('remember', array( 'type' => 'checkbox', 'label' => 'Remember me', 'class' => false )); ?> <?php echo $this->Form->submit('Sign in', array( 'div' => false, 'class' => 'btn btn-default' )); ?> <?php echo $this->Form->end(); ?> </div> </div> </div>というわけで、次に行ってみよう。
■ページネーションとページャ
さて、ページネーションをつかうためには、いくつかの連続したデータが必要になる。ここでは。postsテーブルを作成し、そこにデータを入れてみようじゃないか。例によって以下のSQLで一発でやったぜベイビー状態になれるので、ベイビーorダイ!!
DROP TABLE IF EXISTS `posts`; CREATE TABLE IF NOT EXISTS `posts` ( `id` int(5) NOT NULL AUTO_INCREMENT, `title` varchar(64) NOT NULL COMMENT '件名', `body` text NOT NULL COMMENT '本文', `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`), KEY `title` (`title`,`body`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;データも含めて欲しい場合、ここからSQLをコピするか、ファイルをダウンロードして使ってね。
ダミーデータが51件入れてあるよ。
https://gist.github.com/ogaaaan/6620021
次にapp/Controller/PostsController.phpを作り、app/View/Posts/index.ctpも作り、一時的にAuthコンポーネントも無効にしてみよう。
app/Controller/AppController.php
public $components = array( 'Session', 'Cookie', 'DebugKit.Toolbar', /* 'Auth' => array( 'flash' => array( 'element' => 'alert', 'key' => 'auth', 'params' => array( 'plugin' => 'BoostCake', 'class' => 'alert-error' ), ), ), */ );
そして次はPostsControllerを作る。
app/Controller/PostsController.php
Class PostsController extends AppController { public $name = 'Posts'; public function beforeFilter() { parent::beforeFilter(); } public function index() { $this->paginate = array( 'order' => array('id' => 'desc'), 'limit' => 10, ); $this->set('posts', $this->paginate('Post')); } }
最後にビュー。
app/View/Posts/index.ctp
<div class="container"> <h2>Post</h2> <table class="table"> <thead> <tr> <th><?php echo $this->Paginator->sort('id', 'ID');?></th> <th><?php echo $this->Paginator->sort('title', 'タイトル');?></th> <th><?php echo $this->Paginator->sort('created', '作成日');?></th> </tr> </thead> <tbody> <?php foreach($posts as $post):?> <tr> <th><?php echo h($post['Post']['id'])?></th> <th><?php echo h($post['Post']['title'])?></th> <td><?php echo h($post['Post']['created'])?></td> </tr> <?php endforeach?> </tbody> </table> </div>これで一旦ブラウザで見てみよう。
パスは、『/posts/index』だ。
こんなふうになるはずだ。
さて、このインデックス(一覧ページ)にページネーションとページャを実装してみようじゃないか。
ページネーションっていうのは要するに、今何ページ目だよ!的な『ページ数のリンクリスト』だ。
ページャというのは『次へ』、『前へ』、みたいな、いわゆる『ページめくり』のことね。
まずはページネーション。
以下の1行を、H2タグの下に追記してみよう。
<?php echo $this->Paginator->pagination(array('ul' => 'pagination')); ?>追記したら保存して、早速ブラウザで見てみようじゃないか。
なんと、これだけでページネーションが可能という。
ちょっと色々クリックしてみればわかるけど、ページャのマウスオーバーとかでマウスポインタが変わったり、ちょっと色っぽくなってるよね。
Disable時のマウスポインタはcssの『cursor』に『not-allowed』が割り当てられているだけなので、変更したい人は『bootstrap.css』を継承したcssファイルでもつくって、そこで書き換えればいいと思うよ。
さて、次はページャだ。こっちはインデックスページで使うというより、詳細ページで『一覧に戻らなくても次のページに行ける』的な使い方に最適かもしれないね。まぁ使い方は人それぞれだから絶対ってわけじゃないけどね。
tableタグの下に、以下の1行を追記してみよう。
<?php echo $this->Paginator->pager(); ?>追記したら保存して、早速ブラウザで見てみようじゃないか。
ページネーションで3ページ目アタリを選択してみるとわかるんだけど、左右に『Previous』と『Next』ボタンが表示された。すごい!!
ちなみにこの文字列は簡単に変更可能だ。
以下のようにしてみよう。
<?php echo $this->Paginator->pager(array( 'prev' => __('前へ'), 'next' => __('次へ') )); ?>追記したら保存して、早速ブラウザで見てみようじゃないか。
うぅ~ん、マンダム。
さすがだね!!
ちなみにこちら、『«』などの実体参照でやってみたら、エスケープされなかった。これは残念。オプション付けてもダメみたい。
なので、pager()メソッドじゃなくて、prev()とnext()メソッドを組み合わせて見たのがこちら。
<ul class="pager"> <li class="previous"><?php echo $this->Paginator->prev(__('« 前へ'), array('escape' => false, 'tag' => false))?><li> <li class="next"><?php echo $this->Paginator->next(__('先へ »'), array('escape' => false, 'tag' => false))?></li> </ul>
少し記述が長くなるけど、エレメントとかにしておけばどこででも使えるし、1ページで済むので楽だよね。
そうそう、それからページネーションもページャも、親要素はulタグなので、適宜divタグなどでくくって好きに扱うことができるのも見逃せないポイントだね。
因みにここまでのファイルの内容はこうなってるよ。
app/View/Posts/index.ctp
<div class="container"> <h2>Post</h2> <?php echo $this->Paginator->pagination(array('ul' => 'pagination')); ?> <table class="table"> <thead> <tr> <th><?php echo $this->Paginator->sort('id', 'ID');?></th> <th><?php echo $this->Paginator->sort('title', 'タイトル');?></th> <th><?php echo $this->Paginator->sort('created', '作成日');?></th> </tr> </thead> <tbody> <?php foreach($posts as $post):?> <tr> <th><?php echo h($post['Post']['id'])?></th> <th><?php echo h($post['Post']['title'])?></th> <td><?php echo h($post['Post']['created'])?></td> </tr> <?php endforeach?> </tbody> </table> <ul class="pager"> <li class="previous"><?php echo $this->Paginator->prev(__('« 前へ'), array('escape' => false, 'tag' => false))?></li> <li class="next"><?php echo $this->Paginator->next(__('先へ »'), array('escape' => false, 'tag' => false))?></li> </ul> </div>
■終わり
あとはもうあれだね、BoostCakeのサイトと、Bootstrap3のサイトみながら、面白おかしく好き勝手にやりたい放題やると寝覚め良いかもね。繰り返しになるけどリンク書いておくよ。
BoostCake
ページ | 説明 |
---|---|
Bootstrap3 Basic | ページ中断くらいからが、困ったときに見る場所 |
Bootstrap3 css | グリッドの仕組み、基本的なCSS設定など |
Bootstrap3 Components | BootstrapならではのUX部品の使い方 |
Bootstrap3 JavaScript | 個別にインストール可能なJavaScriptライブラリ |
Bootstrapの特徴としては、HTMLの階層が案外深くなってしまう部分もあるんだけど、レスポンシブってそういうところはしょうがないと思うし、完全にデザインをハンドルするようなアーティストだったらムカないのかもしれないけど、PC版、モバイル版なんかをサクッとつくるには最適なんだよね。
という感じで、みんなでBoostCakeに感謝しつつ、さくさくWebアプリをつくって、日本がいかにすごい国なのかを諸外国に再確認してもらおうか。
というわけで終わり。
読んでくれてありがとうござる。
facebook
twitter
google+
fb share