Webエンジニア 新人日記

Webエンジニアになりました。元々はCOBOLやらBASICやらでプログラムしてました。C言語やVisualBasicは趣味でやっていましたが、久々に現場復帰ということです。資格はエンベデッドスペシャリスト、DBスペシャリスト、ネットワークスペシャリスト、セキュリティスペシャリスト、システムアーキテクト、プロジェクトマネージャ他を所有

【Javascript + PHP】AjaxでDBのデータをJSONで受け取る

JavascriptでDBにアクセスする場合、AjaxPHP側にパラーメータを投げてデータを受け取るのが一般的。
データの受取はJSONにするのがスマート。

Javascriptの場合、PHP側を呼び出すためにはPOSTが良いのでは。

//POSTメソッドで送るデータを定義する
//var data = {パラメータ : 値};
var data = {
	request : $('#bus').val(), 
	init : initflg, 
	};
//Ajax通信メソッド
//type : HTTP通信の種類(POSTとかGETとか)
//url  : リクエスト送信先のURL
//data : サーバに送信する値
$.ajax({
  type: "POST",
  url: "bus.php",
  data: data,
  dataType: "json",
  //Ajax通信が成功した場合に呼び出されるメソッド
  success: function(json){
    console.log(json);
//成功した場合はjson構造体の配列に格納される

    //出力する部分
    $('#result').html(json);
  },
  //Ajax通信が失敗した場合に呼び出されるメソッド
  error: function(XMLHttpRequest, textStatus, errorThrown){
    alert('Error : ' + errorThrown);
    $("#XMLHttpRequest").html("XMLHttpRequest : " + XMLHttpRequest.status);
    $("#textStatus").html("textStatus : " + textStatus);
    $("#errorThrown").html("errorThrown : " + errorThrown);
  }
  
});

この場合、json[0].メンバ名~json[json.length-1].メンバ名までの配列に格納されている。


PHP側では、PDOでDBにアクセスしよう。

$sql .= "SELECT `a`, `b`, `c` FROM `tbl` WHERE `key` = ?";
$stmt = $dbh->prepare($sql);
$stmt->execute(array($bus));
header('Content-type: application/json');
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));

SELECTで指定した項目をキーとして、fetchAllで全件データを取得と同時に
JSONエンコードする。header指定することでJavascript側にJSONで返すことができる。
{}や[]を使った整形を気にしなくて良いので楽といえば楽。

【Javascript】タイマー処理においてのSetTimeout

GPSロガーをWebアプリで開発

Webアプリで、一定間隔毎になにか処理をさせたいときにはJavascriptを使う。
ところが、これが少し曲者だったりする。

例えば、GPSロガーをWebアプリで実装しようとする。一定時間毎にDBにGPS情報を登録する。
Javascript側でDBに書き込みせずにAjaxで書き込みしようとする。
こちらが実際に書き込みを行う部分

var interval=5000;

var sendgeo = function(){

    if (navigator.geolocation) {
        // 現在の位置情報取得を実施
        navigator.geolocation.getCurrentPosition(
		// 位置情報取得成功時
		function (pos) { 
//取得したGPS情報を画面に書き出す
			var location ="<li>"+"緯度:" + pos.coords.latitude + "</li>";
			location += "<li>"+"経度:" + pos.coords.longitude + "</li>";
			var nDate = new Date();
			location += "<li>"+"時刻:" + nDate.getHours() + ":" + nDate.getMinutes() + ":" + nDate.getSeconds() + "</li>";
//ajaxにて現在地をDBに書き込む
			var data = {
				bus : $('#bus').val(), 
				lat : pos.coords.latitude,
				lng : pos.coords.longitude,
			};

    //Ajax通信メソッド
    //type : HTTP通信の種類(POSTとかGETとか)
    //url  : リクエスト送信先のURL
    //data : サーバに送信する値
			$.ajax({
				type: "POST",
				url: "sendgeo.php",
				data: data,
				dataType: "html",
			//Ajax通信が成功した場合に呼び出されるメソッド
				success: function(html){
					$('#location').html(location);
					$('#result').html(html);
				}
			});				
		},
		// 位置情報取得失敗時
		function (error) {
			var message = "";

			switch (error.code) {
			   // 位置情報取得できない場合
			   case error.POSITION_UNAVAILABLE:
			       message = "位置情報の取得ができませんでした。";
			       break;
			  // Geolocation使用許可されない場合
			  case error.PERMISSION_DENIED:
			      message = "位置情報取得の使用許可がされませんでした。";
			      break;
			  // タイムアウトした場合 
			  case error.PERMISSION_DENIED_TIMEOUT:
			      message = "位置情報取得中にタイムアウトしました。";
			      break;
			}
			window.alert(message);
		});
	} else {
		window.alert("本ブラウザではGeolocationが使えません");
	}
}

この処理を一定間隔で起動するために

$(document).ready(function() {
 var id;

  var setCurrent = function(){
	sendgeo();
	id = setTimeout(setCurrent, interval);
  }
});

setTimeoutで、自分自身を読み出すことで無限ループを実現している。

問題発生

ところが、このスクリプトはPC上ではうまく動くがスマホではうまく動かない。
ログが書き込まれた時刻を見ると、「同じ時刻に数件書き込まれる」
が繰り返され、等間隔に記録されているとは言い難い。

原因

setTimeoutの仕様を調べてみると、「指定された時間が経過したら実行」ではなく
「指定された時間が経過したら実行キューに登録」であった。
そして、実行キューにはいったタスクを実行するタイミングが
おそらくスマホではリアルタイムではなかったということだろう。

実行すると約束したが、いつ何時とまでは約束していないっ......


ってことかな。

ブラウザによる違い

Chromeではhttp通信でGPSを使用できないようになっているようです(Chrome50から)

Xperia Z3(Android 5.0.2)特に省電力設定なし

・標準ブラウザ・・・20秒間隔
Chrome・・・20秒間隔
FireFox・・・最初の数件はリアルタイム 途中から反応なし(プログラムの問題?)
・ドルフィンブラウザ・・・20秒間隔

iPhone7(iOS10.0.1)

Chrome・・・リアルタイム?5秒間隔でもOK
Safari・・・GPSを取得できず

【Word】バーコードの印刷について

Word2010でバーコードを印刷する場合、一番簡単なのはCODE39フォントをインストールする方法。

①ここ
www.technical.jp
を参考に、フォントをインストールする

②スタートとストップ用のキャラクターとして*(アスタリスク)で、バーコード化したい文字を挟む
例)123456をフォント化したい場合
123456 → *123456*

③スタートとストップキャラクターを含めて、フォントをCODE39に変更する。
※改行コードは含めないこと

改行コードを含めた場合、「画面上はバーコードとして表示されないが、印刷時にバーコードになる」という事になってしまう。なかなか気が付きにくい。スタートはともかくストップキャラクターがないので正常に読み込まないf:id:ftomo100:20160906174703j:plain

【SQL】truncateとdelete

DELETE FROM `テーブル名`

TRUNCATE `テーブル名`

の違いについて。

①権限
DELETEは1行ずつ削除するためにdelete権限が必要。DML
元に戻すためにログも書いているので、実行すると遅い。
TRUNCATEは、DROP TABLEしてから再作成しているため、
DROP権限が必要。DDL。ログ等も書いていないため、
速度は一般的に早い。


②auto incrementについて
DELETEは以前の値を保持している。
TRUNCATEは初期化する。
ちなみに、phpMyAdminの「空にする」はTRUNCATE。

f:id:ftomo100:20160905165050j:plain

【Javascript】年齢計算

年月日を受け取り、年齢を計算する。
年月日をyyyymmdd形式にし、現在日時もyyyymmddにする。
それぞれを整数と考えると、差分/10000が年齢になる。
引数の年月日はselectなので正しい値しか入らないと仮定。

※注意点
現在日付のgetMonth()は、戻り値が(0~11)という謎仕様なので注意。

function getAge(year, month, day){
	var today=new Date();
	today = today.getFullYear()*10000 + (today.getMonth()+1)*100 + today.getDate();
	var birthday = parseInt(year, 10) * 10000 + parseInt(month, 10)*100 + parseInt(day, 10);
	return(Math.floor((today - birthday)/10000) );
}

【Javascript】全角→半角

英数文字を入力するときに半角を強制する。
リテラシーの無い方は半角と全角の区別がつかないので、こちらで変換する。
formのフォーカスが外れた時に強制的に変換する。
といっても、文字コード正規表現でむりやり変更しているだけ。

※全角英数を半角で表示するchromeアドオンを使っている場合、正常に表示されません

$(function(){
    $("#email, #telno, #zipcode").change(function(){
        var str = $(this).val();
        str = str.replace( /[A-Za-z0-9-!”#$%&’()=<>,.?_[]{}@^~¥]/g, function(s) {
            return String.fromCharCode(s.charCodeAt(0) - 65248);
        });
        $(this).val(str);
    }).change();
});

【Javascript】指定された年月によって日を変更する

selectで年月日を選択させる。
月によっては月末の日が異なるため、実在しない日は選択できないようにする。

年、月、日のhtmlは以下のとおり。それぞれにidを設定しておく。
日は月を選択しないと意味がないため、選択できないようにしておく。
何も選択しないで送信するフールプルーフ対策として、デフォルト値は
「選択なし」にしておく。
年と月のonchangeイベントで日を変更するjavascriptを呼び出す。

生年月日<br>
<select id="year" name="year" onchange="changeday()>
<option value="" selected>選択してください</option>
<option value="2001">2001(平成13)</option>
<option value="2002">2002(平成14)</option>
</select>

<select id="month" name="month" onchange="changeday()">
<option value="" selected>選択</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>

<select id="day" name="day">
<option value="" selected>選択</option>
</select>

javascriptでは、formの年と月を見て、
日のselectの子要素(option)をすべて書き換える。
要素の指定はgetElementbyIdでも良いけどjQueryで。

function changeday(){
    var year    = $('#year').val();
    var month   = $('#month').val();
    var day     = $('#day').val();
    var lastday = new Array('', 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    var option = '<option value="">選択</option>';
//うるう年対策
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
        lastday[2] = 29;
    }
    for (var i = 1; i <= lastday[month]; i++) {
        if (i == day){
            option += '<option value="' + i + '" selected="selected">' + i + '</option>\n';
        }else{
            option += '<option value="' + i + '">' + i + '</option>\n';
        }
    }
    $('#day').html(option);
}