LaravelでmongoDBのAPIを作ったので詰まったところを書いておく

こんにちは。最近急に寒くなってきましたね。
朝は、30分だけ！と暖房つけてしまいます。でもやっぱ、通勤、通学って歩くっていう運動をしていくわけで、到着した会社等で暖房ガンガンだと暑くないですか？僕は暑いです。

今回はWebアプリを作る際に**オンプレのNoSQLを求められた想定**でモジモジしてみました。
# 前提
* PHPがインストールしてあること(brew等で)
* composerがインストールしてあること
* Laravelのプロジェクトが作成してあること  
Laravel始めたいならこの記事おすすめです  
https://qiita.com/sano1202/items/6021856b70e4f8d3dc3d  
Laravelのインストールからの方はこの記事に沿ってLaravelのプロジェクトを作るところまでいくとスムーズですね

# 環境
* Mac OS Mojave
* PHP 7.3.11
* Laravel 6.5.0
* MongoDB 4.0.3

# 手順
## 1. PHP用mongoモジュールをインストール

```
pecl install mongodb
```
#### peclがないと言われたそこのあなた
peclはPHPがそこそこ最新なら付属してきます！
https://teratail.com/questions/126448
このteratail記事のように
```
brew install php
```
してみましょう！

## 2. Laravel用mongoDBドライバー(クエリビルダ等)をインストール
```
composer require jenssegers/mongodb
```

githubはこちら：https://github.com/jenssegers/laravel-mongodb

ここからはこの記事を参考引用します
https://qiita.com/ekzemplaro/items/609fe7a5869a499b298d
## 3. config/app.php の編集

```
'providers' => [
// 略
        Jenssegers\Mongodb\MongodbServiceProvider::class,
 ],

    'aliases' => [
// 略
         'Moloquent' => Jenssegers\Mongodb\Eloquent\Model::class,
 ],
```

## 4. .env の編集
```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```
を消して

```
DB_CONNECTION=mongodb
DB_HOST=127.0.0.1
DB_PORT=27017
DB_DATABASE=city_db
```

## 5. config/database.php の編集
```
'default' => env('DB_CONNECTION', 'mongodb'),
    // 略
    'connections' => [
        'mongodb' => [
            'driver' => 'mongodb',
            'host' => env('DB_HOST'),
            'port' => env('DB_PORT'),
            'database' => env('DB_DATABASE'),
        'username' => env('DB_USERNAME'),
        'password' => env('DB_PASSWORD'),
        ],
    ],
```
## 6. モデルの作成
```
php artisan make:model Models/Project
```
するとModelsディレクトリ配下にProject.phpができています。
<img width="319" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448316/fd16bc9e-b4cc-b960-636d-78741ebe5194.png">

Project.phpは以下のように編集します。

```php:Models/Project.php
<?php

namespace App\Models;


class Project extends \Moloquent
{
    protected $collection = 'project';
}
```
$collectionにはmongoDBでのコレクションを指します。mongoDBはドキュメント型データベースなので、RDB(リレーショナルデータベース like MySQL, PostgreSQL)のように表にはなりません。ここでは言及しませんが興味がでたら調べてみてください。mongoDB自体ははやらずとも、NoSQLという概念は今後も根付いていくと思います。
## 7.routes/api.php の編集
```php:routes/api.php
Route::group(['middleware' => ['api']], function(){
  Route::resource('projects', 'Api\ProjectController');
  Route::get('all', 'Api\ProjectController@all');
  Route::get('find/{id}', 'Api\ProjectController@find');
  Route::get('where/{name}', 'Api\ProjectController@where');

});
```
ProjectControllerはこの後作ります。
## 8.コントローラーの作成
```
php artisan make:controller Api/ProjectController
```
## 9. ProjectController.phpの編集
これまた記事からの参考です。

```php:app/Http/Controllers/Api/CityController.php
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Project;

class ProjectController extends Controller
{
    public function index()
    {
    $projects = Project::orderBy('_id', 'desc')->get();
    return $projects;
    }

    public function all()
    {
    $projects = Project::all();
    return $projects;
    }

    public function find($id)
    {
    $projects = Project::find($id);
    return $projects;
    }

    public function where($name)
    {
    $projects = Project::where('name','=',$name)->get();
    return $projects;
    }
}
```
## 10. API動作確認
```
php artisan serve --host 0.0.0.0
```
でサーバーを起動し、他シェルで

```
curl http://127.0.0.1:8001/api/project
```
とかしたら、登録したやつが帰ってくる
<img width="725" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448316/da49883a-5bf7-37e0-a7f5-db0e8a16fac0.png">

URLに入れるとgetリクエスト飛ばした時の処理になり、帰ってくる  
(そもそもwebページ閲覧はGETリクエスト？なので)
<img width="405" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448316/fb95d228-97c5-33d8-3f06-89589f746efc.png">


## FAQ よくある?(僕が出くわした)
### Class 'MongoDB\Driver\Manager' not found
8のコマンドでコントローラーを作ろうとしたら、  

```
Class 'MongoDB\Driver\Manager' not found
```
ってでた。
多分artisanのキャッシュの問題。[github](https://github.com/jenssegers/laravel-mongodb)確認してもDriver/Managerなんてない。
ちなみに/etc/php.iniの編集でextension記述しなくてもおそらくこの方法なら自動記述してくれると思います。僕の場合、

```
これはやってはダメ。おそらく非推奨の古いmongoDBのドライバーが来ると思います。
pecl install mongo
```
### Answer
説明した手順踏んでさえすれば、キャッシュのクリアで解決しそうです

```
php artisan cache:clear
```

### MongoDB\Driver\Exception\AuthenticationException Authentication failed
<img width="1197" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448316/31d5fca9-cc49-4b39-f832-3c70aa3e6a8e.png">

これは、DB使うならユーザー名とパスワード必要でしょーと言ってmongoDBでユーザーを作成し、かつ**database.phpに**

```
'username' => env('MONGO_USERNAME', ''),
'password' => env('MONGO_PASSWORD', ''),
```
で.envに変数追加したりするとエラーになります。
**あくまでこの記事に沿ってやったらです。本来ちゃんとユーザーauthはしっかりすべきだと思います多分**
解決方法はgithubのissueから見つけました
https://github.com/jenssegers/laravel-mongodb/issues/766