CentOS7&apache2.4&LumenでイチからRESTFullなAPIの実装


商用だとこんな使い方しないだろうとは思いますが、
個人でサーバー立ててAPI公開のためだけにドメイン取得するのもコストがかかるので
ブログとかと共存してApiを置くことができるかチャレンジしてみました。
ほぼWindowsしか扱ったことがなく、
phpは世界に挨拶しかしたことない初心者だったのでいろいろ大変でした・・・・

#環境
|||
|-------|---------|
|CentOS | 7.4.1708|
|apache | 2.4.6|
|php    | 7.1.16|
|Lumen  | 5.6.3 (laravel Components 5.6.*)|

#必要なもののインストール

##apache
```
# yum -y install httpd
```

##php関連
```
// php本体とlumenの構築に必要なもの
# yum -y install epel-release
# yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
# yum --enablerepo=remi-php71 -y install php71 php71-php php-pdo php-mbstring php-pecl-zip php-openssl php-xml
// あとはお好みで
# yum --enablerepo=remi-php71 -y install php-mcrypt php-gd php-bcmath php-enchant php-intl php-devel php-common php-pecl-mysql
```

##composer
```
# curl -sS https://getcomposer.org/installer | php

// composerにリネームしてパスが通っている場所に配置することで
//　'# composer hoge' が可能になる
# sudo mv composer.phar /usr/local/bin/composer
# sudo chmod +x /usr/local/bin/composer
```

##Lumen

```
// lumen installer のダウンロード
# composer global require "laravel/lumen-installer"
```

# `http://example.com/Api/v1/~`でApiを公開する例
ディレクトリの場所は適宜読み替えてください
DocumentRoot下にアプリディレクトリを配置するので
セキュリティ的によろしくない例かもしれません。
普通はどうやってセットアップするんでしょうか・・・・

##LumenProjectのセットアップ

```
// DocumentRootに移動し、Lumenのプロジェクトを作る
# cd /var/www/html
// 下記の例ではカレントディレクトリにApiディレクトリが作られ、そこにproject本体が配置される
# composer create-project --prefer-dist laravel/lumen Api

// Apiディレクトリに移動する
# cd Api

// 必要なライブラリをcomposerでインストール
// (autoload.jsonを読み込んで勝手にやってくれてる)
# composer install
```

##Lumenの動作確認
```
// アプリを起動
// Apiフォルダにて下記コマンドを実行
# php -S localhost:8000 -t public
```

ブラウザのアドレスバーに'localhost:8000'と入力し、ページで移動
LavarelとLumenのバージョンが表示されればOK

##httpd.confの変更
###httpd.confを開く
```
# vim /etc/httpd/conf/httpd.conf
```
###httpd.confの編集
```
// DocumentRootが"/var/www/html"であることを確認
DocumentRoot "/var/www/html"

// 下記項目を追加
// `http://example.com/Api/v1`へアクセスした時のRewriteの設定
<Directory "/var/www/html/Api/v1">
 AllowOverride None
 <IfModule mod_rewrite.c>
  <IfModule mod_negotiation.c>
   Options -MultiViews
  </IfModule>

  RewriteEngine On
  RewriteRule ^(.*)/$ /$1 [L,R=301]
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^ index.php [L]
 </IfModule>
</Directory> 

// Apiディレクトリへのアクセスを拒否する
// これでappフォルダ等への直接のアクセスを弾ける？
<Directory "/var/www/html/Api">
  Deny from All
</Directory> 
```

##アクセスされるディレクトリの作成

```
// Apiディレクトリにてpublicをv1として複製
# cp -r public v1
```

##動作確認

```
// httpdを再起動
# systemctl restart httpd
```

ブラウザで'localhost/Api/v1'にアクセス
LaravelとLumenのバージョンが表示されていれば成功


#機能の追加
例として`http://example.com/Api/v1/info`にアクセスされたら
phpinfoを出力する機能を追加

##phpinfoを出力するコントローラーを追加

```
// 下記ディレクトリに移動
# cd /var/www/html/Api/app/Http/Controllers

//ExampleControllerをコピーしてPhpInfoControllerを作成
# cp ExampleController.php PhpInfoController.php

// PhpInfoControllerを開く
# vim PhpInfoController.php

```

###PhpInfoController全内容
show関数を呼ばれたらphpinfoを返す

```php:PhpInfoController.php
<?php

namespace App\Http\Controllers;

// ExampleControllerをPhpInfoControllerに変更
class PhpInfoController extends Controller
{

    //インスタンスの呼び出しを削除してshow関数を実装
    public function show()
    {
        return phpinfo();
    }

}

```

##ルーティングを設定
URLとControllerの結び付け
Api/v1/infoへのアクセスでphpinfoを返す

```
// ルーティングはApi/routes/web.phpで設定されている
# vim routes/web.php
```

```php:web.php
<?php

$router->get('/', function () use ($router) {
    return $router->app->version();
});

// 下記記述を追加
// 第一引数で"Api/v1/"以降のURLを渡す
// 呼び出されたときに返したいコントローラーと関数を渡す
// @以降は関数名
$router->get('info','PhpInfoController@show');


```

##localhostへアクセスして動作を確認
`http://localhost/Api/v1/info`をブラウザで表示
phpinfoが見れていれば成功

##機能追加のまとめ
呼び出しのURLを追加する時は
- routes/web.phpに呼び出しUrlとリクエストを受けたときに返すControllerの指定を追加
- app/Http/Controllerに実際のビジネスロジックを持ったControllerを追加する
- POSTなども同じ要領で追加可能

他にもURLの中身を関数の引数として渡したり、"/info?name=~"みたいな引数を関数へ引き渡せたりもできるみたいです。
その辺の記事は自分で試せたらまた書こうと思います。

#感想
Controllerをいちいち追加するのがめんどくさいなーと思った
サーバーサイドやってる人っていっつもこんなことをしてるんでしょうか・・・・
便利なコマンドとか、開発ツールとかあったら教えてほしい・・・・
httpd.confの設定等、複雑でいまいち把握できていないところがあるので間違いあればご指摘いただければ幸いです。

[GraphQLのAPIも便利そう](https://qiita.com/shimbaco/items/e3f2f8650b08e1e060bd)なので触ってみたい。

#参考文献
- [Lumen本家のDocument](https://lumen.laravel.com/docs/5.6)

- [blog // sakura note:nginx + php7 + Lumen な開発環境をVagrantでつくる](https://saku.io/dev-env-for-php7-lumen-on-vagrant/)

- [Qiita laravel製軽量フレームワーク Lumen を試してみる](https://qiita.com/yaaamaaaguuu/items/f42f1127c96f44cb836f)