今回は、APIとDBの接続処理を記します。
前回の章では、会員登録のコントローラ、サービスの紐付けとモデルにデータを入れるところまで行いました。
処理の流れ
必要なファイル
今回作成するファイルのみ記しています。
※下記のみだと正常に実行されないのでシリーズの過去記事をご覧ください
sns_training ├── api │ ├── api.php │ └── connection.php └── app └── config └── .env
apiに記述するsqlについては、過去の章で作成した会員登録のIDを使用します。
api.php
<?php namespace Api\Connection; use Api\Connection\Connection; class api{ public function A00001($param = null){ $sql = null; $sql .= <<< EOM SELECT COUNT(*) AS COUNT FROM USERS USR WHERE USR.USER_ID = :USER_ID; EOM; $connection = new Connection(); return $connection->con($sql, $param); } } ?>
api.phpは、sql文をまとめて記述できるファイルです。
以前、サービスで作成した「REQUEST_API_NAME」のメソッドを記述していきます。
今回は、A00001という番号のAPIを作成します。
public function A00001($param = null){...}
このApi.phpでは、前述した通りSQL文をズラーっと記述していきます。
メソッド名は番号にしています。$paramは、サービスクラスでInputModelに入れたモデルです。
$sql .= <<< EOM ... EOM;
sqlを一行で書く場合、ヒアドキュメントを用いた記述は必要ありません。
しかし、複雑な処理である場合、横に長くなってしまいます。
そのため、EOMで囲み複数行を文字列として$sqlに代入しています。
SELECT COUNT(*) AS COUNT FROM USERS USR WHERE USR.USER_ID = :USER_ID;
今回はリクエスト値のUSER_IDと一致するレコード数を返すAPIです。
※後の章で改修を行います。
DBにはUSERSというテーブル、
カラムには、USER_IDが存在する程で記述しています。
また、リクエスト値にプリペアドステートメントを利用することでSQLインジェクションを防ぐことが可能のため採用しています。
$connection = new Connection(); return $connection->con($sql, $param);
後述しますconnectionクラスをインスタンス化します。
このインスタンスのconメソッド対してsqlとリクエスト値を投げます。
戻り値としてsqlの結果が返却されるため、APIメソッドの戻り値としています。
この戻り値がserviceの子クラスoutputメソッドの引数に格納されるわけです。
connection.php
connection.phpは、かなり参考にならないかと思います。。。
なるべくDBの処理を共通化したいあまりにパターンを網羅している途中の段階です。
ただ、このシリーズについての内部処理は重要ではないのでコピペで可です。
<?php namespace Api\Connection; use App\Config\config; use \PDO; use \PDOException; class Connection{ private static $dbh; public static function pdo(){ $dsn = 'mysql:dbname='.Config::getEnv('DB_NAME').';host='.Config::getEnv('DB_HOST'); $user = Config::getEnv('DB_USER'); $password = Config::getEnv('DB_PASSWORD'); self::$dbh = new PDO($dsn, $user, $password); } public function con($sql,$param = null){ self::pdo(); try { $sth = self::$dbh->prepare("$sql"); if($param != null){ foreach($param as $key => $val){ if((preg_match("/_WILDCARD$/",$key) == 1) && $val != null){ $k = explode("_",$key)[0]; $sth->bindValue(':'.$k,$val, PDO::PARAM_STR); }else if(($key == 'ROW_NUM' || $key == 'FROM_NUM' ) && $val != null){ $sth->bindValue( ':'.$key, (int)$val, PDO::PARAM_INT ); } else if($val != null){ $sth->bindValue(':'.$key,$val); }else{ $sth->bindValue(':'.$key, null, PDO::PARAM_NULL); } } } $flag = $sth->execute(); if(trim(mb_strstr( $sql, ' ', true),"\n") != 'SELECT'){ $result = $flag; }else{ $result = $sth->fetchAll(PDO::FETCH_ASSOC); } return $result; } catch(PDOException $e){ exit; } } } ?>
$dsn = 'mysql:dbname='.Config::getEnv('DB_NAME').';host='.Config::getEnv('DB_HOST'); $user = Config::getEnv('DB_USER'); $password = Config::getEnv('DB_PASSWORD'); self::$dbh = new PDO($dsn, $user, $password);
ここでは、DBの接続情報を.envファイルより取得しています。
それらを引数としてPDO(DB接続クラス)をインスタンス化します。
if((preg_match("/_WILDCARD$/",$key) == 1) && $val != null){...}
オレオレすぎて申し訳ないですが、
SQL文のLIKE(あいまい検索)するために必要な記述です。
このLIKE句で使用する検索文字列は「???_WILDCARD」というプロパティに格納してあげます。
if(($key == 'ROW_NUM' || $key == 'FROM_NUM' ) && $val != null){...}
LIKE句検索と同様、ROW_NUM及びFROM_NUMのプロパティに値を格納した場合、値の扱いが変わります。
これらは、LIMIT句、OFFSET句で使用します。
例えば、検索結果を複数ページで表示させる時に使用します。
if(trim(mb_strstr( $sql, ' ', true),"\n") != 'SELECT'){...}
ここでは、SQLがSELECT文か、それ以外かを判定しています。
DMLの基本文法のみサポートしています。
SELECTの場合はレコードを返します。DBに対して変更を加えると実行結果を返します。
戻り値が異なるため分岐をしています。
.env
SUB_DIRECTORY=/sns_training DB_NAME=sns_training DB_HOST=localhost DB_USER=root DB_PASSWORD=root
ここでは、接続情報を追記しました。
今回はホストの[localhost]に[sns_training]というdbを作成して、ユーザ[root]でリクエストをしています。
おわりに
今回はAPIとDB接続処理の作成をいたしました。
次回は、会員登録クラスを使用して実際にAPIで問い合わせをしたいと思います。
転職ならリクナビNEXT
リクナビNEXTとはリクルートが運営する転職サイトです。
効率的に転職活動が行える管理やメール、レジュメ機能の他、
ミスマッチを減らすための診断サービス。
また、選択肢が広がるスカウト登録が可能です。
いずれ転職活動をしたい。本職が合っているか今一度考えたい。という方はぜひ登録してみてください。診断サービスのグッドポイント診断は、登録後ご利用いただけますのでぜひやってみてくださいね。
以上、ありがとうございました。
コメント