CodeIgniterの学習 18 - HTMLテーブルクラスを使ってテーブルタグを自動生成してみる

これまでいろいろ試していたけど、CodeIgniterの標準機能のものをあんまり使って学習していないので、
基本に立ち返って、タスクリストを作りながら学習していくことにする。

設計とかはせずに行き当たりばったりで、いろんな機能を試してみるつもりなので、
途中の過程では相当中途半端だと思う。
でも完成したら使い物になるかも(希望)。


開発方針としては、

  • 設計はしない。思いつきでおもしろそうな機能を試す。
  • モデルにロジックを寄せるのは後回しにする。(全部コントローラ内で完結させる)
  • 必要な項目は必要になった時にalter文で列追加する。
  • xssの対策は後でやる。

理由は、書き方を学習する時に、いちいち設計してたら面倒でやる気が出ないから。


日々の進み具合は非常にゆっくりになると思う。練習アプリはのんびり作っていくことにする。


まずはタスク一覧でも作ってみる

タスクリストといえばまずは、タスク一覧。
前回のエントリで作ったデータを一覧表示してみる。

データの一覧表示には、HTMLテーブルクラスを使ってみたいと思う。
コントローラ内で、

<?php
//上略

$this -> load -> library( 'table' );         
// データ取得
$q = $this -> db -> get( 'tasklist', 20 ); 
$data['tblList'] = $this -> table -> generate($q); 

//下略
 ?>

でテーブルクラスを有効にして、
tasklistテーブルのデータを20件まで取得し、

$this -> table -> generate($q); 

でテーブルを自動生成している。


以下全ソース

これまでのエントリでいろいろやったソースを流用している。(ビューとかcssとか)
作ったテーブルのddl文はソースの末尾にあるが、おそらく後のエントリで相当変わるはず。


1)コントローラ:application/controllers/tasklist.php
クエリを発行して、テーブルタグを作ってテンプレートに流し込んでいる。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
// タスクリストというかいろいろ実験
class Tasklist extends Controller {
    // コンストラクタ
    function Tasklist()
    {
        parent :: Controller(); 

        // ログイン認証、ログインしてなければログイン画面に飛ばされる
        // $this -> freakauth_light -> check();

        // 開発中はscaffoldingを有効に
        //if ( config_item( 'my_debugger' ) ) {
        //    $this -> load -> scaffolding( 'tasklist' ); // テーブル名とクラス名は同じでなくてもいい
        //} 

        // urlヘルパ
        $this -> load -> helper( 'url' );

        //フォームヘルパ
        $this->load->helper('form');

        // モデルの読み込み todo:後でモデルに寄せる
        // $this -> load -> model( 'tasklist_mdl' );
    } 
    // デフォルトインデックス
    function index()
    {
        $data = array();

        //HTML テーブルクラスを使ってみる
        $this -> load -> library( 'table' );         
        // データ取得
        $q = $this -> db -> get( 'tasklist', 20 ); 
        $data['tblList'] = $this -> table -> generate($q); 

        // ビューの生成
        $this -> _setTpl( "tasklist_index" , $data );
    } 
    // ビューの生成 一カ所にまとめた
    function _setTpl( $viewName, $data = array() )
    { 
        // 大枠のテンプレート側の変数(ヘッダ部分のタイトルと、xajax用javascriptタグ)
        $tpl["page_title"] = "タスクリストにようこそ"; 

        // タスクリスト(実験ソース)のテンプレートにデータをセット
        $tpl["main_content"] = $this -> load -> view( $viewName, $data , true ); 

        // 大枠のテンプレートに、タスクリストのビューをはめ込む
        $this -> load -> view( 'base_view', $tpl );
    } 
} //Endofclass
/**
 * タスクリストのテーブル、適当なので後で、完了日時とかユーザーidとか項目を追加
 * CREATE TABLE tasklist (
 * id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
 * user_name VARCHAR(128) NULL,
 * title VARCHAR(255) NULL,
 * note TEXT NULL,
 * target_date DATETIME NULL,
 * limit_date DATETIME NULL,
 * del_flg INTEGER NOT NULL DEFAULT '0',
 * created timestamp NULL DEFAULT CURRENT_TIMESTAMP,
 * modified timestamp NULL DEFAULT '0000-00-00 00:00:00',
 * PRIMARY KEY(id),
 * INDEX idx_tasklist_id(id),
 * INDEX idx_tasklist_tdate(target_date),
 * INDEX idx_tasklist_ldate(limit_date)
 * );
 */

/**
 * End of file tasklist.php
 */
/**
 * Location: ./application/controllers/tasklist.php
 */
 ?>


2)ビュー(中身):application/views/tasklist_index.php
中身のビューはコントローラ側で生成したテーブルを展開しているのみ。

<h2>タスクリスト</h2>
<?= $tblList ?>


3)ビュー(外側):application/views/base_view.php
以前のエントリで作ったもの。特に変えていない。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="keywords" content="ここがキーワード" />
    <meta name="description" content="ここに説明が入る" />
    <title><?php if(isset($page_title)){echo $page_title ;}?></title>
    <?php if(isset($xajax_js)){echo $xajax_js ;}?>
    <link href="/css/style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<!-- container //-->
<div id="container">
    <!-- header //-->
    <div id="header">
        <div id="top">
            <!-- タイトル -->
            <h1><span id="title">CodeIgniterの学習</span><span id="subtitle"> - タスクリスト</span></h1>
            <!-- スローガン -->
            <h2>dix3の練習サンドボックス 適当に作ったけどベースにつかえるかもね。</h2>
        </div>
        <!-- メインメニュー -->
        <!-- todo:後で -->
        <div id="menu">
            <ul>
            <li><a href="/" class="current">ホーム</a></li><li><a href="/flickr">Flickrのテスト</a></li><li><a href="#">ヘルプ</a></li><li><a href="/auth/logout.html">ログアウト</a></li>
            </ul>
        </div>
    </div>
    <!--// header -->

    <!-- leftblock //-->
    <div id="leftblock">
        <div>
            <p>ようこそ!<?php echo ""; //getUserName();//freakauth用 ?>ちゃん</p>
            <p class="yellow">締切り前のタスクが1件あります</p>
            <p class="red">期限切れのタスクが2件あります</p>
        </div>
        <div>
            <!-- サブメニュー -->
            <ul id="submenu">
                <li><a href="#">セッションの動作テスト</a></li>
                <li><a href="#">キャプチャの動作テスト</a></li>
                <li><a href="#">グラフの動作テスト</a></li>
                <li><a href="#">なんとかかんとかの動作テスト</a></li>
            </ul>
        </div>
        <?php if(isset($calendar)){ ?>
            <!-- calendar //-->
            <div class="calendar"><?=$calendar?></div>
            <!--// calendar -->
        <?php } ?>
    </div>
    <!--// leftblock -->
    <!-- rightblock //-->
    <div id="rightblock">
        <!-- breadcrumb //-->
        <div id="breadcrumb">
            <a href="#">ホーム</a> &gt; <a href="#">CodeIgniterの学習</a> &gt; <a href="#">ここはブレッドクラム</a>
        </div>
        <!--// breadcrumb -->
        <!-- content //-->
        <div id="content">
            <!-- main_content //-->
            <?=$main_content?>
            <!--// main_content -->
        </div>
        <!--// content -->
    </div>
    <!--// rightblock -->
    <!-- footer //-->
    <div id="footer">
        &copy; 2008 dix3 ヌル日記 <a href="http://d.hatena.ne.jp/dix3/">http://d.hatena.ne.jp/dix3/</a>
    </div>
    <!--// footer -->
</div>
<!--// container -->

</body>
</html>


5)css : ドキュメントルート/css/style.css
以前のエントリで作ったもの。特に変えていない。

/* ボディ */
body{
  background:#fff;
  font-family: 'メイリオ','Meiryo','Hiragino Kaku Gothic Pro',
  'ヒラギノ角ゴ Pro W3','Osaka','MS Pゴシック',Arial,Verdana,sans-serif;
  font-size:14px;
  line-height:1.4em;
  margin: 0 auto;
}
h1, h2{
  color: #555;
  font-size:1.6em;
  border-bottom:1px solid #ddd;
  padding: 20px 0 1px 2px;
  width:50%;
}
h3, h4{
  color:  #555;
  font-size:1.2em;
  padding: 0 0 4px 2px;
}
hr{
  border:0;
  border-bottom: 1px solid #ddd;
  height: 1px;
}
a{
 text-decoration:none;
}
a:link, a:visited{
  color: #4169e1;
}
a:hover{
  color: #ff6600;
}

li{
  line-height: 1.6em;
}


/* 作成途中のメモ用 */
.memo{
	color:#ff0000;
	font-size:16px;
}
#content{
/* 赤枠は後で消す */
/*border:dotted 1px #ff0000;*/
}

/* フォーム */
#content form{
  padding:8px;
  width:80%;
  background:#f2f2f2;
}
/* フォーム内のラベル */
form label{
  margin:3px 0 2px 0;
  display:block;
  font-weight:bold;
}
#content input{
	padding:2px 3px;
}
#content div{
	padding:4px;
}

/* テーブル */
#content table{
	border-collapse: collapse;
	background:#ddd;
	border:1px solid #ccc;
}
#content  th{
	border:1px solid #ccc;
	text-align:center;
	padding:5px;
}
#content  td{
	border:1px solid #ccc;
	background:#f9f9f9;
	padding:5px;
}

/* ヘッダ */
#header{
  padding: 0 0 4px 0;
  border-bottom: 1px solid #ddd;
  background : transparent;
}
/* フッタ */
#footer{
  clear : both;
  text-align:right;
  margin : 0;
  padding : 10px;
  color : #777;
  border-top : 1px solid #ddd;
  
}
/* トップ */
#top {
  padding:10px;
  background : transparent;
  height:32px;
}

/* タイトル */
#top h1 {
  font-size: 1.7em;
  font-weight: bold;
  margin : 0 10px;
  padding : 18px 0 0 0;
  letter-spacing : 1px;
  color : #a87b7b;
  border:0;
}
/* サブタイトル */
#subtitle{
  color: #666;
}
/* スローガン */
#top h2 {
  font-size : 0.9em;
  margin : 1px 30px;
  padding : 0;
  letter-spacing : 0;
  color : #868686;
  border : 0;
}
/* 大外の枠 */
#container{
  margin : 2px auto;
  width : 97%;
  color: #4F5155;
  border:1px solid #ccc;
}

/* メニュー */
#menu {
  text-align:right;
  margin : 0;
  padding : 0;
  height : 34px;
}
#menu li {
  list-style : none;
  display : inline;
  line-height : 34px;
}
#menu li a {
  text-decoration : none;
  margin : 0;
  padding : 9px 15px 10px 15px;
  font-weight : bold;
  color : #fff;
  background:#bc8f8f;
  border-left:1px solid #fff;
}
#menu li a:hover {
  color : #222;
  background : #f8cbcb;
  margin : 0;
}

#menu li a.current{
  color : #fff;
  background : #eec1c1;
  margin : 0;
}

/* 左ブロック */
#leftblock{
  float: left;
  margin: 0;
  padding: 4px ;
  width: 20%;
  height: auto;
  
}
#leftblock p{
  width: 100%;
	padding: 3px 4px;
}

/* 右ブロック */
#rightblock{
  float: right;
  width:75%;
  min-width: 400px;
  padding: 12px;
  border-left: 1px solid #ddd;
  line-height: 145%;
}

/* サブメニュー */
#submenu{
  width:96%;
  margin:0;
  padding:2px 0 0 18px;
  font-size:0.875em;
	border:1px solid #ffffcc;
	background:#ffffdd;
}
#submenu li{
  padding:0;
  margin:0;
  line-height:100%;
}
#submenu a:link, #submenu a:visited{
  margin: 3px 0;
  padding: 4px 3px 3px 8px;
  text-decoration: underline;
  display: block;
}

/* ブレッドクラム */
#breadcrumb {
  padding: 8px 0 14px 0;
}
#breadcrumb a:link, #breadcrumb a:visited{
	text-decoration: underline;
  color: #777;
}
#breadcrumb a:hover{
  color: #ff6600;
}

/* ラベルの色 */
.info{
  padding: 10px;
  margin:4px 0;
  width:70%;
}
.box{
 padding:4px;
 width:80%;
}
.red{
  background: #ffbbcc;
  border:1px solid #ffbbcc;
}
.green{
  background: #b8e08f;
  border:1px solid #bfdb58;
}
.yellow{
  background: #f6e080;
  border:1px solid #ffd77d;
}
.blue{
  background: #c1ecfa;
  border:1px solid #b7e2f0;
}
.gray{
  background-color: #f9f9f9;
  border:1px solid #f1f1f1;
}
.txt_red{
  color:#ff0000;
}
/* カレンダー */
.calendar {
	margin-top:8px;
	font-size:1.1em;
}
.calendar table{
	border-collapse: collapse;
	background:#bc8f8f;
	border:1px solid #ccc;
}
.calendar  th{
	border:1px solid #ccc;
	text-align:center;
	color:#fff;
	padding:5px;
}
.calendar  th a{
	color:#fff;
}
.calendar  th a:hover{
	color:#ff6600;
}
.calendar  td{
	border:1px solid #ccc;
	background:#fcfcfc;
	padding:6px;
	text-align:center;
}
/* カレンダーの週 */
.cal_weekrow td{
	background:#a69090;
	color:#fff;
}
.cal_today{
	text-decoration:underline;
	color:#ff6600;
}


画面

こんなかんじ。この状態だと全カラムが表示されるので、実用的ではない。


テーブル生成部分を改良してみる

クエリで取得する列を絞り込めばいいのだが、まだ何を表示するか決めていないので、
テーブル生成の呼び方を変えてみた。

// テーブルのヘッダ
$this -> table -> set_heading( 'id','済', 'タスク名', '内容', '完了予定日', '期限' ); 

で、テーブルのヘッダを作り、

 // テーブルの生成
foreach ( $q -> result() as $row ) {
   $this -> table -> add_row($row -> id ,…
}

で、クエリ結果をぐるぐる回して一行毎にタグを生成している。
ついでにフォームヘルパの form_checkbox(名前, 値) を使って、チェックボックスも生成してみた。


1改)コントローラ:application/controllers/tasklist.php

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
// タスクリストというかいろいろ実験
class Tasklist extends Controller {
    // コンストラクタ
    function Tasklist()
    {
        parent :: Controller(); 

        // ログイン認証、ログインしてなければログイン画面に飛ばされる
        // $this -> freakauth_light -> check();

        // 開発中はscaffoldingを有効に
        //if ( config_item( 'my_debugger' ) ) {
        //    $this -> load -> scaffolding( 'tasklist' ); // テーブル名とクラス名は同じでなくてもいい
        //} 

        // urlヘルパ
        $this -> load -> helper( 'url' );

        //フォームヘルパ
        $this->load->helper('form');

        // モデルの読み込み todo:後でモデルに寄せる
        // $this -> load -> model( 'tasklist_mdl' );
    } 
    // デフォルトインデックス
    function index()
    {
        $data = array();

        //HTML テーブルクラスを使ってみる
        $this -> load -> library( 'table' ); 
        
        // データ取得
        $q = $this -> db -> get( 'tasklist', 20 ); 

        // テーブルのヘッダ
        $this -> table -> set_heading( 'id','', 'タスク名', '内容', '完了予定日', '期限' ); 
        // テーブルの生成
        foreach ( $q -> result() as $row ) {
            $this -> table -> add_row(  
                                        $row -> id ,
                                        form_checkbox('done', 'true'),//
                                        $row -> title ,
                                        $row -> note ,
                                        $row -> target_date ,
                                        $row -> limit_date ) ;
        } 
        // テーブルの生成
        $data['tblList'] = $this -> table -> generate(); 

        // ビューの生成
        $this -> _setTpl( "tasklist_index" , $data );
    } 
    // ビューの生成 一カ所にまとめた
    function _setTpl( $viewName, $data = array() )
    { 
        // 大枠のテンプレート側の変数(ヘッダ部分のタイトルと、xajax用javascriptタグ)
        $tpl["page_title"] = "タスクリストにようこそ"; 

        // タスクリスト(実験ソース)のテンプレートにデータをセット
        $tpl["main_content"] = $this -> load -> view( $viewName, $data , true ); 

        // 大枠のテンプレートに、タスクリストのビューをはめ込む
        $this -> load -> view( 'base_view', $tpl );
    } 
} //Endofclass
/**
 * タスクリストのテーブル、適当なので後で、完了日時とかユーザーidとか項目を追加
 * CREATE TABLE tasklist (
 * id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
 * user_name VARCHAR(128) NULL,
 * title VARCHAR(255) NULL,
 * note TEXT NULL,
 * target_date DATETIME NULL,
 * limit_date DATETIME NULL,
 * del_flg INTEGER NOT NULL DEFAULT '0',
 * created timestamp NULL DEFAULT CURRENT_TIMESTAMP,
 * modified timestamp NULL DEFAULT '0000-00-00 00:00:00',
 * PRIMARY KEY(id),
 * INDEX idx_tasklist_id(id),
 * INDEX idx_tasklist_tdate(target_date),
 * INDEX idx_tasklist_ldate(limit_date)
 * );
 */

/**
 * End of file tasklist.php
 */
/**
 * Location: ./application/controllers/tasklist.php
 */
 ?>


画面(改良版)

こんなかんじ。少しずつイメージがわいてきた。

この画面上でステータスとか、予定日とかを一覧画面上で編集できるといいね。
あとタスクの追加も。


今日はここまで。

一覧画面で、完了ロジックとかも入れたいけど、明日は先に個別編集画面の枠を作る。