Laravlでユーティリティクラスはどこに作ればいいのか?

2021-03-11
4 min read

Laravel で、ユーティリティクラスを作る必要が生じたときに、配置などに悩んだことはないでしょうか? 実装が簡単で Laravel の枠組みにしっかりと準じる方法として考えたいのがヘルパー関数です。

Laravel がいうところのヘルパー関数とは、グローバルな共通関数のことになります。 メリットは、どこからでも呼ぶことができ、いちいちuseで使用を宣言する必要もありません。

すでに使用されている共通関数

Laravel でプログラミングをしていると、ヘルパ-関数を意識せずに使用していると思われます。 コントローラの各メソッドの最後で、viewを使用していないでしょうか? viewはヘルパー関数になります。

vendor/laravel/framework/src/Illuminate/Foundation/helpers.php


if (! function_exists('view')) {
    /**
     * Get the evaluated view contents for the given view.
     *
     * @param  string|null  $view
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
     * @param  array  $mergeData
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
     */
    function view($view = null, $data = [], $mergeData = [])
    {
        $factory = app(ViewFactory::class);

        if (func_num_args() === 0) {
            return $factory;
        }

        return $factory->make($view, $data, $mergeData);
    }
}

このファイルには、view以外にもヘルパー関数が定義されています。

vendor/laravel/framework/src/Illuminate/Foundation/helpers.php以外にも、 vendor/laravel/framework/src/Illuminate/Support/helpers.phpにもハルパーの関数は定義されています。

以下の公式ドキュメントにはすべてのヘルパー関数が記載されています。 https://laravel.com/docs/8.x/helpers#method-array-accessible

autoloadのしくみ

ヘルパー関数を利用する際に、useが不要なのはcomposerautoload機能で作られたファイルを Laravle がindex.htmlrequireしているからです。

/var/www/html/todo/public/index.php

require __DIR__.'/../vendor/autoload.php';

このしくみにより、Laravel ではrequireを記述することがありません。

vendor/autoload.phpについては下記になります。

<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit23ab39906b1c8511784f28bd001d9b73::getLoader();

autoload_real.phpにて定義されたComposerAutoloaderInit23ab39906b1c8511784f28bd001d9b73クラスのgetLoaderメソッドで、 composer.jsonの autoload で指定されたものを load するしくみになっています。

vendor/laravel/framework/composer.jsonは下記になります。

    "autoload": {
        "files": [
            "src/Illuminate/Foundation/helpers.php",
            "src/Illuminate/Support/helpers.php"
        ],
        "psr-4": {
            "Illuminate\\": "src/Illuminate/"
        }
    },

filesにて前述の 2 つのファイルが指定されています。 関数だけでなく定数の定義にも利用できます。

定数の定義は、config/const.phpファイル、クラスのstaticプロパティの方法が知られていますがautoloadでも実現できます。

独自のヘルパー関数の定義方法

helpers.phpファイルの作成

app直下にhelpers.phpを作成し関数を定義します。 定義する関数は、チュートリアルのLaravel入門(第12回)で解説したマルチバイト文字のtrimとします。

<?php

if (! function_exists('multibyte_trim')) {
    /**
     * マルチバイト対応trim 
     *
     * @param  string  $value
     * @return string
     */
    function multibyte_trim($value)
    {
        return preg_replace('/\A[\p{C}\p{Z}]++|[\p{C}\p{Z}]++\z/u', '', $value);
    }
}

Composer.jsonファイルへの追加

helpers.phpを autoload の対象に追加します。 filesというキーを作りファイルを指定します。

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
        "files": [
            "app/helpers.php" 
        ]        
    },

Composer dump-autoloadコマンド実行

composer.jsonファイルへの追加作業が完了したら、comoser dump-autoloadコマンドを実行します。

$ composer dump-autoload

このコマンドにて autoload のためのファイル群を最新状態にします。 参考:https://getcomposer.org/doc/01-basic-usage.md#autoloading

動作確認

tinkerにて動作を確認します。

$ php artisan tinker

全角空白をUnicodeポイントで指定し文字「1」の前後に付加しています。

>>> \IntlChar::chr("\u{3000}")."1".\IntlChar::chr("\u{3000}");
=> " 1 "

前後に全角空白が付加されています。 ヘルパー関数として定義したmultibyte_trimを使用します。

>>> multibyte_trim(\IntlChar::chr("\u{3000}")."1".\IntlChar::chr("\u{3000}"));
=> "1"

前後の全角空白が取れて「1」のみが表示されています。

まとめ

Java などのオブジェクト指向的な言語では、ユーティリティクラスを作って対応するものが PHP では関数にて対応できます。 ユーティリティクラスは、実装が少し面倒であり、そして使用する際にuseが必要になってきます。 Laravel ではグローバル関数として定義できてお手軽です。

しかし、なんでもかんでもグローバル関数であるヘルパー関数に定義するのもよくありません。 Laravel でも一連の操作の塊としてユーティリティクラス的なものがあります。

それらは、配列、文字列などの操作を簡単にするユーティリティクラスです。 各メソッドは static で定義されています。

  • Illuminate\Support\Arr
  • Illuminate\Support\Collection
  • Illuminate\Support\Str

バージョン 5.7 以降では、このようなユーティリティクラスも Helpers として公式ドキュメントに紹介されています。 これらは、たしかにヘルパーですが、もはやグローバル共通関数であるヘルパー関数ではなく使用に際してはuseが必要です。

https://laravel.com/docs/master/helpers