Laravelで独自に作ったライブラリファイルへのパスの通し方 | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

コントローラーファイルにごりごりとビジネスロジックを書いていくようなやり方もありますが、コントローラー間の共通処理など別ファイルにロジックを分離したいということはよくあることです。

ってことで、Laravelでライブラリを定義する方法のまとめです。

ここでは、Laravel4.2をベースに書いています。



Laravelでライブラリを読み込む方法


基本的にLaravelはファイルやディレクトリの構成の制約をうけません。

どこに何のファイルを置いているのかを定義しておけば素直に読み込んでくれます。

ということで、まずはライブラリ用のディレクトリ(lib)を今回の例ではlaravel/app以下に作成するとします。


$ cd /path/to/laravel/app
$ mkdir lib

この下にライブラリファイルを作っていくわけですが、このディレクトリへのパスの通し方は幾つか方法があります。


まずは、composerを使う方法。

composerで読み込む場合は、laravel/composer.jsonにオートロードするように記載します。


    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php",
            "app/lib",
        ]
    },

composer.jsonを編集した後は


$ composer dump-autoload

を実行する必要があります。

composerの使い方の詳細は「[Composer] プログラムのオートロードはComposerにお任せ 」を参照。

composerを使うとそっちに依存したり、ディレクトリが増えるたびにdump-autoloadするのが面倒だったりもするというデメリットもあったりします。


次に、app/start/global.phpに対象ディレクトリを書いてしまう方法です。


/*
|--------------------------------------------------------------------------
| Laravelクラスローダーの登録
|--------------------------------------------------------------------------
|
| Composerを使用することに加え、コントローラーとモデルをロードするために
| Laravelのクラスローダーを使用することもできます。Composerを更新しなくても
| 「グローバル」な名前空間にあなたのクラスを設置しておくのに便利です。
|
*/

ClassLoader::addDirectories(array(
    app_path().'/commands',
    app_path().'/controllers',
    app_path().'/models',
    app_path().'/database/seeds',
    app_path().'/lib',
));

最後に、laravel/libへのパスを追加しています。

こちらは、ファイルを編集するとすぐに読み込んでくれるためシステムの構成に柔軟に対応させることができるので一番手っ取り早い方法かもしれません。

ただし、Laravel内の全システムで共通となるため、全てで使う共有ライブラリを作りたいといった場合はよいですが、システム(やコントローラ)ごとのライブラリを作りたいといった場合は多少構成が煩雑になる可能性があります。


最後は、サービスプロバイダを使うやり方です。

こちらは、「Laravelでサブシステム用のディレクトリを分離する 」に書いたようにシステムごとにディレクトリを分離したいといった場合に便利なやり方ですが、少し設定が面倒です。


最初に、サービスプロバイダ用のファイル(CommonServiceProvider.php )を配置します。

今回は、laravel/app/Myproviders/Servicesに置くとします(実際にディレクトリやファイル名はどこでも大丈夫です)。

サービスプロバイダ用のファイルは下記のようなものとなります。


<?php

namespace Myproviders\Services;

use Illuminate\Support\ServiceProvider;

class CommonServiceProvider extends ServiceProvider
{
    public function boot()
    {
        \ClassLoader::addDirectories(array(
            __DIR__ . '/../../lib',
        ));
    }
    /**
     * Iocコンテナの登録.
     *
     * 事前に登録したいクラスがある場合はここで設定する.
     *
     * @return void
     */
    public function register()
    {
    }
}

あとで、composerのオートロードにも登録するため名前空間を定義しています。

そして、boot()内にライブラリ用のディレクトリパスを定義しています(サービスプロバイダファイルからみたディレクトリパスを指定します) 。

次に、laravel/app/config/app.phpを編集し、先ほど作ったサービスプロバイダを登録します。


    /*
    |--------------------------------------------------------------------------
    | オートロードサービスプロバイダー
    |--------------------------------------------------------------------------
    |
    | ここにリストしたサービスプロバイダーはアプリケーションのリクエストに対し
    | 自動的にロードされます。アプリケーションの機能を拡張するため、この配列へ
    | 自由に自分のサービスを付け加えてください。
    |
    */

    'providers'=> array(

        'Illuminate\Foundation\Providers\ArtisanServiceProvider',
        'Illuminate\Auth\AuthServiceProvider',
        'Illuminate\Cache\CacheServiceProvider',
- snip -
        'Myproviders\Services\CommonServiceProvider'
    ),

指定方法は、PSR-0のオートロードに準拠した名前空間で指定します。

最後に、laravel/composer.jsonにサービスプロバイダを置いたディレクトリを登録しておきます。


    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ],
        "psr-0": {
            "Myproviders": "app/"
        }
    },

編集後は、dump-autoloadしておきます。

こちらも編集ファイルが多かったり、composerを使わないといけないといったデメリットはあるんですけど、「Laravelでサブシステム用のディレクトリを分離する 」に書いたようにシステムを分離したいといった場合に便利な方法かもしれません。



Laravelのライブラリを作成する


これでライブラリが読み込める環境となったわけですが、ライブラリファイル自体は一般的なクラスファイルとして定義すればよいだけです(モデルやバリデータを作りたいといった場合は継承するクラスがありますが今回は割愛します) 。


<?php

class Tools
{
    function foo() {
        return true;
    }
}

呼び出し方は、コントローラから


    public function bar()
    {
        $obj = App::make('Tools');
        $obj->foo();
    }

とするだけで呼び出せます。

余談ですが、サービスプロバイダを作っておくと独自のプレフィックスを定義できたりもして便利です。

先ほどのサービスプロバイダのboot()に


    public function boot()
    {
        \ClassLoader::addDirectories(array(
            __DIR__ . '/../../lib',
        ));

        \View::addNamespace('Common', __DIR__ . '/../../views');
        \Config::addNamespace('Common', __DIR__ . '/../../config');
    }

このように「Common」というプレフィックスを定義しておくことで、


// 設定ファイルの読み込み
$env = Config::get('Common::const.MY_ENV');
// Viewファイルを読み込み
return View::make('Common::top');

のようなことができて設定ファイルやViewファイルを分離、明示することができたりもします。