MySQL
注意
最新のmysql-nativeでは、コード中に利用されているexecPreparedResult
メソッドはdeprecatedになっています。
書き換えるのが面倒だったので、とりあえずそのままにしています。最新のものを利用したい場合は公式リファレンスをごらんください。
mysql.d
import std.variant;
import mysql.db
// 返却値を保持するための構造体
struct Table {
ulong id;
string name;
}
void execQuery() {
string query = "SELECT * FROM tables WHERE id = ? AND name = ?";
// MysqlDBインスタンスの生成
MysqlDB db = new MysqlDB("hostname", "user", "passwd",
"dbname", 3306);
// prepared statementを利用しqueryを送る準備
auto con = db.lockConnection();
scope(exit) con.close();
auto cmd = Command(con, query);
cmd.prepare();
// バインド用にVariant型の配列を用意
// id = 10, name = "admin"
Variant[] v;
v.length = 2;
v[0] = cast(ulong)10;
v[1] = "admin";
// パラメータをバインド
cmd.bindParameters(v);
// SELECTなど戻り値が必要な場合
auto result = cmd.execPreparedResult();
// 0番目の結果を構造体へ格納
Table t;
result[0].toStruct(t);
// INSERT, UPDATEなど戻り値が不要な場合
// ulong ra;
// cmd.execPrepared(ra);
}
複数ソースファイルで管理
1バイナリで複数ポートListenしたいときにオススメの構成。
以下は1ソースファイルに1ポートのListenを設定し、Webサービスを開始するコード例。
source/app.d
import vibe.d;
void main()
{
runApplication();
}
source/frontend.d
import vibe.d;
void index(HTTPServerRequest req, HTTPServerResponse res)
{
res.render!("index.dt", req);
}
shared static this()
{
auto router = new URLRouter;
router.get("/", &index);
auto settings = new HTTPServerSettings;
settings.port = 80;
listenHTTP(settings, router);
}
source/backend.d
import vibe.d;
void index(HTTPServerRequest req, HTTPServerResponse res)
{
res.render!("index.dt", req);
}
shared static this()
{
auto router = new URLRouter;
router.get("/", &index);
auto settings = new HTTPServerSettings;
settings.port = 8080;
listenHTTP(settings, router);
}
外部HTTP接続
requestHTTPを利用する。
インターフェースは数種類あるが、個人的には処理の流れがわかりやすいresponseを受け取るやつが好き。
res.dropBody
をスコープ抜けた時に呼び出す理由は、requestHTTP
メソッドが通信中の場合にスコープを抜けてしまうとリクエスト先へ繋ぎっぱなしになり、エラーが出てしまうのを防ぐため。
GET
auto res = requestHTTP("http://qiita.com/", (scope req) {});
scope(exit) res.dropBody();
if (res.statusCode == 200) {
logInfo(res.bodyReader.readAllUTF8());
}
POST
自力でPOSTのbodyを構築する。
auto res = requestHTTP("http://qiita.com/", (scope req) {
req.method = HTTPMethod.POST;
req.writeBody(cast(ubyte[])("hoge=fuga&foo=bar"),
"application/x-www-form-urlencoded");
});
scope(exit) res.dropBody();
if (res.statusCode == 200) {
logInfo(res.bodyReader.readAllUTF8());
}
セッション管理
セッションの開始
void postLogin(HTTPServerRequest req, HTTPServerResponse res)
{
Session session;
if (req.session) {
// すでにセッションがある場合はrequestからセッションを取得
session = req.session;
} else {
// ない場合はセッションスタート
session = res.startSession();
}
// idをセット
session.set!ulong("id", 100);
}
セッション値の取得
void getIndex(HTTPServerRequest req, HTTPServerResponse res)
{
if (req.session) {
// セッションが存在する場合はidを取得
ulong id = req.session.get!ulong("id");
logInfo("ログイン済み %d", id);
} else {
logInfo("未ログイン");
}
}
セッションの終了
void postLogout(HTTPServerRequest req, HTTPServerResponse res)
{
if (req.session) {
res.terminateSession();
}
}
テンプレートエンジン(Diet)
D言語のjadeみたいなもの。基本的な文法は省略。
変数展開
#{ 変数 }
を利用する。
例: idという変数をテンプレートに渡したとすると以下のようになる。
h2 ID = #{ id }
HTMLエスケープした状態で変数表示
!{ 変数 }
を利用する。
例: messageという変数をテンプレートに渡したとすると以下のようになる。
div.tweet
p !{ message }