【CodeIgniter】カレンダーライブラリをつかった『簡単なWebアプリケーションの作り方』
CodeIgniterでカレンダーアプリケーションを作る方法です。今回は基本的なサンプルですが、応用次第ではさまざまなWebアプリケーション開発に有効活用することができます。
・» デモはこちら
・» ソースコードはこちら
目次
それではまとめてきます。
CodeIgniterの初期設定
.htaccessを設置を設置
RewriteEngine On
RewriteBase /calendar/
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#When your application folder isn't in the system folder
#This snippet prevents user access to the application folder
#Submitted by: Fabdrol
#Rename 'application' to your applications folder name.
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn't true it sends the
#request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin
ErrorDocument 404 /index.php
RewriteBase /calendar/ の部分はフォルダ名にあわせて変更してください。
オートロード設定
編集ファイル:config/autoload.php
$autoload['libraries'] = array("database");
$autoload['helper'] = array("url");
ベースURL設定
編集ファイル:config/config.php
$config['base_url'] = 'http://localhost/calendar/';
$config['index_page'] = '';
DB作成
DB名:ci_calendar
データベース設定
編集ファイル:config/database.php
$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'root';
$db['default']['password'] = 'root';
$db['default']['database'] = 'ci_calendar';
$db['default']['dbdriver'] = 'mysql';
CodeIgniterのカレンダーライブラリを利用する
カレンダー表示用のコントローラーをつくる
新規作成ファイル:application/mycal.php
load->library("calendar");
echo $this->calendar->generate();
}
}
カレンダーライブラリのオプションを利用する
編集ファイル:application/mycal.php
public function display(){
$conf = array(
"start_day" => "monday", //曜日初めを月曜日にする
"show_next_prev" =>true, //Next, Prevリンクを生成
"next_prev_url" => base_url() . "mycal/display" //生成されたNext. PrevリンクにURLを渡す
);
$this->load->library("calendar", $conf);
echo $this->calendar->generate();
}
この状態でNext, Prevリンクをクリックすると、URLに変化は起きますが、カレンダー自体は変化しません。
理由は、カレンダーライブラリに情報は渡されていないからです。
カレンダーライブラリに情報を渡す
編集ファイル:application/mycal.php
public function display($year, $month){
$conf = array(
"start_day" => "monday",
"show_next_prev" =>true,
"next_prev_url" => base_url() . "mycal/display"
);
$this->load->library("calendar", $conf);
echo $this->calendar->generate($year, $month);
}
この状態へページを読み込みするとカレンダーは動作します。
しかし、当月を表示する際に、$year, $monthがパラメータを受け取っていないためエラーが発生します。
パラメータをオプショナルにすることで解決できます。
具体的には、以下のとおりです。
public function display($year = null, $month = null)
// 省略
echo $this->calendar->generate($year, $month)
ここまでで、ベーシックなカレンダーが完成しました。
しかし、次からのステップでカレンダーには様々な情報を表示させるためには、先ほどつくったコントローラーをモデルとして利用したほうが使い勝手がよいです。
カレンダーライブラリがDBと情報をやりとりしやすくする
新規作成ファイル:models/mycal_model.php
<?php
class Mycal_model extends CI_Model{
function generate ($year, $month){
$conf = array(
"start_day" => "monday",
"show_next_prev" =>true,
"next_prev_url" => base_url() . "mycal/display"
);
$this->load->library("calendar", $conf);
return $this->calendar->generate($year, $month);
}
}
プログラムの最後がechoではなく、returnになっています。
Mycal_modelをコントローラーで読み込む
編集ファイル:controller/mycal.php
public function display($year = null, $month = null){
$this->load->model("Mycal_model");
// generate機能で取得したデータを$dataに挿入
$data["calendar"] = $this->Mycal_model->generate($year, $month);
$this->load->view("mycal", $data);
// $conf = array(
// "start_day" => "monday",
// "show_next_prev" =>true,
// "next_prev_url" => base_url() . "mycal/display"
// );
// $this->load->library("calendar", $conf);
// echo $this->calendar->generate($year, $month);
}
基礎知識ですが、以下のプログラムに関して。
$data["calendar"] = $this->Mycal_model->generate($year, $month);
上記プログラムは、以下のように書き換えることも可能です。
$data = array(
"calendar" => $this->Mycal_model->generate($year, $month)
);
カレンダー表示用のビューを作成する
新規作成ファイル:views/mycal.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>CodeIgniterカレンダー</title>
<meta name="keywords" content="">
<meta name="description" content="">
</head>
<body>
<?php echo $calendar; ?>
</body>
</html>
ここまでで、DBとの情報のやり取りに関して、より利便性のたかいカレンダーが完成しました。
次にカレンダー内に情報を入れ込む機能を作成していきます。
カレンダー内に情報を埋込む
編集ファイル:models/mycal_model.php
$this->load->library("calendar", $conf);
$cal_data = array(
17 => "Normalday",
25 => "HappyPayment"
);
return $this->calendar->generate($year, $month, $cal_data);
すると、17日と25日にURLパラメータが渡されるようになります。
$confをgenerate機能内から出す
編集ファイル:models/mycal_model.php
class Mycal_model extends CI_Model{
var $conf;
function Mycal_model(){
parent::__construct();
$this -> conf = array(
"start_day" => "monday",
"show_next_prev" =>true,
"next_prev_url" => base_url() . "mycal/display"
);
}
function generate ($year, $month){
$this->load->library("calendar", $this->conf);
$cal_data = array(
17 => "Normalday",
25 => "HappyPayment"
);
return $this->calendar->generate($year, $month, $cal_data);
}
}
CodeIgniterのカレンダーライブラリとDBを繋ぐ
テーブルの作成
次回以降のステップでDBを使うので、ここで一度テーブルを作成します。
テーブル名:calendar
カラム数:2
次に以下のようにテスト用データを挿入しておきます。
DBからカレンダー情報を取得できるようにする
編集ファイル:models/mycal_model.php
以下のプログラムを変更します。
// $cal_data = array(
// 17 => "Normalday",
// 25 => "HappyPayment"
// );
// get_calendar_dataを実行して、取得情報を$cal_dataに挿入する
$cal_data = $this->get_calendar_data($year, $month);
get_calendar_dataを作成していきます。
DBからカレンダー情報を取得する機能(get_calendar_data)の作成
編集ファイル:models/mycal_model.php
function get_calendar_data($year, $month){
// 生成されるSQL : date LIKE "2014-08%"
$query = $this->db->select("date, data") -> from("calendar") -> like("date", "$year-$month", "after") -> get();
$cal_data = array();
foreach ( $query -> result() as $row ){
// $queryで日付を取得しているので、substrを利用している
// 例:2014-08-15の場合⇒15が取得される
// substr(8, 2)⇒8番目の文字から2文字を取得するという意味
// 最後の+0の意味:Mysqlは数字を(01, 02, 03,,,)のように返しますが、カレンダークラスは(1,2,3,4,,,)のうように返します。その問題を+0で解決しています。
$cal_data[substr($row->date, 8,2)] = $row -> data;
}
return $cal_data;
}
すると、2014-08-26の部分のリンクが、ここをテスト中になっているはずです。
次に、リンクではなく、カレンダー内に文字を出現させていきます。
カレンダーテンプレートの作成
編集ファイル:models/mycal_model.php
カレンダーテンプレートを作成することで、カレンダーのデザインを100%コントロールできます。
Smartyみたいなテンプレートですね。以下のとおりに修正してください。
function Mycal_model(){
parent::__construct();
$this -> conf = array(
"start_day" => "monday",
"show_next_prev" =>true,
"next_prev_url" => base_url() . "mycal/display"
);
$this->conf["template"] = '
{table_open}{/table_open}
{heading_row_start}{/heading_row_start}
{heading_previous_cell}<< {/heading_previous_cell}
{heading_title_cell}{heading} {/heading_title_cell}
{heading_next_cell}>> {/heading_next_cell}
{heading_row_end} {/heading_row_end}
{week_row_start}{/week_row_start}
{week_day_cell}{week_day} {/week_day_cell}
{week_row_end} {/week_row_end}
{cal_row_start}{/cal_row_start}
{cal_cell_start}{/cal_cell_start}
{cal_cell_content}
{day}
{content}
{/cal_cell_content}
{cal_cell_content_today}
{day}
{content}
{/cal_cell_content_today}
{cal_cell_no_content}{day}{/cal_cell_no_content}
{cal_cell_no_content_today}{day}{/cal_cell_no_content_today}
{cal_cell_blank}{/cal_cell_blank}
{cal_cell_end} {/cal_cell_end}
{cal_row_end} {/cal_row_end}
{table_close}
{/table_close}';
}
次に、CSS。以下のとおりです。
編集ファイル:views/mycal.php
.calendar {
font-family: Arial;
font-size: 12px;
}
table.calendar {
margin: auto;
border-collapse: collapse;
}
.calendar .days td {
width: 80px;
height: 80px;
padding: 4px;
border: 1px solid #999;
vertical-align: top;
background-color: #DEF;
}
.calendar .days td:hover {
background-color: #FFF;
}
.calendar .highlight {
font-weight: bold;
color: #00F;
}
これで、カレンダー内にDB情報が表示されるようになりました。
カレンダーテンプレート作成方法の詳細は以下からどうぞ。
カレンダークラス : CodeIgniter ユーザガイド 日本語版
次にブラウザから情報をPOSTできるようにします。
ブラウザからカレンダー内に情報をPOSTする
カレンダー内に情報をPOSTするモデルを作成する
編集ファイル:models/mycal_model.php
function add_calendar_data($date, $data){
// calendarのDB内にarrayした情報を挿入する
$this->db->insert("calendar", array(
// dateに取得済みを$dateを挿入する
"date" => $date,
// dataに取得済みを$dataを挿入する
"data" => $data
));
}
動作テストを行なってみます。
http://localhost/calendar/mycal/display/にアクセスした際に、displayコントローラーが実行されます。
displayコントローラーでは、Mycal_modelが読み込まれ、Mycal_model内のgenerateメソッドが実行されます。
ということは、generateメソッド内で、DBへの情報追加機能がテストできることになります。
つまり、プログラムは以下です。
function generate ($year, $month){
$this->load->library("calendar", $this->conf);
$this->add_calendar_data("2014-08-11", "テスト投稿");
// get_calendar_dataを実行して、取得情報を$cal_dataに挿入する
$cal_data = $this->get_calendar_data($year, $month);
return $this->calendar->generate($year, $month, $cal_data);
}
ページ読み込みをすると、情報がDBに挿入され、カレンダーに表示されたことがわかります。
しかし、ページを再度読み込むと以下のエラーが発生します。
A Database Error Occurred
Error Number: 1062
Duplicate entry '2014-08-15' for key 'PRIMARY'
INSERT INTO `calendar` (`date`, `data`) VALUES ('2014-08-15', 'テスト投稿')
Filename: /Applications/MAMP/htdocs/calendar/models/mycal_model.php
Line Number: 81
日本語が文字化けしちゃっていますが、要するに、情報の入っているDBに、再度情報を挿入(insert)しようとしたためにエラーが発生しています。
なので、カラムに情報は入っている場合は、insertではなく、updateするようにプログラムを書き換える必要があります。
カレンダー情報のアップデート
編集ファイル:models/mycal_model.php
function add_calendar_data($date, $data){
// カレンダーDBのdateを選択し、データをカウントする
if( $this->db->select("date")->from("calendar")->where("date", $date)->count_all_results()){
// 情報をアップデートする
$this->db->where("date", $date)->update("calendar", array(
"date" => $date,
"data" => $data
));
}else{
// calendarのDB内にarrayした情報を挿入する
$this->db->insert("calendar", array(
"date" => $date,
"data" => $data
));
}
}
これで無事にエラーから解消されました。
この時点で、テストコードを削除して、DBテーブルも空にしておいてください。
jQueryでデータ挿入できる機能をつくる
編集ファイル:views/mycal.php
各日付をクリックしたら、日付を取得できるようにします。
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<?php echo $calendar; ?>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
$(".calendar .day").click(function(){
// class="day_num"の次には数字が入っているので、それを.html()で取得 day_num = $(this).find(".day_num").html();
alert (day_num);
})
})
</script>
AJAXでデータ挿入を行なっていく(フロントエンドのみ)
編集ファイル:views/mycal.php
$(document).ready(function(){
$(".calendar .day").click(function(){
// class="day_num"の次には数字が入っているので、それを.html()で取得
day_num = $(this).find(".day_num").html();
// alert (day_num);
// prompt:ポップアップでテキストのインプットボックスが出現します。
day_data = prompt("予定を入力");
if( day_data != null ){
// ユーザーがprompt後にキャンセルしなければ以下を実行
$.ajax({
url:window.location,
type:"POST",
data:{
// dayがPostされる
day:day_num,
//prompt部分で入力された情報
data:day_data
},
success:function(msg){
location.reload();
}
});
}
})
})
以上でフロントエンド部分んは動くようになります。
次はAJAXデータをDBに挿入していきます。
AJAXデータをDBに挿入する
編集ファイル:controllers/mycal.php
public function display($year = null, $month = null){
$this->load->model("Mycal_model");
if( $day = $this->input->post("day") ){
// dayがPOSTされたら以下を実行。同時に、day情報を$dayに格納
$this->Mycal_model->add_calendar_data(
// add_calendar_dataは2つのパラメータが必要
// add_calendar_data($date, $data)
"$year-$month-$day", //パラメータ1つめ
$day //パラメータ2つ目
);
}
これで正しいように見えますが、$year = null, $month = nullがあるので、正常に動きません。
$year、$monthがない場合は以下のように初期化(イニシャライズ)しておきます。
if( !$year ){
// $yearが空なら現在の年を挿入
$year = date('Y');
}
if( !$month ){
// $yearが空なら現在の年を挿入
$month = date('m');
}
$this->load->model("Mycal_model");
これで、99%完成です。
最後に少しだけ追加して、ユーザビリティを上げます。
すでに値が挿入されている場合は、Prompt画面に情報が表示されるようにします。
つまり以下のとおり。
■現状
上記をクリックした場合に、以下のように表示されるようにします。
※現状のままだと、ボックスが空です。
■変更後
promptに第2引数をわたす
編集ファイル:views/mycal.php
HTML内部にあるvalueをフェッチできるようにします。
day_data = prompt("予定を入力", $(this).find(".content").html());
以上で完成です!お疲れさまでした。
photo credit: bubbo.etsy.com via photopin cc