LoginSignup
4
2

More than 5 years have passed since last update.

vibe.dチートシート

Last updated at Posted at 2017-06-18

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 }
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2