太平洋時間でメリークリスマス、Frog Advent Calendar 2016 24日目 chan_gamiです。今年はドラゴンのケーキを買いました。
同Advent Calendarの23日目、Hidetoさんが【アメコミ】マーベルAPIでカッコいいサイトを作ろう!という記事を書いてくださいました。
Hidetoさんの記事内容と合わせてAPIアプリケーションごと自分で作ってしまえば自由度がもっともっと広がるので、この機会に挑戦してみましょう。
目次
- CodeIgniterとバンクーバーの関係
- CodeIgniterプロジェクトの作成
- Composerってなに?
- Composerを使う場合
- Composerを使わない場合
- アプリケーションの動きを把握する
- モデルを実装する
- REST APIを実装する
- 動かしてみる
- 今後の実装について
CodeIgniterとバンクーバーの関係
CodeIgniterはPHPのWeb Frameworkの一つで、オープンソースプロジェクトとして公開されています。
CodeIgniter Web Framework
bcit-ci/CodeIgniter: Open Source PHP Framework (originally from EllisLab)
さて、LICENSEにご注目ください。
Copyright (c) 2014 – 2016, British Columbia Institute of Technology
引用: CodeIgniter/license.txt at master · bcit-ci/CodeIgniter
このBCITというのはカナダのブリティッシュコロンビア州立大学で、バンクーバーの隣りにあるバーナビーに本部をおいています。もちろんバンクーバー・ダウンタウンにもキャンパスがあります。今回Advent Calendarに参加してくださった方の中にもこの学校を卒業されている方が何名かいらっしゃいます。
2ヶ月ほど前からPHPに触れはじめて最近CodeIgniterを触りだしたので、ライセンスを読んだときはびっくりしました。
CodeIgniterプロジェクトの作成
CodeIgniterは上に記述した通りPHPのFrameworkなので、PHPは必須です。XAMPPとかMAMPの環境があれば大丈夫ですが、Composerを使用する場合はPHPバージョン5.3.2以上でないと動作しませんのでご注意ください。
Composerってなに?
Composer
ComposerはPHPのパッケージ管理システムです。他の言語でいうと、Node.jsのnpm、Rubyのgem、Pythonのpipです。便利なので利用して楽しましょう。
macOSユーザであれば、HomebrewからComposerをインストールすることが可能です。
brew install composer composer-completion
昔Homebrewを入れていて、その後にOSアップデートを当てた場合はおそらくエラーが出るかと思います。
ので、エラー解決の手助けになるリンクを置いておきます。mac でbrew がおかしくなった(brew updateができない)のを解決 – Qiita
Composerを使う場合
kenjis/codeigniter-composer-installer: Installs the offical CodeIgniter 3 with secure folder structure via Composer
こちらの非常に便利なインストーラーが利用できます。
api-application
の部分はプロジェクト名に置き換えてください。
composer create-project kenjis/codeigniter-composer-installer api-application
cd api-application
composer install
そして先のリポジトリのREADME.mdにあるようにapplication/config/config.php
を以下のように書き換えます。
$config['composer_autoload'] = FALSE;
↓
$config['composer_autoload'] = realpath(APPPATH . '../vendor/autoload.php');
$config['index_page'] = 'index.php';
↓
$config['index_page'] = '';
正常にインストールされているか確認してみましょう。
bin/server.sh
open http://localhost:8000
無事表示されればComposerを利用した開発の準備は終わりです。
Composerを使わない場合
公式からダウンロードします。
解凍してファイルを展開したあとフォルダ名をお好きなプロジェクト名に変更し、コマンドラインで解凍したフォルダに移動して
php -S 127.0.0.1:8000
エラーなく動き出したようであればブラウザでhttp://localhost:8000
にアクセスします。
無事表示されれば開発の準備は終わりです。
アプリケーションの動きを把握する
まずはアプリケーションの動きを把握しましょう。
先ほどhttp://localhost:8000にアクセスした際に表示されていたファイルはapplication/views/welcome_message.php
です。
次に、これを表示するようにしているのがapplication/controllers/Welcome.php
の以下の部分です。
public function index()
{
$this->load->view('welcome_message');
}
そして、このWelcome.php
を呼び出しているのはapplication/config/routes.php
の以下の部分です。
$route['default_controller'] = 'welcome';
つまり、アプリケーションの動作を新たに作りたいときはまずこのroutes.php
で定義する必要があるということだけ覚えておいてください。
モデルを実装する
今回モデル・ビュー・コントローラーなどの説明はしませんが、ご存じない方はモデルというものはデータベースのすぐ近くの存在でデータを司る者、それ以外の処理は行わない者、というくらいの認識で大丈夫です。
ではアプリケーションの実装を行っていきます。
application/models
配下にFrog_advent_calendar.php
を作成して、以下を記述します。
<?php
//Frog_advent_calendar.php
class Frog_advent_calendar_model extends CI_Model
{
private $data = [
["id" => 1, "date" => "2016-12-01", "author" => "chan_gami", "url" => "http://www.changami.com/2016/12/frog-advent-calendar-greeting/"],
["id" => 2, "date" => "2016-12-02", "author" => "Senna", "url" => "https://frogagent.com/job-placement/how-to-pick-a-good-school/"],
["id" => 3, "date" => "2016-12-03", "author" => "chan_gami", "url" => "http://www.changami.com/2016/12/board-game-for-raincouver/"],
["id" => 4, "date" => "2016-12-04", "author" => "ellekasai", "url" => "https://note.mu/ellekasai/n/n1d6a6c77b8be"],
["id" => 5, "date" => "2016-12-05", "author" => "Kay", "url" => "http://blog.kaffeekantate.xyz/enjoy-cafe-and-coffee-in-vancouver/"],
["id" => 6, "date" => "2016-12-06", "author" => "ellekasai", "url" => "https://note.mu/ellekasai/n/nc361452b245e"],
["id" => 7, "date" => "2016-12-07", "author" => "chan_gami", "url" => ""],
["id" => 8, "date" => "2016-12-08", "author" => "Toru", "url" => "http://loudandproud.me/nikkei/"],
["id" => 9, "date" => "2016-12-09", "author" => "Julia", "url" => "http://lilyfolio.com/lilypress/2016/12/loss-in-vancouver/"],
["id" => 10, "date" => "2016-12-10", "author" => "Leo", "url" => "http://unique-experience.xyz/?p=2722"],
["id" => 11, "date" => "2016-12-11", "author" => "ellekasai", "url" => "https://note.mu/ellekasai/n/n62e262e44499"],
["id" => 12, "date" => "2016-12-12", "author" => "MAIMAI", "url" => "https://note.mu/mm72862444/n/n1a6805bc2ef7"],
["id" => 13, "date" => "2016-12-13", "author" => "Hideto", "url" => "http://webdev-bodymake.com/bodymake-in-vancouver/"],
["id" => 14, "date" => "2016-12-14", "author" => "Mao", "url" => "https://frogagent.com/schoolinfo/tips_for_a_better_school_life_in_vancouver/"],
["id" => 15, "date" => "2016-12-15", "author" => "sjntn", "url" => "http://blog.sjntn.com/Entry/119/"],
["id" => 16, "date" => "2016-12-16", "author" => "ginpei", "url" => "http://ginpen.com/2016/12/16/slack-transportation-bot/"],
["id" => 17, "date" => "2016-12-17", "author" => "chan_gami", "url" => "http://www.changami.com/2016/12/introduction-of-apache-cordova/"],
["id" => 18, "date" => "2016-12-18", "author" => "Saaya", "url" => "http://catchdesign.tumblr.com/post/154625302290/%E3%83%90%E3%83%B3%E3%82%AF%E3%83%BC%E3%83%90%E3%83%BC%E3%81%A7%E3%83%95%E3%82%A1%E3%82%B9%E3%83%88%E3%83%97%E3%83%AD%E3%83%88%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0"],
["id" => 19, "date" => "2016-12-19", "author" => "Leo", "url" => "http://unique-experience.xyz/?p=2702"],
["id" => 20, "date" => "2016-12-20", "author" => "Hitomi", "url" => "https://frogagent.com/vancouver/20161220van_design/"],
["id" => 21, "date" => "2016-12-21", "author" => "suige", "url" => "https://suige.github.io/2016/12/wordpress-timezone/"],
["id" => 22, "date" => "2016-12-22", "author" => "Kay", "url" => "https://blog.kaffeekantate.xyz/design-agency-workflow-vancouver/"],
["id" => 23, "date" => "2016-12-23", "author" => "Hideto", "url" => "http://webdev-bodymake.com/marvel-api/"],
["id" => 24, "date" => "2016-12-24", "author" => "chan_gami", "url" => ""],
["id" => 25, "date" => "2016-12-25", "author" => "Senna", "url" => ""],
];
public function find_all()
{
return $this->data;
}
public function find_by_id($id)
{
return $id > 0 && $id <= count($this->data) ? $this->data[$id - 1] : new stdClass();
}
}
今回はデータベースとの接続を想定していないのでdataの値を直書きしています。本来は$this->db->...
といった形でデータベースの値を取得して返すような動きが期待されます。
これでモデルの実装は終わりです。
REST APIを実装する
codeigniter-restserverという便利なものがあるのでそれを利用します。
ダウンロードしたファイルの中から、これらのファイルをプロジェクトフォルダに入れてください。
- application/config/rest.php
- application/language/english/rest_controller_lang.php
- application/libraries/Format.php
- application/libraries/REST_Controller.php
そして今回のAPIを実装するapplication/controllers/Rest_frog_advent_calendar.php
を作成して、以下を記述します。
<?php
//Rest_frog_advent_calendar.php
require APPPATH . '/libraries/REST_Controller.php';
class Rest_frog_advent_calendar extends REST_Controller
{
function __construct()
{
parent::__construct();
}
public function list_get()
{
$this->load->model('Frog_advent_calendar_model');
$data = $this->Frog_advent_calendar_model->find_all();
if (!empty($data)) {
$this->set_response([
'status' => REST_Controller::HTTP_OK,
'message' => 'success',
'data' => $data,
], REST_Controller::HTTP_OK);
} else {
$this->set_response([
'status' => REST_Controller::HTTP_INTERNAL_SERVER_ERROR,
'message' => 'error',
'data' => new stdClass(),
], REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function find_by_get($id)
{
$this->load->model('Frog_advent_calendar_model');
$data = $this->Frog_advent_calendar_model->find_by_id($id);
if (!empty($data)) {
$this->set_response([
'status' => REST_Controller::HTTP_OK,
'message' => 'success',
'data' => $data,
], REST_Controller::HTTP_OK);
} else {
$this->set_response([
'status' => REST_Controller::HTTP_INTERNAL_SERVER_ERROR,
'message' => 'error',
'data' => new stdClass(),
], REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
}
}
}
そして最後に、application/config/routes.php
に以下を追記します。
//routes.php
$route['v1/frog_advent_calendar']['GET'] = 'rest_frog_advent_calendar/list';
$route['v1/frog_advent_calendar/(:num)']['GET'] = 'rest_frog_advent_calendar/find_by/$1';
これでアプリケーションの一連の動きの実装が終わりました。
動かしてみる
実装を終えたら動作を確認してみます。
CodeIgniterプロジェクトの作成で行った動作確認と同じ方法でアプリケーションを起動してください。そして、
curl -i -X GET http://localhost:8000/v1/frog_advent_calendar
またはブラウザからhttp://localhost:8000/v1/frog_advent_calendar
へアクセスします。
{"status":200,"message":"success","data":[{"id":1,"date":"2016-12-01","author":"chan_gami","url":"http:\/\/www.changami.com\/2016\/12\/frog-advent-calendar-greeting\/"},{"id":2,"date":"2016-12-02","author":"Senna","url":"https:\/\/frogagent.com\/job-placement\/how-to-pick-a-good-school\/"},{"id":3,"date":"2016-12-03","author":"chan_gami","url":"http:\/\/www.changami.com\/2016\/12\/board-game-for-raincouver\/"},{"id":4,"date":"2016-12-04","author":"ellekasai","url":"https:\/\/note.mu\/ellekasai\/n\/n1d6a6c77b8be"},{"id":5,"date":"2016-12-05","author":"Kay","url":"http:\/\/blog.kaffeekantate.xyz\/enjoy-cafe-and-coffee-in-vancouver\/"},{"id":6,"date":"2016-12-06","author":"ellekasai","url":"https:\/\/note.mu\/ellekasai\/n\/nc361452b245e"},{"id":7,"date":"2016-12-07","author":"chan_gami","url":""},{"id":8,"date":"2016-12-08","author":"Toru","url":"http:\/\/loudandproud.me\/nikkei\/"},{"id":9,"date":"2016-12-09","author":"Julia","url":"http:\/\/lilyfolio.com\/lilypress\/2016\/12\/loss-in-vancouver\/"},{"id":10,"date":"2016-12-10","author":"Leo","url":"http:\/\/unique-experience.xyz\/?p=2722"},{"id":11,"date":"2016-12-11","author":"ellekasai","url":"https:\/\/note.mu\/ellekasai\/n\/n62e262e44499"},{"id":12,"date":"2016-12-12","author":"MAIMAI","url":"https:\/\/note.mu\/mm72862444\/n\/n1a6805bc2ef7"},{"id":13,"date":"2016-12-13","author":"Hideto","url":"http:\/\/webdev-bodymake.com\/bodymake-in-vancouver\/"},{"id":14,"date":"2016-12-14","author":"Mao","url":"https:\/\/frogagent.com\/schoolinfo\/tips_for_a_better_school_life_in_vancouver\/"},{"id":15,"date":"2016-12-15","author":"sjntn","url":"http:\/\/blog.sjntn.com\/Entry\/119\/"},{"id":16,"date":"2016-12-16","author":"ginpei","url":"http:\/\/ginpen.com\/2016\/12\/16\/slack-transportation-bot\/"},{"id":17,"date":"2016-12-17","author":"chan_gami","url":"http:\/\/www.changami.com\/2016\/12\/introduction-of-apache-cordova\/"},{"id":18,"date":"2016-12-18","author":"Saaya","url":"http:\/\/catchdesign.tumblr.com\/post\/154625302290\/%E3%83%90%E3%83%B3%E3%82%AF%E3%83%BC%E3%83%90%E3%83%BC%E3%81%A7%E3%83%95%E3%82%A1%E3%82%B9%E3%83%88%E3%83%97%E3%83%AD%E3%83%88%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0"},{"id":19,"date":"2016-12-19","author":"Leo","url":"http:\/\/unique-experience.xyz\/?p=2702"},{"id":20,"date":"2016-12-20","author":"Hitomi","url":"https:\/\/frogagent.com\/vancouver\/20161220van_design\/"},{"id":21,"date":"2016-12-21","author":"suige","url":"https:\/\/suige.github.io\/2016\/12\/wordpress-timezone\/"},{"id":22,"date":"2016-12-22","author":"Kay","url":"https:\/\/blog.kaffeekantate.xyz\/design-agency-workflow-vancouver\/"},{"id":23,"date":"2016-12-23","author":"Hideto","url":"http:\/\/webdev-bodymake.com\/marvel-api\/"},{"id":24,"date":"2016-12-24","author":"chan_gami","url":""},{"id":25,"date":"2016-12-25","author":"Senna","url":""}]}
このような結果が得られていれば成功です。また、routes.phpで指定しているようにidごとに取得も可能です。
curl -i -X GET http://localhost:8000/v1/frog_advent_calendar/1
またはブラウザからhttp://localhost:8000/v1/frog_advent_calendar/1
へアクセスします。
{"status":200,"message":"success","data":{"id":1,"date":"2016-12-01","author":"chan_gami","url":"http:\/\/www.changami.com\/2016\/12\/frog-advent-calendar-greeting\/"}}
今後の実装について
今回はAPIアプリケーションの最低限の動きだけ実装しました。これをきっかけに面白さを感じた方は今後も開発を続けていただきたいと思います。
作りたいものはできたけど、今後の実装はどういうところから始めればいいのかわからない。そんな方はまずはこの辺りを考えてみていただければと思います。
- データベースの利用
- APIのURL
- APIのメッセージ設計
- データの管理
- ログイン・ログアウトの管理
- モデルの抽象化(ベースモデルを作る、など)
では皆様、良いお年をお迎えください!
ありがとうございました。