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

Google Map : RefererNotAllowedMapError

vagrantでは表示されるのに、本番環境で、google map apiが表示されない!?
dev toolのconsoleを見ると、

Google Maps API error: RefererNotAllowedMapError https://developers.google.com/maps/documentation/javascript/error-messages#referer-not-allowed-map-error
Your site URL to be authorized

Google Maps Geocoding API
Google Maps JavaScript API
どうやら、js側ではなく、geocodingを有効化しないといけなかったようです。
Google Cloud Platformでgeocodingを有効化し、httpリファラーを設定して数分経ったら、本番環境でも表示されるようになりました。

http://phone-search.online/?p=0526130480

str_replaceの回数指定

03-6803-5794から、”03-“をstr_replaceすると、重複して削除され、685794になってしまう。

preg_replaceなら、回数を指定できる。

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

電話番号から、市外局番、市内局番、加入者番号を抜き出す

strstr trueでハイフン(-)より前を抜き出し、str_replaceで抜き出した数+ハイフンを削除して、またstrstr trueでハイフン(-)より前を抜き出します。

$number = empty($_GET["p"])? NULL: $_GET["p"];
$number = str_replace('-','', $number);

require "function.php";

$number = format_phone_number($number);

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

echo $num1 . "<br>";
echo $num2 . "<br>";
echo $num3;

おおおおお

車輪の再発明:reinventing the wheel

電話番号の市外局番、市内局番を分岐させようと条件分岐式を書いていましたが

$number = str_replace('-','', $number);

$num_2 = substr($number, 0, 2);
$num_5 = substr($number, 0, 5);
if($num_2 == '03' or $num_2 == '04' or $num_2 == '06'){
  $num1 = substr($number, 0, 2);
  $num2 = substr($number, 2, 4);
  $num3 = substr($number, 6, 4);
}elseif($num_5 == '01372' or $num_5 == '01374' or $num_5 == '01377' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '' or $num_5 == '')

書いている途中で車輪の再発明は辞めようと思いました。
function.php

function format_phone_number($input, $strict = false) {
    $groups = array(
        5 => 
        array (
            '01564' => 1,
            '01558' => 1,
            '01586' => 1,
            '01587' => 1,
            '01634' => 1,
            '01632' => 1,
            '01547' => 1,
            '05769' => 1,
            '04992' => 1,
            '04994' => 1,
            '01456' => 1,
            '01457' => 1,
            '01466' => 1,
            '01635' => 1,
            '09496' => 1,
            '08477' => 1,
            '08512' => 1,
            '08396' => 1,
            '08388' => 1,
            '08387' => 1,
            '08514' => 1,
            '07468' => 1,
            '01655' => 1,
            '01648' => 1,
            '01656' => 1,
            '01658' => 1,
            '05979' => 1,
            '04996' => 1,
            '01654' => 1,
            '01372' => 1,
            '01374' => 1,
            '09969' => 1,
            '09802' => 1,
            '09912' => 1,
            '09913' => 1,
            '01398' => 1,
            '01377' => 1,
            '01267' => 1,
            '04998' => 1,
            '01397' => 1,
            '01392' => 1,
        ),
        4 => 
        array (
            '0768' => 2,
            '0770' => 2,
            '0772' => 2,
            '0774' => 2,
            '0773' => 2,
            '0767' => 2,
            '0771' => 2,
            '0765' => 2,
            '0748' => 2,
            '0747' => 2,
            '0746' => 2,
            '0826' => 2,
            '0749' => 2,
            '0776' => 2,
            '0763' => 2,
            '0761' => 2,
            '0766' => 2,
            '0778' => 2,
            '0824' => 2,
            '0797' => 2,
            '0796' => 2,
            '0555' => 2,
            '0823' => 2,
            '0798' => 2,
            '0554' => 2,
            '0820' => 2,
            '0795' => 2,
            '0556' => 2,
            '0791' => 2,
            '0790' => 2,
            '0779' => 2,
            '0558' => 2,
            '0745' => 2,
            '0794' => 2,
            '0557' => 2,
            '0799' => 2,
            '0738' => 2,
            '0567' => 2,
            '0568' => 2,
            '0585' => 2,
            '0586' => 2,
            '0566' => 2,
            '0564' => 2,
            '0565' => 2,
            '0587' => 2,
            '0584' => 2,
            '0581' => 2,
            '0572' => 2,
            '0574' => 2,
            '0573' => 2,
            '0575' => 2,
            '0576' => 2,
            '0578' => 2,
            '0577' => 2,
            '0569' => 2,
            '0594' => 2,
            '0827' => 2,
            '0736' => 2,
            '0735' => 2,
            '0725' => 2,
            '0737' => 2,
            '0739' => 2,
            '0743' => 2,
            '0742' => 2,
            '0740' => 2,
            '0721' => 2,
            '0599' => 2,
            '0561' => 2,
            '0562' => 2,
            '0563' => 2,
            '0595' => 2,
            '0596' => 2,
            '0598' => 2,
            '0597' => 2,
            '0744' => 2,
            '0852' => 2,
            '0956' => 2,
            '0955' => 2,
            '0954' => 2,
            '0952' => 2,
            '0957' => 2,
            '0959' => 2,
            '0966' => 2,
            '0965' => 2,
            '0964' => 2,
            '0950' => 2,
            '0949' => 2,
            '0942' => 2,
            '0940' => 2,
            '0930' => 2,
            '0943' => 2,
            '0944' => 2,
            '0948' => 2,
            '0947' => 2,
            '0946' => 2,
            '0967' => 2,
            '0968' => 2,
            '0987' => 2,
            '0986' => 2,
            '0985' => 2,
            '0984' => 2,
            '0993' => 2,
            '0994' => 2,
            '0997' => 2,
            '0996' => 2,
            '0995' => 2,
            '0983' => 2,
            '0982' => 2,
            '0973' => 2,
            '0972' => 2,
            '0969' => 2,
            '0974' => 2,
            '0977' => 2,
            '0980' => 2,
            '0979' => 2,
            '0978' => 2,
            '0920' => 2,
            '0898' => 2,
            '0855' => 2,
            '0854' => 2,
            '0853' => 2,
            '0553' => 2,
            '0856' => 2,
            '0857' => 2,
            '0863' => 2,
            '0859' => 2,
            '0858' => 2,
            '0848' => 2,
            '0847' => 2,
            '0835' => 2,
            '0834' => 2,
            '0833' => 2,
            '0836' => 2,
            '0837' => 2,
            '0846' => 2,
            '0845' => 2,
            '0838' => 2,
            '0865' => 2,
            '0866' => 2,
            '0892' => 2,
            '0889' => 2,
            '0887' => 2,
            '0893' => 2,
            '0894' => 2,
            '0897' => 2,
            '0896' => 2,
            '0895' => 2,
            '0885' => 2,
            '0884' => 2,
            '0869' => 2,
            '0868' => 2,
            '0867' => 2,
            '0875' => 2,
            '0877' => 2,
            '0883' => 2,
            '0880' => 2,
            '0879' => 2,
            '0829' => 2,
            '0550' => 2,
            '0228' => 2,
            '0226' => 2,
            '0225' => 2,
            '0224' => 2,
            '0229' => 2,
            '0233' => 2,
            '0237' => 2,
            '0235' => 2,
            '0234' => 2,
            '0223' => 2,
            '0220' => 2,
            '0192' => 2,
            '0191' => 2,
            '0187' => 2,
            '0193' => 2,
            '0194' => 2,
            '0198' => 2,
            '0197' => 2,
            '0195' => 2,
            '0238' => 2,
            '0240' => 2,
            '0260' => 2,
            '0259' => 2,
            '0258' => 2,
            '0257' => 2,
            '0261' => 2,
            '0263' => 2,
            '0266' => 2,
            '0265' => 2,
            '0264' => 2,
            '0256' => 2,
            '0255' => 2,
            '0243' => 2,
            '0242' => 2,
            '0241' => 2,
            '0244' => 2,
            '0246' => 2,
            '0254' => 2,
            '0248' => 2,
            '0247' => 2,
            '0186' => 2,
            '0185' => 2,
            '0144' => 2,
            '0143' => 2,
            '0142' => 2,
            '0139' => 2,
            '0145' => 2,
            '0146' => 2,
            '0154' => 2,
            '0153' => 2,
            '0152' => 2,
            '0138' => 2,
            '0137' => 2,
            '0125' => 2,
            '0124' => 2,
            '0123' => 2,
            '0126' => 2,
            '0133' => 2,
            '0136' => 2,
            '0135' => 2,
            '0134' => 2,
            '0155' => 2,
            '0156' => 2,
            '0176' => 2,
            '0175' => 2,
            '0174' => 2,
            '0178' => 2,
            '0179' => 2,
            '0184' => 2,
            '0183' => 2,
            '0182' => 2,
            '0173' => 2,
            '0172' => 2,
            '0162' => 2,
            '0158' => 2,
            '0157' => 2,
            '0163' => 2,
            '0164' => 2,
            '0167' => 2,
            '0166' => 2,
            '0165' => 2,
            '0267' => 2,
            '0250' => 2,
            '0533' => 2,
            '0422' => 2,
            '0532' => 2,
            '0531' => 2,
            '0436' => 2,
            '0428' => 2,
            '0536' => 2,
            '0299' => 2,
            '0294' => 2,
            '0293' => 2,
            '0475' => 2,
            '0295' => 2,
            '0297' => 2,
            '0296' => 2,
            '0495' => 2,
            '0438' => 2,
            '0466' => 2,
            '0465' => 2,
            '0467' => 2,
            '0478' => 2,
            '0476' => 2,
            '0470' => 2,
            '0463' => 2,
            '0479' => 2,
            '0493' => 2,
            '0494' => 2,
            '0439' => 2,
            '0268' => 2,
            '0480' => 2,
            '0460' => 2,
            '0538' => 2,
            '0537' => 2,
            '0539' => 2,
            '0279' => 2,
            '0548' => 2,
            '0280' => 2,
            '0282' => 2,
            '0278' => 2,
            '0277' => 2,
            '0269' => 2,
            '0270' => 2,
            '0274' => 2,
            '0276' => 2,
            '0283' => 2,
            '0551' => 2,
            '0289' => 2,
            '0287' => 2,
            '0547' => 2,
            '0288' => 2,
            '0544' => 2,
            '0545' => 2,
            '0284' => 2,
            '0291' => 2,
            '0285' => 2,
            '0120' => 3,
            '0570' => 3,
            '0800' => 3,
            '0990' => 3,
        ),
        3 => 
        array (
            '099' => 3,
            '054' => 3,
            '058' => 3,
            '098' => 3,
            '095' => 3,
            '097' => 3,
            '052' => 3,
            '053' => 3,
            '011' => 3,
            '096' => 3,
            '049' => 3,
            '015' => 3,
            '048' => 3,
            '072' => 3,
            '084' => 3,
            '028' => 3,
            '024' => 3,
            '076' => 3,
            '023' => 3,
            '047' => 3,
            '029' => 3,
            '075' => 3,
            '025' => 3,
            '055' => 3,
            '026' => 3,
            '079' => 3,
            '082' => 3,
            '027' => 3,
            '078' => 3,
            '077' => 3,
            '083' => 3,
            '022' => 3,
            '086' => 3,
            '089' => 3,
            '045' => 3,
            '044' => 3,
            '092' => 3,
            '046' => 3,
            '017' => 3,
            '093' => 3,
            '059' => 3,
            '073' => 3,
            '019' => 3,
            '087' => 3,
            '042' => 3,
            '018' => 3,
            '043' => 3,
            '088' => 3,
            '050' => 4,
        ),
        2 => 
        array (
            '04' => 4,
            '03' => 4,
            '06' => 4,
        ),
    );
    $groups[3] += 
        $strict ?
        array(
            '020' => 3,
            '070' => 3,
            '080' => 3,
            '090' => 3,
        ) :
        array(
            '020' => 4,
            '070' => 4,
            '080' => 4,
            '090' => 4,
        )
    ;
    $number = preg_replace('/[^\d]++/', '', $input);
    foreach ($groups as $len => $group) {
        $area = substr($number, 0, $len);
        if (isset($group[$area])) {
            $formatted = implode('-', array(
                $area,
                substr($number, $len, $group[$area]),
                substr($number, $len + $group[$area])
            ));
            return strrchr($formatted, '-') !== '-' ? $formatted : $input;
        }
    }
    $pattern = '/\A(00(?:[013-8]|2\d|91[02-9])\d)(\d++)\z/';
    if (preg_match($pattern, $number, $matches)) {
        return $matches[1] . '-' . $matches[2];
    }
    return $input;
}

修正
function.phpをrequire

$number = empty($_GET["p"])? NULL: $_GET["p"];
$number = str_replace('-','', $number);

require "function.php";

$number = format_phone_number($number);

echo $number;

2000万ファイルの作成について

東京都の電話番号の全てのパターンをつくりたいとする

03-XXXX-YYYY

市外局番:03
市内局番:3100~6999(2264件)
加入者番号:0000~9999(9999件)

仮に全て、ファイルを作ったとすると、2264万ファイル作成することになる。

「Linuxの場合、一つのディレクトリの配下に10000個から15000個程度のファイルを作成することが出来るが、実際には5000個もファイルを作成するとディスクI/Oの性能が落ち、ファイル読み書きのパフォーマンスが落ちる」、とのこと。