ちょっとしたパフォーマンスの改善

Laravelは非常にたくさんのファイルを起動時に読み込んでいるので、パフォーマンスの改善は以前から感心があります。最近、管理画面だけでrouteの数が300近いプログラムをインストールするにあたり、重たくなることを予想して、簡単にできる範囲でLaravelでのパフォーマンスの改善を調査してみました。

1.設定ファイルのキャッシュ作成

php artisan config:cache

この実行は、configのディレクトリにあるファイルすべてを合わせて1つのキャッシュファイルにします。これにより設定データのローディング時間を速めようということです。

ファイルは、

bootstrap/cache/config.php

として作成されます。

この使用において、注意は3点あります。

注意点1:プログラムにおいてenv()の関数を使用してはいけない

例えば、

.envのファイルにおいて、

APP_ENV=local

と設定していて、

$path = storage_path().'/'.env('APP_ENV').'/logs/test.log';

のように、現在の環境変数の値によりログファイルを置くディレクトリを変えるとすると、

$pathの値は、

/var/www/test/storage/local/logs/test.log

のようになります。

しかし、config:cacheを実行すると、env()の値は空となり、

/var/www/test/storage/logs/test.log

となってしまい、意図した場所とは違うことになってしまいます。

それゆえに、先のプログラムは以下と変更することが必要です。

$path = storage_path().'/'.config('app.env').'/logs/test.log';

もちろん、config/app.phpなどの設定ファイルの中でのenv()の使用は問題ないです。

注意点2:ダイナミックに値を設定しているconfigに気おつける

設定ファイルの値は、

config(['some_setting' => 'some_value']);

のようにダイナミックに値の設定が可能です。例えば、DBからの値をAppServiceProvider::boot()で読み込んでおいて、DBに再度アクセスすることなくプログラムのあちらこちらで使用しようというときなどに便利です。

ところが、php artisan config:cacheの実行時に、AppServiceProvider::boot()が実行されるので、それらの設定もキャッシュファイルに保存されてしまいます。これで、ダイナミックに変わる値が固定されては困ります。

しかし、ダイナミックに上書きされるので問題はなさそうです。しかし、プログラムの他の部分では問題があるかもしれません。使用には気おつけてください。

注意点3:.envやconfigのファイルを編集したら、必ずキャッシュを再作成

最後に忘れてはならないのは、.envやconfig/*.phpのファイルを編集したら、必ずphp artisan config:cacheの実行が必要なことです。それなくしては、せっかくの変更も反映されません。

2.routeのキャッシュ作成

php artisan route:cache

こちらは、config:cacheと違い、この実行で作成されるファイル、

bootstrap/cache/routes.php

には、routes.phpファイルを読み込んでLaravelがマップしたデータ構造をbase64_encodeして、serializeした形で収めます。それゆえに、この読み込みとマップの作業を一気に短縮します。とくに、routeの数が大きいプロジェクトではパフォーマンスの改善に期待できる仕組みです。

それからconfig:cacheと同様に、routes.phpファイルを編集したら、必ずphp artisan route:cacheの実行が必要です。

3.共有クラスファイルの最適化

これは、環境変数のAPP_ENVがproductionの値のときにだけに有効なものです。また、設定ファイルに依存するので、設定ファイルをキャッシュするなら、php artisan config:cacheを実行してから以下を実行してください。

php artisan optimize

この実行で、共有されるクラスファイルを1つのファイルにまとめ、読み込み時間を短縮するのが目的です。以下のファイルを作成します。

bootstrap/cache/compiled.php

このファイルには、デフォルトでは、Laravel関連のファイルが含まれますが、必要なら以下の設定ファイルに追加が可能です。

bootstrap/cache/compile.php

改善した?

さて、実際にこれらの最適化でパフォーマンスはどれくらい変わるのでしょうか?

私の厳密ではないテストでは、DB操作を伴わない計測では10~30%の違いがありました。configよりもrouteやoptimizeの方が実際のパフォーマンスにより影響ありました。多分、設定ファイルが小さく数少ないためがその違いと思います。しかし、現実では、DBクエリーやCSS、JS、画像などのダウンロードがはるかに時間がかかるので、まだ私のプロジェクトのスケールではちょっとした改善というところです。スケールがより大きくなるとかなりの差となるかもしれません。

入力のブラックリストとホワイトリスト

このブログを開始してから、もうすでに1年以上。RawのSQLを書いてコードに埋め込む日常から、Eloquentを使用したORMのコードへと日常へと移行しています。Eloquentに関しても、ブログを書き始めた頃からは理解が深まり、洗練されたLaravelのコードを書けるようになってきたこの頃です。

1年前に書いた「マスアサインメントで一括取り込み」のトピックで、EloquentのModelのクラスの属性fillableguardedの話、1年の経験で学んだことを含めてここでもう一度説明します。
続き “入力のブラックリストとホワイトリスト”

カスタムバリデーション (3) 既存バリデーションの置き換え

Laravelには最初から利用可能なバリデーションルールが多数存在していますが、そのいくつかは実用にならなかったり、自分好みに挙動を変えたりしたいこともあります。

CustomValidatorクラスは標準Validatorを継承していますので、これらを置き換えて上書きすることが可能です。

vendor/laravel/framework/src/Illuminate/Validation/Validator.php

ここから関数宣言をコピーして、前回作成したCustomValidatorクラスのファイルに貼り付けて編集します。引数はそれぞれの関数によって異なりますし、宣言が public ではなく protected であることに注意してください。

email

標準のemailバリデーションは実在してるメールアドレスがエラー判定になることがあります。これを解決するために正規表現による判定に置き換えてみたものです。

    /**
     * email
     *
     * @param string $attribute
     * @param string $value
     * @return true
     */
    protected function validateEmail($attribute, $value)
    {
        return (preg_match("/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,10})$/i", $value));
    }

 

管理画面では、メール送信者の指定などで名前付きメールアドレスの入力を容認する場面もあります。ついでに email_with_name を作成しておきましょう。

    /**
     * email_with_name
     *
     * @param string $attribute
     * @param string $value
     * @return true
     */
    public function validateEmailWithName($attribute, $value)
    {
        if (preg_match('/<(.*)>$/', $value, $m)
        {
            $value = $m[1];
        }

        return $this->validateEmail($attribute, $value);
    }

 

alpha, alpha_dash, alpha_num

これらアルファベット系の標準バリデーションは、全角英数字の文字コードを通します。

半角のasciiコードだけの入力許可に絞るため、これらも正規表現によるバリデーションルールに置き換えます。

/**
 * alpah
 *
 * @param string $attribute
 * @param string $value
 * @return true
 */
protected function validateAlpha($attribute, $value)
{
    return (preg_match("/^[a-z]+$/i", $value));
}

/**
 * alpah_dash
 *
 * @param string $attribute
 * @param string $value
 * @return true
 */
protected function validateAlphaDash($attribute, $value)
{
    return (preg_match("/^[a-z0-9_-]+$/i", $value));
}

/**
 * alpah_num
 *
 * @param string $attribute
 * @param string $value
 * @return true
 */
protected function validateAlphaNum($attribute, $value)
{
    return (preg_match("/^[a-z0-9]+$/i", $value));
}

ただし、ユーザが入力した全角英数に対してただエラーを返すようなユーザーインターフェースは褒められたものではありませんね。

入力を受け付けてからphpで半角に変換するという方法もありますが、私たちはjQueryスクリプトで入力前に変換する方法を選択しています。

jQueryスクリプトの例:

			var toHankaku = function (strVal){
				// 半角変換
				var halfVal = strVal.replace(/[!-~]/g, function(tmpStr) {
					// 文字コードをシフト
					return String.fromCharCode(tmpStr.charCodeAt(0) - 0xFEE0);
				});

				// 文字コードシフトで対応できない文字の変換
				halfVal = halfVal.replace(/”/g, "\"")
					.replace(/[ーー―-‐]/, "-")
					.replace(/’/g, "'")
					.replace(/‘/g, "`")
					.replace(/¥/g, "\\")
					.replace(/ /g, " ")
					.replace(/?/g, "~");

				return halfVal;
			};

			$("input.en").change(function() {
				var $this = $(this);
				$this.val(toHankaku($this.val()));
			});

カスタムバリデーション (2) CustomValidatorを追加

カスタムバリデーションのクラスを追加するには、サービスプロバイダーで次のようにクラスを登録します。

追加するクラスの名前や位置はどのようなものでもかまいせん。ここでは、ディレクトリパス app/Services に CustomVaidator.phpを作成し、AppServiceProvider に登録することにします。
続き “カスタムバリデーション (2) CustomValidatorを追加”

カスタムバリデーション(1)Validatorファサードのextend

はじめまして。ブログ主筆khino氏と同じプロジェクトで仕事をしてます。
彼とは別テーマを平行して掲載しますので、これまで順番に読み進めていた方にはちょっと読みにくくなるかもしれませんが、ご容赦ください。

私の最初のテーマはカスタムバリデーションルールです。
このシリーズでは、Validatorファサードの基本的な使い方から始めて、より複雑なルールの定義の仕方や、laravel 5.2で追加された配列定義のカスタムバリデーションまで紹介する予定です。
続き “カスタムバリデーション(1)Validatorファサードのextend”

routesを使いこなす(1)resourceを使う

私が開発・管理しているプロジェクトのひとつは、もともとは過去に人気があったCodeIgniterで書かれたもの。過去2年の間に、それをLaravelのバージョン4で書き直し、さらに更新して現在はLaravelのバージョン5.2となっています。

それゆえに、最初のLaravelを使っての書き換えは、Laravelを勉強しながらの書き換えで、知らないことが多く、Route::controllerを多用していました。
続き “routesを使いこなす(1)resourceを使う”

Top