2018.02.09 Laravel5.5でMongoDBを使ったWebサイト作成
3行で概要

このサイトはLaravel + MongoDBで作られているが
LaravelはデフォルトでMongoDBをサポートしてないので
専用のライブラリをインストール!

長い概要

このサイトの前身となるサイト(ver2 part1)を作った時に初めてMongoDBを使ってみて、RDBMSと比べてテーブルの関係性やSQL文を気にせず使えるNoSQLって凄くいいな!と感じたので今回もMongoDBを使ってみたのですが、LaravelはデフォルトでMongoDBをサポートしていないみたいだったので
https://github.com/jenssegers/laravel-mongodb
こちらのライブラリを使用してLaravelからMongoDBを使えるようにしました。

LaravelとMongoDBとの接続の部分で結構詰まってしまったので、その部分も含めてLaravelのサイトを動かすための手順をメモっていきます。

OS・ミドルウェアなどのバージョンは以下の通りです。
OS … Ubuntu 16.04
PHP … 7.2.2
Nginx … 1.12.2
MongoDB … 3.6.2
composer … 1.6.3
Laravel … 5.5.28

作業

Vagrantで作った仮想環境でサイトを作っていきます。
Vagrantfileの中身は以下の通りです。

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-16.04"
  config.vm.network "private_network", ip: "192.168.35.10"
end
必要なものをインストール

以下のコマンドを打っていきます

# php 7.2系と必要な拡張機能をインストール
sudo apt -y install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt -y install php7.2 php7.2-dev php7.2-dom php7.2-fpm php7.2-mbstring php7.2-mongodb php-pear pkg-config libssl-dev

# composer をインストール
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

# Nginx をインストール
curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"
VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb-src http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"
sudo apt update
sudo apt -y install nginx

# MongoDB 3.6系をインストール
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
sudo apt update
sudo apt install -y mongodb-org

# Laravel のプロジェクトを作成
sudo apt -y install  php7.2-zip
composer create-project --prefer-dist "laravel/laravel=5.5.*" test
# 新しく作られたtestディレクトリ内にLaravelのコードなど一式が入っているはず
Webサーバを立てるために設定変更 & Nginx起動

MongoDBを使うためのライブラリを入れる前に一旦素の状態のLaravelを起動させてみます。

まずはNginxでPHPを実行できるように /etc/nginx/conf.d/default.conf ファイルを変更します。
ファイルの中身は以下の通りです。

server {
    listen       80;
    server_name  localhost;
    root /home/vagrant/test/public;

    location / {
        index  index.php;
        try_files $uri $uri /index.php$is_args$args;
    }

    location ~ .php$ {
        fastcgi_pass   unix:/run/php/php7.2-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
        include        fastcgi_params;
    }
}

php-fpmとLaravelはデフォルトの状態だと権限周りのエラーが出てしまうので、以下のコマンドで権限を変更しNginxを起動します。

sudo chmod 666 /run/php/php7.2-fpm.sock
chmod 777 ~/test/storage/logs/
chmod 777 ~/test/storage/framework/views/
sudo service nginx start

これでNginxが起動したので、ブラウザを開いてアクセスすると・・・

Laravelのデフォルトページが表示されました!

LaravelにMongoDBのライブラリ & 設定追加

Laravelのデフォルトページが開くことが確認できたので、本題のMongoDBの部分に入っていきます。
まずは以下のコマンドでライブラリをインストールします。

cd ~/test
composer require "jenssegers/mongodb=^3.3"

次に、インストールしたライブラリをLaravelから使えるようにするためにconfigディレクトリ内のファイルを編集していきます。
まずは、 ~/test/config/app.php に以下の内容を加えます。

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

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

MongoDBを使うためのクラスをLaravelのコードから呼び出せるように設定しました。
次に、 ~/test/config/database.php に以下の内容を追加します。

return [
    // 略
    //'default' => env('DB_CONNECTION', 'mysql'),
    'default' => env('DB_CONNECTION', 'mongodb'),
    // 略
    'connections' => [
        'mongodb' => [
            'driver' => 'mongodb',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', 27017),
            'database' => env('DB_DATABASE', 'testDB'),
        ],
    ],
    // 略
];

最後に、 ~/test/.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=testDB

LaravelがMongoDBを使う時の設定を追加し、デフォルトの状態でDBに接続するときはMySQLではなくMongoDBを使うように変更しました。

Laravelの設定を変更した際は、Laravelが保存している過去のキャッシュのせいでエラーが出てしまうので、以下のコマンドを打っておきます。

php ~/test/artisan cache:clear
MongoDBを使うためのコーディング

これでLaravelからMongoDBを使うための準備は全て終わったので、実際にMongoDBから値を取ってきて表示するコードを書いていきます。
まずはルーティングを作るために ~/test/routes/web.php を以下の内容に変更します。

<?php
Route::get('/', 'TestController@index');

これでルートディレクトリにアクセスした際にTestControllerのindexメソッドが呼び出されるようになりました。
次はこのコントローラーを作ります。
ファイルパスは ~/test/app/Http/Controllers/TestController.php で、内容は以下の通りです。

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class TestController extends Controller
{
    static function index() {
        $posts = Post::orderBy('_id', 'desc')->get();
        return view('index', ['posts' => $posts]);
    }
}

Postモデルからデータを取得してindexというviewに取得したデータをそのまま渡しています。
次はこのPostモデルを作っていきます。
ファイルパスは ~/test/app/Post.php で、内容は以下の通りです。

<?php
namespace App;
class Post extends \Moloquent
{
    protected $collection = 'post';
}

使う機能は継承元のMoloquentクラスのものをそのまま使うので、postコレクションから値を取ってくるぞ!ということだけを書いておきます。
最後に実際に画面に表示するviewを作っていきます。
ファイルパスは ~/test/resources/views/index.blade.php で、内容は以下の通りです。

<div>全部で{{ count($posts) }}件</div>
<ul>
  @foreach($posts as $post)
    <li>{{ $post['date'] . ' | ' . $post['body'] }}</li>
  @endforeach
</ul>
MongoDBにデータを入れて確認

これでコーディング部分は全て終わったので、MongoDBに実際にデータを入れて、正しく表示されるかを確認してみます。
まずは以下のコマンドでMongoDBを起動します。

sudo service mongod start

次にMongoDBにデータを入れていきます。
コマンドでぽちぽち入れていくのはしんどいのでRobo 3Tというクライアントソフトを使いました。

こんな感じでデータを入れてもう一度ブラウザでアクセスすると・・・

MongoDBのデータが反映されました!

後書き

この記事を書いてる途中でLaravel5.6がリリースされたのでそっちでも試してみたのですが、

composer require "jenssegers/mongodb=^3.3"

コマンドを打った時にエラーが出てしまった(このライブラリがLaravel5.6に対応していない?)ので断念することに・・・