目次
AngularJSの$httpサービスは、デフォルトの動作でPOSTやGETメソッドの送信データをJSON形式に変換してくれる。
これは、サーバサイドのスクリプトもNode.js等のJavaScriptで書かれている場合は便利な機能だが、PHPで受けるには不便である。
そこで、送信するデータを下記のコードで通常のx-www-form-urlencode形式に変換する。(要jQuery)
$httpProvider.defaults.headers.post['Content-Type'] ='application/x-www-form-urlencoded';
$httpProvider.defaults.transformRequest = function (data) {
if (data === undefined)
return data;
return $.param(data);
};
このコードは、app.jsのapp.config()の中に書くことで、起動時に自動的に設定される。
$httpProvider.defaults.transformRequest.push(
function(data) {
var requestStr;
if (data) {
data = JSON.parse(data);
for (var key in data) {
if (requestStr) {
requestStr += '&' + key + '=' + data[key];
} else {
requestStr = key + '=' + data[key];
}
}
}
return requestStr;
});<?php
/* 新規メンバーを登録する
* nm : 氏名
* ge : 性別
* ma : メールアドレス
* bt : 血液型
*/
try{
$pdo=new PDO("mysql:host=mysql514.db.sakura.ne.jp;".
"dbname=forcreate_XXXXXXXX;".
"charset=utf8",
"forcreate","XXXXXXXX");
$q="insert into member (name,gender,mail,bloodtype)".
" values (:name,:gender,:mail,:bloodtype);";
$s=$pdo->prepare($q);
$sa=array(":name"=>$_POST['nm'],
":gender"=>$_POST['ge'],
":mail"=>$_POST['ma'],
":bloodtype"=>$_POST['bt']);
$s->execute($sa);
$q="select * from member order by id desc limit 1;";
$s=$pdo->prepare($q);
$s->execute();
print json_encode($s->fetchAll());
}
catch(PDOException $e){
print json_encode(array("msg"=>$e->getMessage()));
}
?>
<?php
/* 指定したIDのメンバーを更新する
* id : ID
* nm : 氏名
* ge : 性別
* ma : メールアドレス
* bt : 血液型
*/
try{
$pdo=new PDO("mysql:host=mysql514.db.sakura.ne.jp;".
"dbname=forcreate_XXXXXXXX;".
"charset=utf8",
"forcreate","XXXXXXXX");
$q="update member set ".
"name=:name,".
"gender=:gender,".
"mail=:mail,".
"bloodtype=:bloodtype,".
"modified=now() where id=:id;";
$s=$pdo->prepare($q);
$sa=array(":id"=>$_POST['id'],
":name"=>$_POST['nm'],
":gender"=>$_POST['ge'],
":mail"=>$_POST['ma'],
":bloodtype"=>$_POST['bt']);
$s->execute($sa);
//print json_encode(array("result"=>$s->rowCount()));
$q="select * from member where id=:id;";
$s=$pdo->prepare($q);
$sa=array(":id"=>$_POST['id']);
$s->execute($sa);
print json_encode($s->fetchAll());
}
catch(PDOException $e){
print json_encode(array("msg"=>$e->getMessage()));
}
?>
<?php
/* 指定したIDのメンバーを削除する
* id : ID
*/
try{
$pdo=new PDO("mysql:host=mysql514.db.sakura.ne.jp;".
"dbname=forcreate_XXXXXXXX;".
"charset=utf8",
"forcreate","XXXXXXXX");
$q="delete from member where id=:id;";
$s=$pdo->prepare($q);
$sa=array(":id"=>$_POST['id']);
$s->execute($sa);
print json_encode(array("result"=>"ok"));
}
catch(PDOException $e){
print json_encode(array("msg"=>$e->getMessage()));
}
?>
(function () {
var app = angular.module("MemberManager", ['ngRoute']);
// ルーティング
app.config(function ($routeProvider,$httpProvider) {
$routeProvider
.when('/', {
templateUrl: 'list.html',
controller: 'ListController'
})
.when('/regist', {
templateUrl: 'regist.html',
controller: 'RegistController'
})
.when('/modify/:num', {
templateUrl: 'modify.html',
controller: 'ModifyController'
})
.otherwise({
redirectTo: '/'
});
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
$httpProvider.defaults.transformRequest = function (data) {
if (data === undefined)
return data;
return $.param(data);
};
});
// 初期化
app.run(function (MemberService) {
MemberService.load();
//MemberService.regist("john", "male", "john@aaaa.jp", "A");
//MemberService.regist("paul", "male", "paul@bbbb.uk", "B");
//MemberService.regist("marry", "female", "marry@cccc.jp", "O");
});
}());
(function () {
var app = angular.module("MemberManager");
// 会員クラス
// id : シリアル番号
// name : 氏名
// gender : 性別
// mail : メールアドレス
// bloodtype : 血液型
// modified : 修正日時
var Member = function (id, nm, ge, ma, bt, mo) {
this.id = id;
this.name = nm;
this.gender = ge;
this.mail = ma;
this.bloodtype = bt;
this.modified = mo;
};
// 会員サービス
app.factory("MemberService", function ($http) {
var ms = {} // サービスの実体
ms.s_max = 0; // 会員番号の最大値
ms.members = []; // 会員リスト
ms.Member = Member; // 会員コンストラクタ
// 新規会員の登録
ms.regist = function (nm, ge, ma, bt) {
$http({
method: 'post',
url: 'http://seminar-senior.jeez.jp/fuchida/MemberManager/php/registMember.php',
data: {
nm: nm,
ge: ge,
ma: ma,
bt: bt
}
})
.success(function (data, status, headers, config) {
console.log(data);
var d = data[0];
ms.members.push(new ms.Member(
d.id,
d.name,
d.gender,
d.mail,
d.bloodtype,
new Date(d.modified)));
})
.error(function (data, status, headers, config) {
alert("Error:" + data.msg);
});
};
// 会員情報の修正
// num : ms.membersリストの中の番号
// mem : 修正後の会員の情報
ms.modify = function (num, mem) {
$http({
method: 'post',
url: 'http://seminar-senior.jeez.jp/fuchida/MemberManager/php/modifyMember.php',
data: {
id: mem.id,
nm: mem.name,
ge: mem.gender,
ma: mem.mail,
bt: mem.bloodtype
}
})
.success(function (data, status, headers, config) {
console.log(data);
var d = data[0];
var m = ms.members[num];
m.name = d.name;
m.gender = d.gender;
m.mail = d.mail;
m.bloodtype = d.bloodtype;
m.modified = new Date(d.modified);
})
.error(function (data, status, headers, config) {
alert("Error:" + data.msg);
});
}
// 会員情報の削除
ms.delete = function (num) {
var mem=ms.members[num];
$http({
method: 'post',
url: 'http://seminar-senior.jeez.jp/fuchida/MemberManager/php/deleteMember.php',
data: {
id: mem.id
}
})
.success(function (data, status, headers, config) {
console.log(data);
ms.members.splice(num, 1);
})
.error(function (data, status, headers, config) {
alert("Error:" + data.msg);
});
};
// サーバーからデータをロードする
ms.load = function () {
$http({
method: 'post',
url: 'http://seminar-senior.jeez.jp/fuchida/MemberManager/php/getMember.php'
})
.success(function (data, status, headers, config) {
console.log(data);
for (var i in data) {
ms.members.push(new ms.Member(data[i].id,
data[i].name,
data[i].gender,
data[i].mail,
data[i].bloodtype,
new Date(data[i].modified)));
}
})
.error(function (data, status, headers, config) {
alert("MemberServce: load error");
});
};
return ms;
});
}());
性別と血液型でフィルタリングできるようにした。
<p>
<button class="btn btn-default" ng-click="changeUrl('regist')">
新規登録
</button>
</p>
<form class="form-inline">
性別:
<select class="form-control" ng-model="gender_filter">
<option value='b'>両方</option>
<option value='m'>男</option>
<option value='f'>女</option>
<option value=''>なし</option>
</select>
血液型:
<select class="form-control" ng-model="bloodtype_filter">
<option value='all'>すべて</option>
<option value='A'>A型</option>
<option value='B'>B型</option>
<option value='AB'>AB型</option>
<option value='O'>O型</option>
</select>
</form>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>氏名</th>
<th>性別</th>
<th>メール</th>
<th>血液型</th>
<th>更新日</th>
</tr>
</thead>
<tr ng-repeat="m in members
|genderSelect:gender_filter
|bloodtypeSelect:bloodtype_filter">
<td>{{m.id}}</td>
<td><a href="#/modify/{{$index}}">{{m.name}}</a></td>
<td>{{m.gender|gender}}</td>
<td>{{m.mail}}</td>
<td>{{m.bloodtype}}</td>
<td>{{m.modified | date:'yyyy年MM月dd日 HH時mm分ss秒'}}</td>
</tr>
</table>
(function () {
var app = angular.module("MemberManager");
// 性別フィルタ
// 'male'なら'男'、'female'なら'女'を返す
app.filter("gender", function () {
return function (value) {
if (value == 'male') return '男';
if (value == 'female') return '女';
return '?';
};
});
// 性別選別フィルタ
// 指定した性別だけを通す
// m : 男性
// f : 女性
// b : 両方
// それ以外 : 何も通さない
app.filter('genderSelect', function () {
return function (values, flag) {
if (!angular.isArray(values)) return values;
if (flag == 'b') return values;
var newValues = [];
angular.forEach(values, function (v) {
if ((flag == 'm' && v.gender == 'male') ||
(flag == 'f' && v.gender == 'female'))
newValues.push(v);
});
return newValues;
}
});
// 血液型選別フィルタ
// 指定した性別だけを通す
// all : すべて
// A : A型
// B : B型
// AB: AB型
// O : O型
// それ以外 : 何も通さない
app.filter('bloodtypeSelect', function () {
return function (values, flag) {
if (!angular.isArray(values)) return values;
if (flag == 'all') return values;
var newValues = [];
angular.forEach(values, function (v) {
if (flag==v.bloodtype)
newValues.push(v);
});
return newValues;
}
});
// 性別転換
app.filter("toggleGender", function (MemberService) {
return function (values) {
if (!angular.isArray(values)) return values;
var newValues = [];
angular.forEach(values, function (v) {
var m = new MemberService.Member();
newValues.push(m);
m.id = v.id;
m.name = v.name;
m.gender = v.gender;
m.mail = v.mail;
m.bloodtype = v.bloodtype;
m.modified = v.modified;
if (m.gender == 'male')
m.gender = 'female';
else
m.gender = 'male';
});
return newValues;
};
});
}());
AngularJSではJasmineとKarmaが標準のテストフレームワークである。
まずは環境を構築しよう。
>npm -h
npm i jasmine jasmine-spec-reporter rewire
set PATH=node_modules/.bin;%PATH%
jasmine init
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
]
}npm i karma karma-jasmine karma-chrome-launcher
karma --version
npm i karma-cli
karma init
npm i karma-html2js-preprocessor npm i karma-spec-reporter karma-jasmine-html-reporter