ご無沙汰しております。きんです。
最近は2歳児の夜泣きに毎日苦しめられております。
いきなりMAXの音量で泣き始めるため、毎度心臓バクバクで飛び起きています。
いわゆるかんの強い子なのでしょうか。
…完全にママ似です。ごめんね☆
先日業務で利用する機会があったSilexが個人的にかなりお気に入りです。
CakePHPやLaravelなどに比べて学習コストも少なくて済み、私のようなめんどくさがりさんや、ちょこっと何か作りたい時にはぜひおすすめです。
Silexについての情報は詳しくは公式サイトをご覧くださいまし。
目次
Silex利用手順
vagrant作業環境
- php5.3.3
- CentOS6.6
※composerが入っている前提です。
手順
composerから作業フォルダにsilexインストール
$ composer require silex/silex:~1.2
公式サイトを参考に.htaccessを設定
Options -MultiViews
RewriteEngine On
#RewriteBase /path/to/app
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
index.phpを作成
<?php
require_once __DIR__ . '/vendor/autoload.php';
// Silex
$app = new Silex\Application();
# トップページ
$app->get('/', function() use($app) {
return 'Hello World';
});
$app->run();
とりあえず表示まではこれでOKです。
ただ、SilexのテンプレートにはTwigがありますが、こちらはデフォルトではインストールされていませんので、別途TwigServiceProviderからインストールする必要があります。
また、DBも同様にDoctrineServiceProviderからインストールしてきます。
ではcomposer.jsonを編集します。
{
"require": {
"silex/silex": "~1.2",
"symfony/twig-bridge": "~2.6",
"doctrine/dbal": "~2.5"
}
}
$ composer update
これで開発に必要な環境はすべて整いました。
fullcalender.jsを利用してスケジュール管理サイトの作成
今回はこちらを利用してスケジュール帳を作りました♪
ちょいちょい俺流記述があるかと思いますので、お見苦しい点はご容赦下さい。。。
[デモ]
※デモはDBに接続していません。
DB
テーブル名:schedules
id int(11)
title varchar(50)
start datetime
end datetime
status tinyint(1)
allDay tinyint(1) デフォルト値0
deleted tinyint(1) デフォルト値0
javascriptライブラリ
ソース
index.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
// Silex
$app = new Silex\Application();
$app['debug'] = TRUE;
// Twigテンプレートエンジン
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__ . '/views',
));
// DB
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'db.options' => array(
'dbname' => 'dbname',
'user' => 'user',
'password' => 'password',
'host' => 'localhost',
'driver' => 'pdo_mysql',
)
));
//ルーティング
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
//ステータス
$statusList = array('会議', '往訪', '来訪', 'その他');
# トップページ
$app->get('/', function() use($app, $statusList) {
return $app['twig']->render('index.twing', array(
'statusList' => $statusList
));
})->bind('index');
# スケジュールの取得(トップページ)
$app->get('/getSchedule', function() use($app, $statusList) {
//未削除データをすべて取得
$stmt = $app['db']->query(
'SELECT * FROM schedules WHERE deleted = 0'
);
$scheduleList = array();
while ($row = $stmt->fetch()) {
$scheduleList[] = array(
'id' => $row['id'],
'status' => $row['status'],
'title' => '【'
. $statusList[$row['status']] . '】' . $row['title'],
'start' => date('Y-m-d H:i', strtotime($row['start'])),
'end' => date('Y-m-d H:i', strtotime($row['end'])),
'allDay' => (bool) $row['allDay']
);
}
return json_encode($scheduleList);
});
# スケジュールの登録
$app->post('/addSchedule', function() use($app) {
$start = $app['request']->get('date') . ' '
. $app['request']->get('startHour')
. ':' . $app['request']->get('startMinute');
$end = $app['request']->get('date') . ' '
. $app['request']->get('endHour')
. ':' . $app['request']->get('endMinute');
$allDay = 0;
if($app['request']->get('allDay')) {
$allDay = $app['request']->get('allDay');
}
$app['db']->insert(
'schedules',
array(
'title' => $app['request']->get('title'),
'status' => $app['request']->get('status'),
'start' => $start,
'end' => $end,
'allDay' => $allDay,
)
);
return $app->redirect($app['url_generator']->generate('index'));
});
# スケジュールの修正または削除
$app->post('/updateSchedule', function() use($app) {
if (!$app['request']->get('deleted')) {
//編集時
$start = $app['request']->get('date') . ' '
. $app['request']->get('startHour')
. ':' . $app['request']->get('startMinute') . ':00';
$end = $app['request']->get('date') . ' '
. $app['request']->get('endHour')
. ':' . $app['request']->get('endMinute') . ':00';
$app['db']->update(
'schedules',
array(
'title' => $app['request']->get('title'),
'start' => $start,
'end' => $end,
'status' => $app['request']->get('status'),
'allDay' => $app['request']->get('allDay'),
),
array(
'id' => $app['request']->get('id')
));
} else {
//削除時
$app['db']->update(
'schedules',
array(
'deleted' => $app['request']->get('deleted'),
),
array(
'id' => $app['request']->get('id')
));
}
return $app->redirect($app['url_generator']->generate('index'));
});
# エラー時
$app->error(function (\Exception $e, $code) use ($app) {
if ($app['debug']) {
return;
}
echo $e->getMessage();
});
$app->run();
views/index.twing
<!DOCTYPE html>
<html>
<head>
<link media="screen" href="./css/style.css" rel="stylesheet">
<link href="./js/fullcalendar/fullcalendar.min.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="./js/fullcalendar/moment.min.js"></script>
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script type="text/javascript" src="./js/fullcalendar/jquery-ui.custom.min.js"></script>
<script type="text/javascript" src="./js/fullcalendar/fullcalendar.js"></script>
<script type="text/javascript" src="./js/fullcalendar/ja.js"></script>
<script type="text/javascript" src="./js/jquery.lightbox_me.js"></script>
<script type="text/javascript" src="./js/index.js"></script>
<meta charset="utf-8" />
</head>
<body>
<div id="header">
<h1>スケジュール</h1>
</div>
<div id="content">
<div id="calendar" style="width:95%"></div>
<div id="schedule_form">
*スケジュール登録
<form method='post' action="" id="scheduleForm" class="formTable">
<table>
<tr id="deleteArea">
<th>削除</th>
<td>
<input type="checkbox" name="deleted" value="1" />
</td>
</tr>
<tr class="inputArea">
<th>ステータス</th>
<td>
<select name="status">
{% for key, status in statusList %}
<option value="{{key}}">{{status}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr class="inputArea">
<th>内容</th>
<td><input required type="text" name="title" /></td>
</tr>
<tr class="inputArea">
<th>日時</th>
<td><input type="text" name="date" value="" /></td>
</tr>
<tr class="inputArea">
<th>終日</th>
<td>
<input type="checkbox" name="allDay" value="1" />
</td>
</tr>
<tr class="inputArea timeArea">
<th>開始時間</th>
<td>
<select name="startHour">
{% for i in 0..23 %}
<option value="{{i}}">{{i}}</option>
{% endfor %}
</select>
:
<select name="startMinute">
<option value="0">00</option>
<option value="15">15</option>
<option value="30">30</option>
<option value="45">45</option>
</select>
</td>
</tr>
<tr class="inputArea timeArea">
<th>終了時間</th>
<td>
<select name="endHour">
{% for i in 0..23 %}
<option value="{{i}}">{{i}}</option>
{% endfor %}
</select>
:
<select name="endMinute">
<option value="0">00</option>
<option value="15">15</option>
<option value="30">30</option>
<option value="45">45</option>
</select>
</td>
</tr>
</table>
<input type="hidden" name= "id" value="" />
<br />
<div class="submit">
<input type="submit" value="送信" id="submit" />
</div>
</form>
</div>
</div>
<div id="footer"></div>
</body>
</html>
js/index.js
jQuery(document).ready(function($){
//イベント登録用フォーム
$('#schedule_form').hide();
//カレンダー設定
$('#calendar').fullCalendar({
// ヘッダーのタイトルとボタン
header: {
left: 'prev,next today',
center: 'title',
right: 'month'
},
timeFormat: 'H:mm',
theme: false,
height: 500,
// 日付クリック時
dayClick: function (date) {
//日付のみフォームにセット
var m = moment(date._d);
var month = m.month() + 1;
var setDate = m.year() + '/' + month + '/' + m.date();
setFormData(setDate);
//フォームのポップアップ表示
$('#schedule_form').lightbox_me({
centered: true,
overlaySpeed: 'fast',
});
},
//イベントクリック時
eventClick: function(event) {
//更新時は削除用のチェックボックス表示
var formArr = [];
formArr.deleteArea = 'show';
//日付のセット
var m = moment(event._start._i, event._start._f);
var date = m.format('YYYY/MM/DD'); //日付
formArr.startHour = m.hours();//時(start)
formArr.startMinute = m.minutes(); //分(start)
if (event.allDay == false) {
var m = moment(event._end._i, event._end._f);
}
formArr.endHour = m.hours(); //時(end)
formArr.endMinute = m.minutes(); //分(end)
formArr.title = event.title.replace(/^【.+?】/, '');//内容
formArr.allDay = event.allDay;//終日フラグ
formArr.id = event.id;//イベントID
formArr.status = event.status;//イベントステータス
//各データをフォームにセット
setFormData(date, formArr);
//フォームのポップアップ表示
$('#schedule_form').lightbox_me({
centered: true,
overlaySpeed: 'fast',
});
},
// 初期表示ビュー
defaultView: 'month',
//スケジュール取得
events : './getSchedule'
});
//イベント登録送信(新規登録と編集で送信先変更)
$('#submit').click(function() {
if ($(':input[name="id"]').val() != '') {
$(this).parents('form').attr('action', './updateSchedule');
} else {
$(this).parents('form').attr('action', './addSchedule');
}
$(this).parents('form').submit();
});
//削除ボタンをチェックしたらそれ以下は入力不可に
$(':input[name="deleted"]').change(function() {
if($(this).is(':checked')) {
$('.inputArea :input').prop('disabled', true);
} else {
$('.inputArea :input').prop('disabled', false);
}
});
//終日ボタンをチェックしたらそれ以下は入力不可に
$(':input[name="allDay"]').change(function() {
if($(this).is(':checked')) {
$('.timeArea :input').prop('disabled', true);
} else {
$('.timeArea :input').prop('disabled', false);
}
});
});
/*
* フォームの値をセット
*/
function setFormData(date, dataArr) {
//データがない時は初期値セット
if (dataArr == undefined) {
var dataArr = {
'startHour' : 0,
'startMinute' : 0,
'endHour' : 0,
'endMinute' : 0,
'title' : '',
'id' : '',
'status' : 0,
'allDay' : false,
'deleteArea' : 'hidden'
};
}
//各データをフォームにセット
$(':input[name="date"]').val(date);
$(':input[name="startHour"]').val(dataArr.startHour);
$(':input[name="startMinute"]').val(dataArr.startMinute);
$(':input[name="endHour"]').val(dataArr.endHour);
$(':input[name="endMinute"]').val(dataArr.endMinute);
$(':input[name="title"]').val(dataArr.title);
$(':input[name="id"]').val(dataArr.id);
$(':input[name="status"]').val(dataArr.status);
$(':input[name="deleted"]').prop('checked', false);
$('.inputArea :input').prop('disabled', false);
//イベント更新時は削除フォームを表示
if (dataArr.deleteArea == 'show') {
$('#deleteArea').show();
} else {
$('#deleteArea').hide();
}
//終日の場合は時間の選択不可
$(':input[name="allDay"]').prop('checked', true);
$('.timeArea :input').prop('disabled', true);
if(dataArr.allDay == true) {
$(':input[name="allDay"]').prop('checked', true);
$('.timeArea :input').prop('disabled', true);
} else {
$(':input[name="allDay"]').prop('checked', false);
$('.timeArea :input').prop('disabled', false);
}
}
解説
indexを表示すると
fullcadenderのオプションで設定した
events : './getSchedule'
でイベントデータをDBから引っ張ってきてカレンダーに反映させます。
※イベント登録
カレンダー上の日付をクリックすると、dayClickのfunctionが呼ばれます。
初期値をセットして、フォームが書かれたdivをポップアップ表示します。
こちらはイベントの更新時にも使用するフォームのため、idのあるなしでフォームの送信先をかえています。
※イベント更新・削除
カレンダー上に表示しているイベントをクリックすると、eventClickのfunctionが呼ばれます。
もろもろフォームにセットしてポップアップ表示。
送信するとphpからDBの更新をしてくれます。
なんか色々とっ散らかってる感じが満載ですが、今回はこんなもんでご勘弁下さい。
またいずれ時が来たら修正しますので。。。(逃)