phalconのチュートリアル学習記録

phalconのチュートリアル「REST」を解剖しながらみていきます。

macでXAMPPの上で動かしています。

[チュートリアル-Creating a Simple REST API編-](https://docs.phalconphp.com/en/3.2/tutorial-rest)


全てを解剖した上で、知っておくべき知識がやっとわかったので、
以下の内容をコンプリートしてから先に進みましょう笑笑

でも、まだよくわからないことだらけなので、わからない部分はごめんなさい、笑


[Phalconモデルまとめ(１)データ取得の基本](http://ryo511.blog.jp/archives/37644913.html)
[よく見るHTTPステータスコード一覧とその意味を理解する](https://www.seohacks.net/blog/seo-tech/1147/)
[HTTPについて](http://www.fellow-ship.com/tech/httperr.html)
[クラスPhalcon \ Http \ Response](https://docs.phalconphp.com/en/latest/api/Phalcon_Http_Response)　⇦レスポンスの部分
[PhalconのHTTPリクエスト](http://w.builwing.info/2015/04/16/phalcon%E3%81%AEhttp%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88/)


#ファイル構造
ファイル構造はこんな感じです。チュートリアルと一緒

```
my-rest-api/
    models/
        Robots.php
    index.php
    .htaccess
```


#.htaccessを作る
これは良く分からんので、コピペで。

```my-rest-api/.htaccess
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^((?s).*)$ index.php?_url=/$1 [QSA,L]
</IfModule>
```

#index.phpを作る

分解していきます。

```my-rest-api/index.php
<?php

use Phalcon\Loader;　//オートローダー使うよ！って宣言
use Phalcon\Mvc\Micro;　 //マイクロフレームワークのようなアプリケーションを作成する
use Phalcon\Di\FactoryDefault; //Phalconに付属しているコンポーネントのほとんどを登録するための宣言
use Phalcon\Db\Adapter\Pdo\Mysql as PdoMysql; //mysqlを使う

// Use Loader() to autoload our model
$loader = new Loader(); //オートローダーを作る

$loader->registerNamespaces( //名前空間を定義する
    [
        'Store\Toys' => __DIR__ . '/models/', //store\Toysを定義。「/models/」以下のディレクトリをロードする
    ]
);

$loader->register();　//上で定義したオートローダーを登録

$di = new FactoryDefault(); //DIを作る

// Set up the database service
$di->set(
    'db',  //データベースを定義
    function () {
        return new PdoMysql(
            [
                'host'     => 'localhost', //XAMPPならlocalhost
                'username' => 'root',  //使用するデータベースの名前を記す
                'password' => 'secret',  //使用するデータベースのパスワードを記す
                'dbname'   => 'robotics', //使用するデータベースの名前を記す
            ]
        );
    }
);

// Create and bind the DI to the application
$app = new Micro($di); //appというマイクロを作って??DIと結びつける

```

```my-rest-api/index.php
// Retrieves all robots
//データの検索の定義
$app->get(
    '/api/robots', //検索する際は「/api/robots」を使う！
    function () use ($app) {
        $phql = 'SELECT * FROM Store\Toys\Robots ORDER BY name'; //Store\Toys\Robotsから、全ての情報を取り出す(名前順に)という作業を変数phqlに代入

        $robots = $app->modelsManager->executeQuery($phql); //さっきのphqlを実行します。

        $data = []; //空のdataを作ります。

        foreach ($robots as $robot) { 
            $data[] = [
                'id'   => $robot->id, //全てのrobotのidとnameをdataに格納します
                'name' => $robot->name, 
            ];
        }

        echo json_encode($data); //dataをjson形式にして表示
    }
);
```
JSON形式ってなんやったっけ・・・

>要するに「JavaScriptの中でオブジェクトを記述する書式」のことです。

>JSONというのは「データを表現するための記法（≒文法）」です。

らしいです。笑



```my-rest-api/index.php
// Searches for robots with $name in their name
$app->get(
    '/api/robots/search/{name}', 「名前」で検索するのは「/api/robots/serch/{name}」
    function ($name) use ($app) {  
        $phql = 'SELECT * FROM Store\Toys\Robots WHERE name LIKE :name: ORDER BY name';　//Store\Toys\Robotsから、全ての情報を取り出す(名前順に)という作業を変数phqlに代入

        $robots = $app->modelsManager->executeQuery( //先ほどのphqlを実行
            $phql,
            [
                'name' => '%' . $name . '%'  //なんじゃこりゃ？？
            ]
        );

        $data = []; //空のデータを作成

        foreach ($robots as $robot) {
            $data[] = [
                'id'   => $robot->id,　　//さっき抽出したやつのidとnameをdataに格納します
                'name' => $robot->name,
            ];
        }

        echo json_encode($data);　//dataをjson形式にして表示
    }
);
```

```my-rest-api/index.php
use Phalcon\Http\Response;

// Retrieves robots based on primary key
$app->get(
    '/api/robots/{id:[0-9]+}',　//主キーで検索するのは「/api/robots/{id:[0-9]+}」を使う
    function ($id) use ($app) {
        $phql = 'SELECT * FROM Store\Toys\Robots WHERE id = :id:'; //「Store\Toys\Robots」から全てのIDを取り出す。

        $robot = $app->modelsManager->executeQuery( //先ほどのphqlを実行
            $phql,
            [
                'id' => $id, //idを表示？代入？
            ]
        )->getFirst(); //最初のレコードを取得

        // Create a response
        $response = new Response();　responseを作る

        if ($robot === false) { //もし変数robotがなかったら
            $response->setJsonContent( 
                [
                    'status' => 'NOT-FOUND' //ステータスを404 NOT FOUNDにする
                ]
            );
        } else {
            $response->setJsonContent( 
                [
                    'status' => 'FOUND', 
                    'data'   => [
                        'id'   => $robot->id, //dataにidとnameを格納
                        'name' => $robot->name
                    ]
                ]
            );
        }

        return $response; responseを返す
    }
);

```

```my-rest-api/index.php
// Adds a new robot 新しいのを入れる
$app->post(
    '/api/robots',　POSTには「/api/robots」を使う
    function () use ($app) {
        $robot = $app->request->getJsonRawBody(); //POSTのbodyを取得する機能を$robotに持たせます

        $phql = 'INSERT INTO Store\Toys\Robots (name, type, year) VALUES (:name:, :type:, :year:)'; //phqlは、「Store\Toys\Robots」に「name」「type」「year」を追加

        $status = $app->modelsManager->executeQuery(
            $phql,
            [
                'name' => $robot->name, //phqlを実行し、nameに名前をtypeにタイプを、yearに年を代入
                'type' => $robot->type,
                'year' => $robot->year,
            ]
        );

        // Create a response
        $response = new Response(); //responseを作る

        // Check if the insertion was successful
        if ($status->success() === true) {　　//successはフラッシュメッセージ
            // Change the HTTP status
            $response->setStatusCode(201, 'Created'); //ステータスのコード設定　404のNOTFOUNDみたいな感じで、201のCreatedを設定しているのだろう。

            $robot->id = $status->getModel()->id;　//$robotに先ほどのstatusの現在のモデル状況からidを参照します。

            $response->setJsonContent( //HTTPレスポンスの本文を作成する
                [
                    'status' => 'OK',  //statusがokの場合はリクエストがなんの問題もなく受理されます
                    'data'   => $robot, //dataに先ほどのrobotを代入
                ]
            );
        } else {
            // Change the HTTP status
            $response->setStatusCode(409, 'Conflict');　//ステータスコードを409のConflictに設定

            // Send errors to the client
            $errors = []; //エラーメッセージを入れるようの空箱を用意

            foreach ($status->getMessages() as $message) { //ステータスのエラーメッセージを取得
                $errors[] = $message->getMessage(); // errorsに格納
            }

            $response->setJsonContent(　//HTTPレスポンスの本文を作成する
                [
                    'status'   => 'ERROR',//ステータスをエラーにして
                    'messages' => $errors, //エラーメッセージをmessagesに代入
                ]
            );
        }

        return $response; responseを返す
    }
);
```



```my-rest-api/index.php
// Updates robots based on primary key アップデート
$app->put(
    '/api/robots/{id:[0-9]+}', 
    function ($id) use ($app) {
        $robot = $app->request->getJsonRawBody(); //POSTのbodyを取得する機能を$robotに持たせます

        $phql = 'UPDATE Store\Toys\Robots SET name = :name:, type = :type:, year = :year: WHERE id = :id:'; //それぞれアップデート

        $status = $app->modelsManager->executeQuery( //先ほどのphqlを実行
            $phql,
            [
                'id'   => $id, //それぞれ代入
                'name' => $robot->name,
                'type' => $robot->type,
                'year' => $robot->year,
            ]
        );

        // Create a response
        $response = new Response(); //レスポンスを作成

        // Check if the insertion was successful
        if ($status->success() === true) {
            $response->setJsonContent( //ステータスがうまくいったら
                [
                    'status' => 'OK' //ステータスをOKにする
                ]
            );
        } else {
            // Change the HTTP status
            $response->setStatusCode(409, 'Conflict'); //うまくいかなければ、409のConflictにする

            $errors = []; //エラーを格納する空箱を用意

            foreach ($status->getMessages() as $message) { //エラーメッセージを取得して、
                $errors[] = $message->getMessage(); //errorsに代入
            }

            $response->setJsonContent(　//HTTPレスポンスの本文を作成する
                [
                    'status'   => 'ERROR', //ステータスをエラーにして
                    'messages' => $errors, //エラーメッセージを表示？
                ]
            );
        }

        return $response;　//レスポンスを返す
    }
);
```

```my-rest-api/index.php
// Deletes robots based on primary key 削除
$app->delete(
    '/api/robots/{id:[0-9]+}',
    function ($id) use ($app) {
        $phql = 'DELETE FROM Store\Toys\Robots WHERE id = :id:'; //削除なので、DELETEがありますね

        $status = $app->modelsManager->executeQuery( //先ほどのphqlを実行
            $phql,
            [
                'id' => $id, //idを表示？？
            ]
        );

        // Create a response
        $response = new Response();

        if ($status->success() === true) { //うまくいったら
            $response->setJsonContent( //HTTPレスポンスの本文を作成する
                [
                    'status' => 'OK' //ステータスをOKにする
                ]
            );
        } else { //うまくいかなければ
            // Change the HTTP status
            $response->setStatusCode(409, 'Conflict'); //ステータスを409のConflictにする

            $errors = [];　//エラーを格納する空箱を作って

            foreach ($status->getMessages() as $message) { //エラーメッセージを取得し
                $errors[] = $message->getMessage(); //errorsに代入
            }

            $response->setJsonContent(　//HTTPレスポンスの本文を作成する
                [
                    'status'   => 'ERROR', //ステータスをERRORにして
                    'messages' => $errors, //エラーメッセージを表示？
                ]
            );
        }

        return $response; //responseを返す
    }
);
```