laravel x モバイルアプリ
発表内容
• アプリ開発者という生き物について

• アプリ開発のDB事情

• モバイルアプリ用Web API 実装 tips
pochikawa

starfruits_j

Azione Co., Ltd.
Oshikawa
• 元Webデザイナ

• iOSアプリ開発

• たまにWebも触る

• PHP7は未経験

• SQLが嫌い
• 元Webデザイナ

• iOSアプリ開発

• たまにWebも触る

• PHP7は未経験

• SQLが嫌い
which.photos
ヤラナイカ
スプラトゥーンのフレンドの
オンライン状態をチェックし
たり通知してくれるアプリ
他 > littlegleam.com
発表内容
• アプリ開発者という生き物について
• アプリ開発のDB事情

• モバイルアプリ用Web API 実装 tips
アプリ開発者とはどんな生物? (所感です)
• ローカルでは主にSQLite

• アップデートの壁があるので、仕様変更はあまりしない(したく
ない)

• サーバサイドのように負荷分散等考えなくて良いので、あまり
チューニングとかしない(したくない)

• Viewはアプリ側にあるので、たまにしかサーバサイドは触らな
い

• Swiftばっかり書いてると、Swift以外のコードは隠 したくなる
つまりたまにしか

SQL書かない
忘れます!
SQL組み立てめんどい!
$sql = 'SELECT * FROM `laravel` WHERE ';
if ($user_id) {
$sql .= ' `user_id` = ' . $user_id;
} else {
$sql .= ' 1 = 1';
}
連想配列で組み立てるクエリビルダ
$arr = [];
if ($user_id) {
$arr['user_id'] = $user_id;
}
$db->select('table', $fields, $arr);
$arrってなんだっけ?
• resultがarrayだったり?

• 久々に触ると仕様を確認したりコードを呼んだ
りしなければならない

• SQL読んだ方が分かりやすい

• SQLが複雑になると、もはや読めもしない
発表内容
• アプリ開発者という生き物について

• アプリ開発のDB事情
• モバイルアプリ用Web API 実装 tips
Realm
realm.io
RealmのModel
// Define your models like regular Swift classes
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
}
// Use them like regular Swift objects
let mydog = Dog()
mydog.name = "Rex"
print("name of dog: (mydog.name)")
// Persist your data easily
let realm = try! Realm()
try! realm.write {
realm.add(mydog)
}
https://realm.io/docs/swift/latest/
RealmのSelect
let tanDogs = realm.objects(Dog).filter("color = 'tan'")
let tanDogsWithBNames = tanDogs.filter("name BEGINSWITH ‘B'")
※メソッドチェインでクエリを組み立てられる
https://realm.io/docs/swift/latest/#queries
よく使うクエリをclassメソッドで実装すると便利
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
dynamic var color = "white"
class func tanDogs() -> Results<Dog> {
let realm = try! Realm()
return realm.objects(Dog).filter("color =
'tan'")
}
}
Dog.tanDogs().sorted("age", ascending: false)
https://realm.io/docs/swift/latest/#queries
モデルを書くことで仕様が決まり

モデルを見れば仕様が理解できる

コードが出来上がる👏
PHPでもメソッドチェインでクエリ
書けないものか?
そう、laravelならね
発表内容
• アプリ開発者という生き物について

• アプリ開発のDB事情

• モバイルアプリ用Web API 実装 tips
可視性の高い設計
• サーバ側とアプリ側でモデルを統一化したい

• Realmと酷似しているのでGood! 

• レコードを連想配列にしてJSON出力

• ModelのtoJson();でOK!レスポンスをJSONに
するのも簡単。

• アプリ側はRealmにマッピングして保存
users.password等、ユーザに渡せない情報
• Modelのhidden propertyで指定
アプリ側の実装
class User: Object {
dynamic var id = ""
dynamic var name = ""
}
https://realm.io/docs/swift/latest/#queries
laravel側の実装
/**
* @property string $id // ID
* @property string $name // 名前
* @property string $password // パスワード
*/
class User extends Model {
protected $hidden = ['password'];
}
https://realm.io/docs/swift/latest/#queries
deleted_at -> isDeleted
• カラムにないプロパティはget∼∼Attributeで追
加できる
アプリ側の実装
class User: Object {
dynamic var id = ""
dynamic var name = “"
dynamic var isDeleted = false
}
https://realm.io/docs/swift/latest/#queries
laravel側の実装
/**
* @property string $id // ID
* @property string $name // 名前
* @property string $deleted_at // 削除日時
*/
class User extends Model {
protected $hidden = [‘deleted_at’];
function getIsDeletedAttribute() {
return (boolean) ($this->deleted_at);
}
}
https://realm.io/docs/swift/latest/#queries
画像読み込みのストレスを減らす
• ローディング中に表示する
プレースホルダ用にサムネイ
ルをbase64したバイナリを
返す
laravel側の実装
/**
* @property string $id // ID
* @property string $name // 名前
*/
class User extends Model {
function getImageURLAttribute() {
return sprintf('%s/images/%d.jpg',
Config::get('app.url'), $this->user_id);
}
function getThumbnailAttribute() {
$bin = file_get_contents(
$this->thumbnail_file_path);
return base64encode($bin);
}
}
https://realm.io/docs/swift/latest/#queries
時差を考慮する
海外展開する場合等に困るので、
ISO8601で返すようにしてあげると安全
class User extends Model {
public function
getCreatedAtAttribute($date) {
return date('c', strtotime($date));
}
public function
getUpdatedAtAttribute($date) {
return date('c', strtotime($date));
}
}
https://realm.io/docs/swift/latest/#queries
RESTfulは注意
• リクエストの回数が増える

• フリースポット等で予期せぬ200が返ります

• statusをjsonに含めてチェックする等してあげた
方が無難
エラー発生時
App::error(function(Exception $exception, $code)
use($self) {
Log::error($exception);
$res = array(
'status' => 0,
'code' => $code,
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
);
if ($self->isDebug()) {
$res['sql_history'] = $self->sql_history;
$res['post'] = $_POST;
$res['get'] = $_GET;
}
return Response::json($res, $code);
});
https://realm.io/docs/swift/latest/#queries
AfterFilter
$this->afterFilter(function($route, $request,
$response) use($self) {
$data = $response->getOriginalContent();
if (!$data) {
$data = array();
}
if (is_array($data)) {
if (!isset($data['status'])) {
$data['status'] = 1;
}
if ($self->isDebug()) {
$data['sql_history'] = $self->sql_history;
$data['post'] = $_POST;
$data['get'] = $_GET;
}
$response->setContent($data);
}
});
https://realm.io/docs/swift/latest/#queries
レスポンスがタイムアウトするかも
• 通信状態が悪い場合、画像/動画のアップロード
でタイムアウトが発生するが、PHPはアップロー
ドが完了した時点でinsertしてしまう

• 極端に大きな通信はcommit用のAPIを用意して、
送信完了のレスポンスを受け取ってからcommit
する
ちょっとした変更でリクエストが複数回
• 通信量、速度のみでなく失敗のリスクも高まる

• JSON-RPC使う

• githubにあります (未確認)
laravelって素晴らしい!😉
• 優秀なQuery Builder

• 暗黙的でフレキシブルなORM

• SQLなんか書かなくて良い!

• 他FWに比べて並列分割のテーブルも扱いやすい

• API構築にも最適化されている
laravelって素晴らしい?😅
• CREATE TABLE必要

• Schema Builderもあるけど、やっぱり忘れる

• 複数テーブルをJOINし始めると辛い

• PHP7の新機能の活用に期待!
ご静聴ありがとう
ございました!

laravel x モバイルアプリ