ピュアなPHPアプリケーションにLaravel標準ORMのEloquentを導入した

本エントリでは、ピュアなPHPで書かれたWebアプリケーションにLaravel標準のORMであるEloquentを導入した際にやったことを簡単にまとめています。

実施した際はPHP5.6でしたが、学習のためも含めて本エントリ内のソースコードはPHP7.2で動作させています。
経緯でも書かせていただいていますが、データベースはSQLite3を使っていますが、macOSで動かす場合にはすでにインストールされていると思うのでsqlite3 -versionで確認してから動かしてみてください。

経緯

事前に、Eloquentを導入するに至った経緯を簡単に説明しておきたいと思います。

SQLite3をデータソースにしたレガシーなプロジェクト

あるプロジェクトが素のPHPで書かれています。すべてのAPIがその1つのモノリシックなPHPアプリケーションとなっています。
ここで問題となっているのが、データベースとしてSQLite3を利用していることでした。
SQLite3はデータベースをファイルとして扱うため、

  • ファイルI/Oが遅くなる
  • サーバの分散ができない

という問題を抱えています。
また、行ロックではなくテーブルロックであるため書き込みが多いようなアプリケーションには向かない、という問題もありました。
嬉しいことに、サービスの成長によってサーバをスケールアウトできるようにしてリソースに余裕がほしいという要望が出てくることになりました。

Laravelへの移行は一朝一夕ではできない

ほかのプロジェクトではLaravelを利用しており、データベースは一部SQLite3を引き継いでいるものの、多くはMySQL(AWS Aurora)です。
ただ、前述のアプリケーションの大きさゆえに、Laravel + MySQLへの移行はすぐには難しく、まずは、MySQLへの移行をする準備として、Laravel標準のORMであるEloquentを既存のコードに入れていくという運びとなりました。

クライアントごとにSQLite3のファイルが異なる

また、管理していたSQLite3のファイルは複数存在しました。
グローバルな情報を扱うアプリケーションに唯一のデータベースと、クライアントにつき幾つか存在するデータベースがあり、リクエストの方法によって、クライアントごとに書き込みや参照をするデータベースを変えるということをしていました。
今回は、こちらの話には触れず、Eloquentの導入部分のみを書きます。
こちらの話も今後別記事として書きたいと思います。

やったこと

あとは淡々とやっていったこと、その際に調べたことを書きます。

※ 簡単な例を用意しました。
https://github.com/zuckeyM-17/php-sandbox/tree/master/use-eloquent-at-pure-php-app

4ステップでできます。

  1. PHPのバージョン管理ツールであるcomposerをインストール
  2. illuminate/databaseというパッケージをインストール
  3. illuminate/databaseの設定
  4. 必要なEloquentモデルを作成

1. PHPのバージョン管理ツールであるcomposerをインストール

$ cd ./src
$ curl -sS https://getcomposer.org/installer | php

用意した例では、環境を汚さないようcomposer.pharというファイルをsrcディレクトリ直下にダウンロードするという方法を取っています。

2. illuminate/databaseというパッケージをインストール

$ ./composer.phar require illuminate/database

ステップ1で用意したcomposer.pharを利用して illuminate/databaseというパッケージをインストールします。
Larvelを構成するライブラリはすべてgithubilluminateというところに所属します。
そこでdatabase部分を担当する、illuminate/databaseをインストールするわけです。

illuminate/databaseのREADME.mdの日本語訳が見当たらなかったので、和訳しました。

3. illuminate/databaseの設定

ほぼ、illuminate/databaseのREADMEを読めば簡単に作ることができます。
READMEではデータソースがMySQLだったため、例ではSQLiteで指定しました。
SQLiteで必要な項目は、ファイルへのパスのみなので簡単です。

<?php

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => 'sqlite',
    'database'  => SRC_DIR . '/app.db',     // ここにSQLiteファイルへのパスを入れる
]);

$capsule->setAsGlobal();
$capsule->bootEloquent();

4. 必要なEloquentモデルを作成

illuminate\Database\Eloquent\Modelというクラスを継承したモデルクラスを作成します。
EloquentはActiveRecordの実装となっているため、Modelクラスはテーブルについて1つ作成し、Modelクラスに生えた便利なメソッドでテーブルにアクセスすることができます。
最低限な実装をすると以下のようになります。

<?php
require_once dirname(__FILE__).'/database.php';
use Illuminate\Database\Eloquent\Model;
class Book extends Model {}

これで、Bookモデルがアプリケーションで使えるようになりました。
以下ではBookの中身を取り出して表示しています。

<?php
define('SRC_DIR', dirname(__FILE__));

require_once(SRC_DIR . '/vendor/autoload.php');
require_once(SRC_DIR . '/database.php');
require_once(SRC_DIR. '/Book.php');

$books = Book::all();

foreach($books as $book) {
    echo $book->isbn, "\t" , $book->name, "\t", $book->author, "\t", $book->created, "\t", $book->updated, PHP_EOL;
}

まとめ

Eloquentをライブラリとして導入しました。
illuminate/databaseというパッケージを入れることで可能でした。
ただ、 illuminate/database単体では、マイグレーション周りをサポートしていないらしく、今回のユースケースでは既存のテーブルに対して行うということだったので、ただ純粋にEloquentをライブラリとして使うということを目的とすると、調査が甘かったようです。
EloquentのModelは便利なメソッドがたくさん生えているので、そちらについても今後紹介して行こうと思います。

また、illuminateなどOSSとしてのLaravelのプロジェクトについて少し知識がついたので、これからもう少しソースコードをしっかり追っていきたいなとも思いました。

間違っている部分、この施策についてのフィードバックなどありましたら、いただけると嬉しいです!