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ができています。

Project.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 の編集

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の編集

これまた記事からの参考です。

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

とかしたら、登録したやつが帰ってくる

URLに入れるとgetリクエスト飛ばした時の処理になり、帰ってくる

(そもそもwebページ閲覧はGETリクエスト?なので)

FAQ よくある?(僕が出くわした)

Class 'MongoDB\Driver\Manager' not found

8のコマンドでコントローラーを作ろうとしたら、

Class 'MongoDB\Driver\Manager' not found

ってでた。
多分artisanのキャッシュの問題。github確認してもDriver/Managerなんてない。
ちなみに/etc/php.iniの編集でextension記述しなくてもおそらくこの方法なら自動記述してくれると思います。僕の場合、

これはやってはダメ。おそらく非推奨の古いmongoDBのドライバーが来ると思います。
pecl install mongo

Answer

説明した手順踏んでさえすれば、キャッシュのクリアで解決しそうです

php artisan cache:clear

MongoDB\Driver\Exception\AuthenticationException Authentication failed

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

'username' => env('MONGO_USERNAME', ''),
'password' => env('MONGO_PASSWORD', ''),

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