tanaka's Programming Memo

プログラミングについてのメモ。

SlimPHP:Slim マイクロフレームワークで REST アプリケーションを作成する(1)GET

次へ


IBM developerWorks Slim マイクロフレームワークで REST アプリケーションを作成するを参考に、SlimPHPのスケルトンアプリから作成します。コードはSlimPHP3用に書き換えています。

ステップ 1: アプリケーションのディレクトリー構造を作成する / ステップ 2: Slim フレームワークをダウンロードする

上記はまとめて行います。

  • アプリケーションのディレクトリーを作成したい場所にcdで移動
  • 以下でスケルトンアプリを作成して、そのフォルダーに入る
composer create-project slim/slim-skeleton <アプリディレクトリ名>
cd <アプリディレクトリ名>

ステップ 3: サンプル・データベースを初期化する

  • ローカルのmysqlを起動して、mysqlにログイン
mysql.server start
mysql -u <データベースの作成権限のあるユーザー> -p
  • 要求されたらパスワードを入力する
  • 以下で、作業用のデータベースを作成
CREATE DATABASE IF NOT EXISTS ibm_slim CHARACTER SET=utf8;
  • 以下のコマンドでテーブルを作成する
CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` text NOT NULL,
  `url` text NOT NULL,
  `date` date NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
  • テーブルにアクセス属性を設定する場合は、以下のように実行
GRANT SELECT,DELETE,INSERT,UPDATE ON TABLE ibm_slim.* TO <操作するユーザー>;
  • 作業用のデータを登録
INSERT INTO `articles` (`id`, `title`, `url`, `date`) VALUES 
(1, 'Search and integrate Google+ activity streams with PHP applications', 
'http://www.ibm.com/developerworks/xml/library/x-googleplusphp/index.html', '2012-07-10');

INSERT INTO `articles` (`id`, `title`, `url`, `date`) VALUES 
(2, 'Getting Started with Zend Server CE', 
'http://devzone.zend.com/1389/getting-started-with-zend-server-ce/', '2009-03-02');

RedBeanPHPを設定

RedBeanPHPは、ORM(Object-relational mapping、O/RM、オブジェクト関係マッピング)ライブラリーです。ORMは、データベースをオブジェクト指向言語のオブジェクト操作と同様に操作するものです。

  • RedBeanPHP4 :: Welcomeから、recommendedされているバージョンをダウンロード
  • ダウンロードしたファイルを解凍
  • プロジェクトフォルダー内のpublicフォルダーにRedBeanというフォルダーを新規に作成
  • 解凍したRedBeanPHPx_x_xフォルダーの中身を、RedBeanフォルダーに移動

ステップ 4: 仮想ホストを定義する

このステップは、PHPの組み込みサーバーを起動することで置き換えます。

  • 作成したプロジェクト用フォルダーから以下を実行
php -S 0.0.0.0:8080 -t public public/index.php

GET リクエストの処理

GETリクエストには、リソースのリストの取得(GET /articles)と、特定のリソースの取得(/articles/123)の2つの機能を持たせます。そのためのルーターコールバックを作成していきます。

articles一覧の取得

public/index.phpを開いて、以下のように修正します。

<?php
if (PHP_SAPI == 'cli-server') {
    // To help the built-in PHP dev server, check if the request was actually for
    // something which should probably be served as a static file
    $file = __DIR__ . $_SERVER['REQUEST_URI'];
    if (is_file($file)) {
        return false;
    }
}

require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/RedBean/rb.php';          // ←この行を追加

session_start();

// Instantiate the app
$settings = require __DIR__ . '/../src/settings.php';
$app = new \Slim\App($settings);

// Setup Database connection
R::setup('mysql:host=localhost;dbname=ibm_slim', 'ユーザー名', 'パスワード');  // ←この行を追加
R::freeze(true);                                                               // ←この行を追加

// Set up dependencies
require __DIR__ . '/../src/dependencies.php';

// Register middleware
require __DIR__ . '/../src/middleware.php';

// Register routes
require __DIR__ . '/../src/routes.php';

// Run app
$app->run();

次に、 src/routes.php を開いて、以下のように書き換えます。

<?php
// Routes

// articlesへのルートを設定する
$app->get('/articles', function($request, $response, $args) {
    // 一覧を取得
    $articles = R::find('articles');

    // JSONでエンコードした結果を返す
    echo json_encode(R::exportAll($articles));

    // JSONを返すためのヘッダを設定
    return $response->withHeader('Content-Type', 'application/json');
});

以上が完了したら、 http://0.0.0.0:8080/articles にWebブラウザーでアクセスします。GETメソッドで、articlesが指定されているルートを設定したので、先に作成したデータベースからarticlesテーブルの中身を取得して、それをR::exportAll()メソッドによってPHP配列に変換し、さらにJSON文字列にエンコードして表示します。

参考元のコードは古いので、そのままではヘッダーの設定に失敗します。SlimPHP3用に書き換えたものを掲載しました。

特定のarticlesを取得する

特定のarticlesを取得する場合は、'/articles/123'のようにアクセスします。付記する数値に応じてデータを取り出すためには、プログラムで数値を読み取る仕組みが必要です。ルートパターンに'/articles/{id}'を設定すると、これを実現できます。

取り出すには、 $route = $request->getAttribute('route'); などとして取得したルート属性のオブジェクトから、 $route->getArgument('id') で取り出すことができます。

routes.phpを以下のように修正してください。

<?php
// Routes

class ResourceNotFoundException extends Exception {}

// articlesへのルートを設定する
$app->get('/articles', function($request, $response, $args) {
    // 一覧を取得
    $articles = R::find('articles');

    // JSONでエンコードした結果を返す
    echo json_encode(R::exportAll($articles));

    // JSONを返すためのヘッダを設定
    return $response->withHeader('Content-Type', 'application/json');
});

// /articles/:idのためのGETリクエストを設定する
$app->get('/articles/{id}', function($request, $response, $args) {
    try {
        // データベースから1つデータを取り出す
        $route = $request->getAttribute('route');
        $article = R::findOne('articles', 'id=?', array($route->getArgument('id')));

        if ($article) {
            // データが見つかればJSONで返す
            echo json_encode(R::exportAll($article));
            return $response->withHeader('Content-Type', 'application/json');
        }
        // 違う場合は例外を投げる
        throw new ResourceNotFoundException();
    } catch (ResourceNotFoundException $e) {
        // return 404 サーバーエラー
        return $response->withStatus(404);
    } catch (Exception $e) {
        return $response
            ->withStatus(400)
            ->withHeader('X-Status-Reason', $e->getMessage());
    }
});

できたら、 http://0.0.0.0:8080/articles/1http://0.0.0.0:8080/articles/2 にアクセスしてください。それぞれのデータのみが取得できます。

また、 http://0.0.0.0:8080/articles/3http://0.0.0.0:8080/articles/a などの存在しないIDを指定すると画面には何も表示されず、Firebugなどでステータスを見ると404が返ってきます。

Slimはルートパターンに正規表現を指定できます。数値のみ受け付けるようにするには以下のようにします。

$app->get('/articles/{id:[0-9]+}', function($request, $response, $args) {

http://0.0.0.0:8080/articles/a にアクセスすると、先ほどと違って「Page Not Found」が表示されるようになります。

エラーを独自仕様にする方法は System Error Handler - Slim Framework を参照してください。

GETの処理は以上です。POSTに続きます。


次へ