質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • PHP

    25088questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • API

    1893questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

PHPのAPIを作る勉強中ですが

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 2,299

lol

score 72

phpでapiを作る勉強中です。

http://localhost/test/apiTest.php?id=1234
http://localhost/test/apiTest.php?flg=1
というURLで、
apiTest.phpにidを渡して、処理する部分はできました。

idから名前を取得する部分と

仮にflgというパラメータが来るとして、
このflgで別のロジックを処理したい場合は、
ファイルを分ける方法しかございませんか??

今私のレベルでは、ファイル分けて処理するしか思い浮かばずです。

メソッドを分けて呼べる方法とかはありませんか??

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • HiroshiWatanabe

    2016/03/25 16:09

    (理解できていないのが私だけなら申し訳ないんですけども)
    ファイルを分けるという意味がよくわからないんですが
    apiTest.php?flg=1ができないからapiTest2.php?flg=1
    としなくてはならない、という事…でも無いですよね?
    質問の意図がよく理解できません…
    「こういう処理を期待してこう記述したけどこんなエラーが出てしまう」
    みたいな情報があればしたいことと困ってる内容がわかって答えやすいかも…

    キャンセル

  • lol

    2016/03/25 16:14

    質問が悪かったです。すみません。

    まず、ファイルを分けるという意味は
    パラメータが異なる場合の事を伝えるつもりでした。

    1.http://localhost/test/apiTest.php?id=1234
    パラメータがIDが来る場合

    2.http://localhost/test/apiTest.php?flg=1
    パラメータがflgが来る場合

    この場合に同じファイルでは、別々の処理ができないような気がしました。

    また、

    3.http://localhost/test/apiTest.php?id=1234&name=suzuki
    これもあったとしたら、区別をつけないといけないかなと思って質問しました。

    パラメータは5個とか来ると処理できないよなぁと一人で悩んでました。

    キャンセル

回答 4

checkベストアンサー

+5

「1ファイルに1処理」というスタイルは,HTML+CSSしか書けなかった素人がWebプログラミングに手をだすための敷居こそ低いものの,機能が増えてくると設計が破綻してきます.「register.php」「postMessage.php」「showMessage.php」「editMessage.php」「showUser.php」「editUser.php」みたいなファイルが大量に並べられることでしょう.

これを防ぐためにPHPを用いた中規模以上の開発ではMVCフレームワークを用いた開発を行うのが一般的です.いきなりこれが敷居が高く感じられるのであれば,V以外を極限まで小さく抑えるマイクロフレームワークを使っても構いません.(後々MVCのほうが良かった,と思うことは多いですが,入門用としてマイクロフレームワークは悪い選択肢ではありません)

「1ファイルに1処理」問題を解決するためにあるのがルーティングです.これはMVCフレームワークでもマイクロフレームワークでも使われます.ルーティングはURLを見てどういう処理を実行するのかを制御するものです.「*.php」の拡張子を消すことが出来たり,必ずしもパラメータを「?a=b&c=d」の形式で渡す必要がないのもメリットです.例えばこんな感じ.

  • 「/entry/list」にGETでアクセスが来たら,投稿一覧を取得する
  • 「/entry/post」にPOSTでアクセスが来たら,新規投稿を追加する
  • 「/user/profile/ユーザ名」にGETでアクセスが来たら,該当ユーザのプロフィールを取得する

この「〜を取得する」の処理の部分ですが,これを1ファイルにまとめる必要はありません.堂々と分離させましょう.この際,処理をクラスメソッドや関数として定義しておくと,全体の見通しがよくなります.グローバルスコープに処理をズラズラ書き並べるのは可能な限り避けましょう

上記の「コールバックには何が使えるか?」のところでいろいろなパターンが紹介されています.Slimの公式ドキュメントではクロージャを使ったものがほとんどですが,これを乱立させてしまうとまた1ファイルが膨大になってくるのでおすすめできません.「クラス名:メソッド名」が一番いいかと思います.

今回はAPIを作りたい,ということでしたよね?おそらくレスポンスをJSONで返すだけだと思うので,ビューに特別な手間をかける必要はないです.以下のように $response オブジェクトから withJSON() メソッドを生やすだけです.

$app->get('/user/profile/{name}', 'UserController:showProfile');

class UserController
{
    public function showProfile($request, $response, $args)
    {
        $params = $request->getQueryParams();
        return $response->withJSON([
            'name' => $args['name'],
            'description' => "{$args['name']}のプロフィール",
            'flag_enabled' => !empty($params['flag']),
        ]);
    }
}

注意: Slim3のwithJsonはステータスコードをデフォルトで200に書き換える

上記のルーティングを行っている場合, http://example.com/user/profile/CertaiN?flag=1 でアクセスすると以下のようなJSONが返ってくるはずです. (見やすくしています)

{
    "name": "CertaiN",
    "description": "CertaiNのプロフィール",
    "flag_enabled": true
}

なお実際にはデータベースに繋いでユーザ情報を取得してくることになると思いますが,全てのメソッドの中にPDOを扱う処理を毎回記述するのは非常に冗長なので,こういう処理は別のクラスにまとめておきましょう.そして,Slim\Appのインスタンスを作る際に渡すコンテナにあらかじめ突っ込んでおき,後から参照するようにしましょう.例えばこんな感じ.

(サービスロケータというアンチパターンを使っているんですが,まぁSlim3がそういう設計思想なのでしょうがないですね)

$container = new Slim\Container;
$container['db'] = function () { return new DB; };

$app = new Slim\App($container);
$app->get('/user/profile/{name}', 'UserController:showProfile');

class UserController
{
    private $db;
    public function __construct(ContainerInterface $container)
    {
        $this->db = $container['db'];
    }
    public function showProfile($request, $response, $args)
    {
        $params = $request->getQueryParams();
        return $response->withJSON([
            'name' => $args['name'],
            'description' => $this->db->getDescriptionByName($args['name']),
        ]);
    }
}

class DB
{
    private $dbh;
    public function __construct()
    {
        $this->dbh = new PDO(...);
    }
    public function getDescriptionByName($name)
    {
        $stmt= $this->dbh->prepare(...);
        ...
        return ...;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/28 09:42

    このような回答がほしかったです。ありがとうございます。

    MVCフレームワークを使うとできるとのことですね?
    また、DBの接続を毎回するのも悩んでました。

    まずは、クラス化をして分離してみます。

    ありがとうございます。

    キャンセル

0

ん?

if (@$_GET['flg'] == 1) {
  // 1の処理
}
elseif ($_GET['flg'] == 2) {
  // 2の処理
}
else {
  // その他
}


みたいな?

追記

パラメータに値を付けると、HTTPプロトコルではGETでデータを受け取ることになります。
フォームなどにデータを入力してデータを受け取る場合、POSTでデータを受け取ります。

しかし、実はリクエストヘッダーの中身を見ると興味深いです。

flg=1&id=1234&name=suzuki

のように渡しています。
そして、PHPはそのデータを直接利用することができます。

$id = $_POST['id'];

とするだけで、idを変数に入れて利用可能です。

これはURLパラメータでも同じです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/25 23:22

    「リクエストを受け取った段階で問答無用でサニタイズする」というのは誤った設計です.「エスケープすべき瞬間にその用途に応じたエスケープを行う」のが正しいです.詳しくは「サニタイズ言うなキャンペーン」でググってください.このキャンペーン啓発者曰く「サニタイズは死語として扱うべきだ」だそうですが,そのとおりだと思います.

    キャンセル

  • 2016/03/25 23:30

    >> $dbh->query('SET NAMES sjis');

    これは絶対にやめてください.この書き方をするとプレースホルダを使っていてもSQLインジェクションを受ける可能性があります.詳しくは以下の徳丸さんのブログを参照してください.

    http://www.tokumaru.org/d/20100701.html

    設計方針としては,まずそもそもShift_JISなんて古臭い文字コードを使わないこと.今のWebでは全ての文字コードをUTF-8に統一するのがもはや当たり前です.Shift_JISをPHPで使うとデメリットが沢山あります.例えば str_replace や explode といった関数はよく使うと思いますが,Shift_JISエンコードされた文字列に対しては動作保証されていません.また,文字コードの設定にはDSNのcharset指定を使うようにしてください.

    $dsn = 'mysql:dbname=test;host=localhost;charset=utf8';

    >> $sql = 'select id, name from name_table where id == ?';

    これ構文エラーになると思います.SQLの比較は「==」じゃなくて「=」です.

    また,SQLの構文エラーなどにもすぐ気づけるように,「new PDO」以外の部分でもPDOExceptionがスローされるように必ず以下の設定を最初に行ってください.これを行わないと全体をtry~catchで括る意味がありません.

    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    キャンセル

  • 2016/03/26 12:51

    Re: CertaiNさん
    老婆心で余計な一言を入れてしまいました。言われてみればそうですよね。
    わたしもサニタイズなんてしてませんし(笑)
    初心者のように見えるからって、いい加減なことを書かないように気を付けます。

    キャンセル

0

クラス化してみたら幸せになれるかも?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/25 16:50

    クラス化まではまだなので、さっぱりですが

    http://www.objective-php.net/mvc/dispatcher
    ここを見る限りでは、クラス化しないといけないようですね。

    キャンセル

  • 2016/03/25 16:57

    ちなみに、


    $dsn = 'mysql:dbname=test;host=localhost';
    $user = 'testuser';
    $password = 'testuser';
    $id = $_GET['id'];
    try{
    $dbh = new PDO($dsn, $user, $password);
    $dbh->query('SET NAMES sjis');

    $sql = 'select id, name from name_table where id == ?';
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array($id));

    while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
    print($result['id']);
    print($result['name'].'<br>');
    }

    }catch (PDOException $e){
    print('Error:'.$e->getMessage());
    die();
    }


    これをクラス化するのは簡単にできるものでしょうか??

    キャンセル

  • 2016/03/25 17:26

    >ここを見る限りでは、クラス化しないといけないようですね。

    クラスにしなくても要求を満たす事はできると思います。
    答えに至る道(実現手段)は1つではありませんので。

    >これをクラス化するのは簡単にできるものでしょうか??

    はい。クラスにする事自体はそんなにムズカシイ事ではありません。

    キャンセル

0

なんだかよくわからないけど、

今私のレベルでは、ファイル分けて処理するしか思い浮かばずです。メソッドを分けて呼べる方法とかはありませんか??

パラメータでメソッドとかを指定すると同じファイルでも分けて処理ができるのかが知りたいことでした。

これですと、idとflgが同時に来るパターンはまた分岐するということでしょうか??

クラス化まではまだなので、さっぱりですが

という良い子のみんなの意見を纏めると、

apiTest.php

if(isset($_GET["id")){
    doIdMethod($_GET["id"]);
}

if(isset($_GET["flg"])){
    doFlgMethod($_GET["flg"]);
}

function doIdMethod($id){
    // $idでの処理
}

function doFlgMethod($flg){
    // $flgでの処理
}

こんなんでましたけど?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/28 09:42

    これは違います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    25088questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • API

    1893questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。