Symfoware

Symfowareについての考察blog

CodeIgniter3 JSONを返すAPIサーバーとして使用する

PHPフレームワークのCodeIgniter
http://www.codeigniter.com/

JSON形式な文字列を返すAPIサーバーとして使用してみます。


簡単なサンプル



ドキュメントを見ると、outputクラスを用いたサンプルがあります。
https://www.codeigniter.com/userguide3/libraries/output.html

簡単なコントローラークラスを作成して試してみます。

・application/controllers/Api.php


  1. <?php
  2. class Api extends CI_Controller {
  3.     public function index() {
  4.         $this->output
  5.             ->set_content_type('application/json')
  6.             ->set_output(json_encode(array('foo' => 'bar')));
  7.     }
  8. }




これをPythonから呼び出して使ってみます。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import urllib2
  4. url = 'http://192.168.1.103:8080/api'
  5. response = urllib2.urlopen(url)
  6. # 戻り値を解析
  7. body = response.read()
  8. response.close()
  9. data = json.loads(body)
  10. print(data['foo'])




うまく動いてくれたようです。


$ python api_test.py
bar







郵便番号検索サンプル



mariadbに郵便番号データを登録して検索してみます。
テーブルレイアウトは以下のとおり。


create table zip (
zip_code char(7) not null primary key,
address varchar(200)
);




データはこちらから全国版を取得しました。
http://www.post.japanpost.jp/zipcode/dl/kogaki-zip.html

重複しないよう、適当に加工して登録します。


  1. # -*- coding:utf-8 *-
  2. import codecs
  3. import MySQLdb
  4. def execute(line, cur, zips):
  5.     
  6.     data = [s.strip('"') for s in line.split(u',')]
  7.     zip_code = data[2]
  8.     if zip_code in zips:
  9.         return
  10.     address = data[6] + data[7] + data[8]
  11.     cur.execute(u"insert into zip(zip_code, address) values (%s, %s)", [zip_code, address])
  12.     
  13.     zips.add(zip_code)
  14. con = MySQLdb.connect(
  15.     host='localhost',
  16.     db='sample',
  17.     user='root',
  18.     passwd='P@ssw0rd',
  19.     charset='utf8')
  20. cur = con.cursor()
  21. zips = set()
  22. with codecs.open('KEN_ALL.CSV', 'r', 'ms932') as f:
  23.     for line in f:
  24.         execute(line.strip(), cur, zips)
  25. con.commit()
  26. cur.close()
  27. con.close()





これで下準備完了です。
CodeIgniterのconfig/database.phpを微調整。


  1. $active_group = 'default';
  2. $query_builder = TRUE;
  3. $db['default'] = array(
  4.     'dsn'    => '',
  5.     'hostname' => 'localhost',
  6.     'username' => 'root',
  7.     'password' => 'P@ssw0rd',
  8.     'database' => 'sample',
  9.     'dbdriver' => 'mysqli',
  10.     'dbprefix' => '',
  11.     'pconnect' => FALSE,
  12.     'db_debug' => (ENVIRONMENT !== 'production'),
  13.     'cache_on' => FALSE,
  14.     'cachedir' => '',
  15.     'char_set' => 'utf8',
  16.     'dbcollat' => 'utf8_general_ci',
  17.     'swap_pre' => '',
  18.     'encrypt' => FALSE,
  19.     'compress' => FALSE,
  20.     'stricton' => FALSE,
  21.     'failover' => array(),
  22.     'save_queries' => TRUE
  23. );





検索したい郵便番号を引数として受け取り、検索結果を返すControllerはこうなりました。


  1. <?php
  2. class Api extends CI_Controller {
  3.     // 郵便番号検索
  4.     public function zip($zip_code) {
  5.         
  6.         $this->load->database();
  7.         
  8.         $this->db->select('address');
  9.         $this->db->from('zip');
  10.         $this->db->where('zip_code', $zip_code);
  11.         
  12.         $rows = $this->db->get()->result_array();
  13.         
  14.         // 検索結果をそのまま返す
  15.         $this->output
  16.             ->set_content_type('application/json')
  17.             ->set_output(json_encode($rows));
  18.         
  19.     }
  20. }




Pythonから使ってみます。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import urllib2
  4. url = 'http://192.168.1.103:8080/api/zip/0690364'
  5. response = urllib2.urlopen(url)
  6. # 戻り値を解析
  7. body = response.read()
  8. response.close()
  9. data = json.loads(body)
  10. for row in data:
  11.     print(row['address'])




動いてくれました。


$ python api_test.py
北海道岩見沢市上幌向南三条







リクエストボディーを引数として使用する



リクエストボディにJSONな文字列を設定。
その値をAPIの引数として使用するよう構成します。

こんな場合は、raw_input_streamが使えます。
https://www.codeigniter.com/userguide3/libraries/input.html


  1. <?php
  2. class Api extends CI_Controller {
  3.     // 郵便番号検索
  4.     public function zip() {
  5.         
  6.         // クライアントからの値を復元
  7.         $query = json_decode($this->input->raw_input_stream);
  8.         
  9.         $this->load->database();
  10.         $this->db->select('address');
  11.         $this->db->from('zip');
  12.         $this->db->where('zip_code', $query->zip_code);
  13.         
  14.         $rows = $this->db->get()->result_array();
  15.         
  16.         // 検索結果をそのまま返す
  17.         $this->output
  18.             ->set_content_type('application/json')
  19.             ->set_output(json_encode($rows));
  20.         
  21.     }
  22. }




テスト用のサンプルはこのようになりました。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import urllib2
  4. url = 'http://192.168.1.103:8080/api/zip'
  5. values = {'zip_code':'0690364'}
  6. send_data = json.dumps(values)
  7. req = urllib2.Request(url, send_data)
  8. response = urllib2.urlopen(req)
  9. # 戻り値を解析
  10. body = response.read()
  11. response.close()
  12. data = json.loads(body)
  13. print data[0]['address']




ちゃんと検索結果が取得できています。


$ python api_test.py
北海道岩見沢市上幌向南三条







画像データを送信



リクエストヘッダーにファイル名。
リクエストボディーに画像データを入れて送信。
サーバー側で復元してみます。


まずサーバー側。


  1. <?php
  2. class Api extends CI_Controller {
  3.     // 画像アップロード
  4.     public function upload() {
  5.         
  6.         // クライアントからの値を復元
  7.         // ファイル名
  8.         $file_name = $this->input->get_request_header('File-name');
  9.         // 画像データ
  10.         $image = $this->input->raw_input_stream;
  11.         
  12.         // 指定されたファイル名で保存
  13.         file_put_contents(FCPATH.$file_name, $image);
  14.                 
  15.         // 保存結果を返信
  16.         $this->output
  17.             ->set_content_type('application/json')
  18.             ->set_output(json_encode(['result' => 'ok']));
  19.         
  20.     }
  21. }




ファイル送信のサンプルはこのようになりました。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import urllib2
  4. url = 'http://192.168.1.103:8080/api/upload'
  5. headers = { 'File-name' : 'sample.jpg' }
  6. with open('cc2.jpg', 'rb') as f:
  7.     image = f.read()
  8. req = urllib2.Request(url, image, headers)
  9. response = urllib2.urlopen(req)
  10. # 戻り値を解析
  11. body = response.read()
  12. response.close()
  13. data = json.loads(body)
  14. print data




ちゃんとサーバー側に画像ファイルが復元できました。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/05/16(月) 23:37:42|
  2. PHP
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<lftp 隠しファイル(ドットから始まるファイル)もmirrorする | ホーム | PHP file_get_contentsでAPIサーバーにGET,POST,画像アップロード>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1886-2488d9c1
この記事にトラックバックする(FC2ブログユーザー)