pdoで予約情報をmysqlに格納する

■mysql側
まず、テーブルを作ります。
1.管理画面側で予約情報をcake.phpで閲覧できるようにしたいので、テーブル名は複数にします。
2.いたずらの予約が複数回あった場合は、そのipアドレスをhtaccessでアクセス制御できるようにしたいので、ipアドレスと、user agentのカラムを作ります。
3.予約送信時間の型は、yyyy-mm-ddではなくyyyy-mm-dd h:i:sなので、dateではなくdatetimeにします。(間違えました)
4.管理者画面で後からメモをinsert出来るようにしたいので、memoのカラムを作ります。

create table reserve.masters(
        id int unsigned auto_increment primary key,
        day varchar(255),
	time1 varchar(41),
	time2 varchar(41),
	course varchar(41),
	charge varchar(41),
	name varchar(41),
	mail varchar(41),
	ip varchar(255),
	useragent varchar(255),
	created datetime,
	memo varchar(255)
);

■php側
普通のpdoです。REMOTE_ADDRとHTTP_USER_AGENTでユーザー情報を取得しています。

$start = $_POST['stime'];
	$end = $_POST['etime'];

	$ip = $_SERVER['REMOTE_ADDR'];
	$useragent = $_SERVER['HTTP_USER_AGENT'];
	$date = date('Y-m-d H:i:s');

	$dsn = "mysql:dbname=reserve;host=localhost";
	$user = "hoge";
	$password = "hogehoge";	 
	try {
	    $dbh = new PDO($dsn, $user, $password);
	} catch (PDOException $e){
	    print('connection failed:'.$e->getMessage());
	} 

	$stmt = $dbh -> prepare("INSERT INTO masters (day, time1, time2, course, charge, name, mail, ip, useragent, created) VALUES(:day, :time1, :time2, :course, :charge, :name, :mail, :ip, :useragent, :created)");
	$stmt->bindParam(':day', $_POST['day'], PDO::PARAM_STR);
	$stmt->bindParam(':time1', $_POST['time1'], PDO::PARAM_STR);
	$stmt->bindParam(':time2', $_POST['time2'], PDO::PARAM_STR);
	$stmt->bindParam(':course', $_POST['course'], PDO::PARAM_STR);
	$stmt->bindParam(':charge', $_POST['charge'], PDO::PARAM_STR);
	$stmt->bindParam(':name', $_POST['name'], PDO::PARAM_STR);
	$stmt->bindParam(':mail', $_POST['mail'], PDO::PARAM_STR);
	$stmt->bindParam(':ip', $ip, PDO::PARAM_STR);
	$stmt->bindParam(':useragent', $useragent, PDO::PARAM_STR);
	$stmt->bindParam(':created', $date, PDO::PARAM_STR);
    $stmt->execute();

■画面遷移
1.入力フォーム

2.確認画面

3.thankyou画面

4.メール受信

5.mysql

ここまでは特に問題なさそうです。
次はvalidation周りを作っていきたいと思います。

簡易的な確認画面

mb_send_mailでメールを送る。

if(!isset($_POST['name'])){
   header('Location: http://192.168.33.10:8000');
} else {
	$name = $_POST['name'];
	$mail = $_POST['mail'];
	$day = $_POST['day'];
	$time = $_POST['time'];
	$hour = floor($time / 60);
	$minutes = $time % 60;
	if(!$minutes == NUll ){
			$stime = $hour.":".$minutes;
		}  else {
			$stime = $hour.":00";
		}
	$time =$_POST['time'] + $_POST['course'];
	$hour = floor($time / 60);
	$minutes = $time % 60;
	if(!$minutes == NUll ){
			$etime = $hour.":".$minutes;
		}  else {
			$etime = $hour.":00";
		}
	$course = $_POST['course'];
	$lawyer = $_POST['lawyer'];
}

if(isset($_POST["submit"])){
	mb_language('ja');
	mb_internal_encoding("utf-8");

	$start = $_POST['stime'];
	$end = $_POST['etime'];

	$subject = "[自動送信]お問い合わせありがとうございます";

	$body = <<< EOM

 {$name} 様

この度はご予約ありがとうございます。
以下のご予約内容を承りました。
===================================================
【 お名前 】 
{$name} 様

【 メールアドレス 】 
{$mail}

【 ご予約日時 】 
{$day} {$start} ~ {$end}

【 コース 】
{$course} 分

【 担当弁護士 】 
{$lawyer}
===================================================

内容を確認のうえ、回答させて頂きます。

〇〇弁護士事務所
EOM;
     $fromEmail = "hoge@gmail.com";
     $fromName = "〇〇事務所";
     $header = "From:".mb_encode_mimeheader($fromName)."<$fromEmail>";
     mb_send_mail($mail,$subject,$body,$header);

     // header("Location: thanks.php");
     exit;
}
?>
<form action="" method="post">
<input type="hidden" name="name" value="<?php echo $name; ?>">
<input type="hidden" name="mail" value="<?php echo $mail; ?>">
<input type="hidden" name="day" value="<?php echo $day; ?>">
<input type="hidden" name="stime" value="<?php echo $stime; ?>">
<input type="hidden" name="etime" value="<?php echo $etime; ?>">
<input type="hidden" name="course" value="<?php echo $course; ?>">
<input type="hidden" name="lawyer" value="<?php echo $lawyer; ?>">
<h1>お問い合わせ内容の確認</h1>
<p>お問い合わせ内容はこちらで宜しいでしょうか?<br>
よろしければ「送信する」ボタンを押してください。<hr>
<b>お名前</b><br>
<?php echo $name; ?>様<br>
<b>メールアドレス</b><br>
<?php echo $mail; ?><br>
<b>日付</b><br>
<?php echo $day; ?><br>
<b>時間</b><br>
<?php echo $stime; ?>~<?php echo $etime; ?><br>
<b>コース</b><br>
<?php echo $course; ?>分<br>
<b>担当</b><br>
<?php echo $lawyer; ?><br><br>
<input type="button" value="内容を修正する" onclick="history.back(-1)">
<button type="submit" name="submit">送信する</button>
</form>

メール

予約日(datepicker)が今日の場合は、現在時刻以降のselectを表示

onSelectのところで、dateTextが今日を選択された場合、idと現在時刻の分を比較して、idが現在時刻より前(値が小さければ)、display noneに変更する。

onSelect: function(dateText, inst) {
                    $("#date_val").val(dateText);
                    if(today == dateText){
                    	for(var i = 0; i < timelist.length; i++){
                    		if(timelist[i] < time){
                    			document.getElementById(timelist[i]).style.display = "none";
                    		}
                    	}
                    	
                    } else{
                    	for(var i = 0; i < timelist.length; i++){
                    			document.getElementById(timelist[i]).style.display = "";
                    	}
                    }              
        }

デフォルト

今日の日付が選択された場合
->現在時刻以降しか選択できない

きた!

if(timelist[i] < time + 60) とすれば、現在時刻から、1時間後以降しか選べなくなりますね♪♪♪

phpで予約システムを作くろう3 予約時間

予約時間をselectできるようにします。

<b>予約フォーム</b><br>
<form method="POST" action="">
1.お名前(必須)<br>
<input class="form1" type="text" name="username" placeholder=" お名前"/><br><br>
2.メールアドレス(必須)<br>
<input class="form1" type="text" name="username" placeholder=" 〇〇@gmail.com"/><br><br>
3.カレンダーから日付を選択してください<br>
<input type="text" id="date_val" placeholder=" 2018年〇月〇日"/><br>
<div id="datepicker"></div><br>
4.時間を選択してください<br>
	<select name="time">
	<option value=""> 選択してください</option>
	<option value="">9:00~</option>
	<option value="">10:00~</option>
	<option value="">11:00~</option>
	<option value="">13:00~</option>
	<option value="">14:00~</option>
	<option value="">15:00~</option>
	<option value="">16:00~</option>
	<option value="">17:00~</option>
	</select>

	<select name="time">
	<option value="">30分</option>
	<option value="" selected>60分</option>
	<option value="">90分</option>
	<option value="">120分</option>
	</select>

	<br><br>
5.ご希望される弁護士を選択してください<br>
	<select name="lawyer">
	<option value=""> 選択してください</option>
	<option value="">松島</option>
	<option value="">小野</option>
	<option value="">草野</option>
	</select>
	<br><br>
	<input type="submit" value="予約する" class="submit">
</form>

あれ、これ、もしかして、valueをminuteで変換すればいいだけじゃないですかね?
おいおいおい、結構簡単ではないですか。

datepickerを日本語化する

asset/datepicker-ja.js

jQuery(function($){
    $.datepicker.regional['ja'] = {
        closeText: '閉じる',
        prevText: '<前',
        nextText: '次>',
        currentText: '今日',
        monthNames: ['1月','2月','3月','4月','5月','6月',
        '7月','8月','9月','10月','11月','12月'],
        monthNamesShort: ['1月','2月','3月','4月','5月','6月',
        '7月','8月','9月','10月','11月','12月'],
        dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
        dayNamesShort: ['日','月','火','水','木','金','土'],
        dayNamesMin: ['日','月','火','水','木','金','土'],
        weekHeader: '週',
        dateFormat: 'yy/mm/dd',
        firstDay: 0,
        isRTL: false,
        showMonthAfterYear: true,
        yearSuffix: '年'};
    $.datepicker.setDefaults($.datepicker.regional['ja']);
});

index.phpのheader

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="asset/datepicker-ja.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.css">

javascript lang:’ja’を追加

$(function() {
	var dateFormat = 'yy年mm月dd日';
    $("#datepicker").datepicker({
    	lang:'ja',
        dateFormat: dateFormat,
        minDate: 0,
        onSelect: function(dateText, inst) {
                    $("#date_val").val(dateText);
        }
    });
});

view -> OK!

土日選択不可

$(function() {
	var dateFormat = 'yy年mm月dd日';
    $("#datepicker").datepicker({
    	lang:'ja',
        dateFormat: dateFormat,
        minDate: 0,
        onSelect: function(dateText, inst) {
                    $("#date_val").val(dateText);
        }
    });
    $( "#datepicker" ).datepicker('option','beforeShowDay',function(date){
	    var ret = [(date.getDay() != 0 && date.getDay() != 6)];
	    return ret;
	});
});

phpで予約システムを作くろう2 予約画面

jQueryのdatepickerで日付を取得します。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.css">
<b>予約フォーム</b><br>
<form method="POST" action="">
1.カレンダーから日付を選択してください<br>
<input type="text" id="date_val"/><br>
<div id="datepicker"></div><br>
2.時間を選択してください<br>
	<select name="time">
	<option value=""> 選択してください</option>
	<option value="">9:00~10:00</option>
	<option value="">10:00~11:00</option>
	<option value="">11:00~12:00</option>
	<option value="">13:00~14:00</option>
	<option value="">14:00~15:00</option>
	<option value="">15:00~16:00</option>
	<option value="">16:00~17:00</option>
	<option value="">17:00~18:00</option>
	</select><br><br>
3.ご希望される弁護士を選択してください<br>
	<select name="lawyer">
	<option value=""> 選択してください</option>
	<option value="">松島</option>
	<option value="">小野</option>
	<option value="">草野</option>
	</select>
	<br><br>
	<input type="submit" value="予約する" class="submit">
</form>

<script>
$(function() {
	var dateFormat = 'yy年mm月dd日';
    $("#datepicker").datepicker({
        dateFormat: dateFormat,
        minDate: 0,
        onSelect: function(dateText, inst) {
                    $("#date_val").val(dateText);
        }
    });
});
</script>

あれ?かなり簡単にできたが大丈夫か?

画面遷移を以下のようにしたい。
1.今週のスケジュール表(view) -> 2.予約画面(form) -> 3.確認画面(重複チェック:validation) -> 4.ユーザー・担当者へ確認メール送信(mb_send_mail) -> 5.管理者画面で予約を一覧表示

1.今週のスケジュールは、今日の日付と曜日を取得して、DBから予約を引き出す。
3.確認画面でのvalidation
-> 予約時間が全て1時間単位なら、問題なさそう
-> 予約時間が30分、1時間、1時間30分のように選択式にすると、計算が複雑になりそうだ

### PHPとMySQLの接続を解説をしている本
本屋で立ち読みでも良いが、作った後に本で確認すると頭の中が整理されて参考になります。

phpで予約システムを作くろう1 DBの設計

弁護士事務所の予約システムを作っていきたい。

まず、DBの設計からですが、
基本は「ユーザーから予約リクエストがあったら、テーブルに書き込む」となりますが、どういう設計がいいのでしょうか?

初期設計では、マスターのテーブルと、予約したい人のそれぞれのテーブルを作っていく、という作りで始めてみたいと思います。
予約時間を30分、1時間、1時間30分、2時間と選べるようにしたいので、timeのカラムもつくります。

create table reserve.master(
	id int unsigned auto_increment primary key,
	reserve date,
	name varchar(255)
)

create table reserve.matsushima(
	id int unsigned auto_increment primary key,
	reserve date,
	time varchar(255),
	name varchar(255),
	content varchar(255)
)

create table reserve.ono(
	id int unsigned auto_increment primary key,
	reserve date,
	time varchar(255),
	name varchar(255),
	content varchar(255)
)

create table reserve.kusano(
	id int unsigned auto_increment primary key,
	reserve date,
	time varchar(255),
	name varchar(255),
	content varchar(255)
)

ファイルのルーティング

例えば、電話のXX-YYYY-ZZZZのうち、YYYY(市内局番)によって、読み込むディレクトリを変えたいとする。
その場合、ファイルをインクルードする際に、フォルダを指定すればよい。

以下のように、6832と6833のフォルダを作る。

$_SERVER[‘PATH_INFO’]でパスを読み込んで、市内局番のフォルダから、加入者番号のファイルを読み込めばよい。

$path = explode('/', $_SERVER['PATH_INFO']);

require "function.php";
$number = format_phone_number($path[1]);

$num1 =  strstr($number, '-', true);
$num = preg_replace("/".$num1."-/","", $number, 1);
$num2 =  strstr($num, '-', true);
$num3 = str_replace("".$num2."-","", $num);

include("".$num2."/".$num3.".php");

0368320900

0368330900

例えば、市内局番が2264件、それぞれ加入者番号が9999件あったとすれば、2264個のフォルダ(ディレクトリ)をつくり、そこから加入者番号のファイルを読み込めばいいので、フォルダを分散させて、フレームワークのルーティングのようにインクルードすれば、理論上、2000万ファイルを作ることは可能ということになる。

@mediaでレスポンシブルを設計する

まず初期画面

mobileの場合は、1カラムで表示させたい。

amazonトップページのソースからcssを見るとどうやら、768pxと979pxで切り分けているので、メディアクエリ@mediaはひとまず768pxしたいと思います。

https://www.amazon.co.jp

@media (max-width:767px){.a-visible-phone{display:inherit!important}.a-hidden-phone{display:none!important}.a-hidden-desktop{display:inherit!important}.a-visible-desktop{display:none!important}}@media (min-width:768px) and (max-width:979px){.a-visible-tablet{display:inherit!important}

max-width:767pxの時は、float:leftとfloat:rightを解除します。

@media screen and (min-width: 767px) {
	#content{
	width:800px;
	margin:10px auto;
	}
	fieldset{
		border:1px #C0C0C0 solid;
	}
	h1 {
		display:inline;
	}
	#img {
		height:28px;
	}
	.form1{
	    margin-top: 1em;
	    padding: .5em;
	    size:80;
	}
	.submit1{
	    margin-top: 1em;
	    padding: .3em;
	}
	#owner{
		width:52%;
		float:left;
	}
	#map{
		width: 45%;
		float:right;
		height: 200px;
	}
}

@media screen and (max-width: 767px) {
	#content{
	width:75%;
	margin:5px auto;
	}
	fieldset{
		border:1px #C0C0C0 solid;
	}
	h1 {
		display:inline;
		font-size:18px;
	}
	#img{
		height:18px;
	}
	.form1{
	    margin-top: 1em;
	    padding: .5em;
	    size:25;
	}
	.submit1{
	    margin-top: 1em;
	    padding: .3em;
	}
	#owner{
		width:99%;
	}
	#map{
		width: 99%;
		margin-top:5px;
		height: 200px;
	}
}

一応、レスポンシブルになりました。
min768px

max767px