LoginSignup
5
8

More than 5 years have passed since last update.

Perfectを使って、Swiftでサーバーサイドプログラミング3 - MySQLに接続

Last updated at Posted at 2016-05-21

目次

Perfectを使って、Swiftでサーバーサイドプログラミング1 - 導入
Perfectを使って、Swiftでサーバーサイドプログラミング2 - Hello PerfectをWebページに表示
Perfectを使って、Swiftでサーバーサイドプログラミング3 - MySQLに接続←イマココ

はじめに

前回、サーバー立ち上げて、サイトにHello Perfectを表示できたので、今回はローカルのMySQLに接続して、DBとTableの作成、データの読み込みと書き込みの部分をやりたいと思います。

MySQLプロジェクトを追加

メニューからFile > Add Filesを選択。

スクリーンショット 2016-05-20 2.40.03.png

Perfectを使って、Swiftでサーバーサイドプログラミング1 - 導入でダウンロードしたPerfectLibの中にMySQLのプロジェクトが入っているので、選択して追加します。

スクリーンショット 2016-05-20 2.40.45.png

HelloPerfectプロジェクトにMySQLを追加します。

スクリーンショット 2016-05-20 2.41.47.png

MySQL設定

次にHost名やDB名などを設定します。
HelloPerfectHandler.swiftのPerfectServerModuleInit()メソッドの上あたりにでも以下をコピーしてhogeの値を書き換えてください。

private let DB_HOST = "127.0.0.1"  //localhost
private let DB_USER = "hoge"       // MySQLユーザー名
private let DB_PASSWORD = "hoge"   // MySQLパスワード
private let DB_NAME = "hoge"       // 新しく作成するDB名
private let DB_TABLE_NAME = "hoge" // 新しく作成するTable名

DBとTableを作成する

Perfectを使って、Swiftでサーバーサイドプログラミング2 - Hello PerfectをWebページに表示で追加したHelloPerfectHandler.swift内のIndexHandlerクラスのhandleRequestメソッド内に以下のコードを記述。

let mysql = MySQL()
let connected = mysql.connect(DB_HOST, user: DB_USER, password: DB_PASSWORD)
guard connected else {
    print(mysql.errorMessage())
    return  
}

defer {
    mysql.close()
}

//DB,Tableがなければ作成する
var schemaExists = mysql.selectDatabase(DB_NAME)
if !schemaExists {
    schemaExists = mysql.query("CREATE SCHEMA \(DB_NAME) DEFAULT CHARACTER SET utf8mb4;")
}

let tableSuccess = mysql.query("CREATE TABLE IF NOT EXISTS \(DB_TABLE_NAME) (id INT(11) AUTO_INCREMENT, Content varchar(255), PRIMARY KEY (id))")

guard schemaExists && tableSuccess else {
    print(mysql.errorMessage())
    return
}

http://0.0.0.0:8181/にアクセスした際にDBとTableが作成されてなければ、作成するようにしています。

DBにデータを追加する

次に、http://0.0.0.0:8181/post/投稿したい文字列にアクセスした際に「投稿したい文字列」をDBにInsertするために、PerfectServerModuleInitメソッド内にRoutingを追加します。

Routing.Routes["GET", "/post/{content}"] = { (_:WebResponse) in return PostHandler() }

urlの{content}の部分に入る文字列は、次に作成するPostHandlerメソッド内で

request.urlVariables["content"]

とすると取得できます。

では、http://0.0.0.0:8181/post/投稿したい文字列にアクセスした際のHandlerを作成しましょう。
HelloPerfectHandler.swift内に以下クラスを追加。

class PostHandler: RequestHandler {

    func handleRequest(request: WebRequest, response: WebResponse) {
        let reqData = request.urlVariables["content"]!

        // MySQLに接続
        let mysql = MySQL()
        let connected = mysql.connect(DB_HOST, user: DB_USER, password: DB_PASSWORD)
        guard connected else {
            print(mysql.errorMessage())
            response.setStatus(500, message: "Server Error")
            response.requestCompletedCallback()
            return
        }

        // DBを選択
        mysql.selectDatabase(DB_NAME)

        defer {
            mysql.close()
        }

        // Insert query発行(DB_TABLE_NAMEのContentカラムにreqDataを追加)
        let querySuccess = mysql.query("INSERT INTO \(DB_TABLE_NAME) (Content) VALUES ('\(reqData)')")
        guard querySuccess else {
            print(mysql.errorMessage())
            response.setStatus(500, message: "Server Error")
            response.requestCompletedCallback()
            return
        }

        response.appendBodyString("Sccess!! Insert \(reqData)")
        response.setStatus(201, message: "Created")
        response.requestCompletedCallback()
    }

}

これでDBに追加できます。処理が成功したら以下のように表示されるはずです。

スクリーンショット 2016-05-21 12.15.50.png

DBからデータを読み込む

次に先ほど格納したデータを読み込んでみます。
http://0.0.0.0:8181/getにアクセスするために、PerfectServerModuleInitメソッド内にRoutingを追加します。

Routing.Routes["GET", "/get"] = { (_:WebResponse) in return GetHandler() }

次にHandlerを追加します。

class GetHandler: RequestHandler {

    func handleRequest(request: WebRequest, response: WebResponse) {

        // MySQL接続
        let mysql = MySQL()
        let connected = mysql.connect(DB_HOST, user: DB_USER, password: DB_PASSWORD)
        guard connected else {
            print(mysql.errorMessage())
            response.setStatus(500, message: "Server Error")
            response.requestCompletedCallback()
            return
        }

        // DB選択
        mysql.selectDatabase(DB_NAME)
        defer {
            mysql.close()
        }

        // SELECT query発行(DB_TABLE_NAMEのContentカラムから10件取得)
        let querySuccess = mysql.query("SELECT Content FROM \(DB_TABLE_NAME) LIMIT 10")
        guard querySuccess else {
            print(mysql.errorMessage())
            response.setStatus(500, message: "Server Error")
            response.requestCompletedCallback()
            return
        }

        // resultsのカウントが0件ならリターン
        let results = mysql.storeResults()!
        if results.numRows() == 0 {
            print("no rows found")
            response.setStatus(500, message: "Server Error")
            response.requestCompletedCallback()
            return
        }

        // 値を配列にする
        var contents = [String]()
        results.forEachRow { row in
            contents.append(row[0])
        }

        //JSONを文字列にしてAppendBodyStringに追加
        do {
            let data = try NSJSONSerialization.dataWithJSONObject(["content": contents], options: .PrettyPrinted)
            let string = NSString(data: data, encoding: NSUTF8StringEncoding)

            response.appendBodyString(string as! String)
            response.addHeader("Content-Type", value: "application/json")
            response.setStatus(200, message: "OK")
        } catch {
            response.setStatus(500, message: "Server Error")
        }

        response.requestCompletedCallback()

    }

}

処理がうまくいったらこんな感じで取得できます。

スクリーンショット 2016-05-21 12.16.28.png

おわり

MySQLへのデータ取得、追加は思ったよりもシンプルにできた。
次はクライアント側の操作で取得、追加をしてみたい。

Sample

Perfectを使って、Swiftでサーバーサイドプログラミングシリーズの
SampleCode

5
8
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
5
8