Laravel5で開発を始める前に行っていることをまとめました。
各設定ファイルのディレクトリ構成のカスタマイズや、Laravelを拡張するためのコードの配置場所を設定しています。
この方法がスタンダードということはありませんが、開発チームで予め標準化しておくと、保守性も向上するのではないでしょうか。
ここではデータベースのマイグレーションやカスタムミドルウェアの設定、Javascript/CSSのビルドなどは割愛しています。
環境
- OS: osx10.11.4
- PHP: PHP5.6.x
- Laravel: 5.2.31
Laravelインストール
現時点では、5.2.31がリリースされています。
$ composer create-project --prefer-dist laravel/laravel
$ cd laravel
$ ./artisan --version
Laravel Framework version 5.2.31
gitリポジトリ作成
gitリポジトリを作成します。
$ git init
$ git add .
$ git commit -m 'initial commit'
動作確認
簡単に動作を確認します。
実際の開発時も、PHPビルトインサーバを利用することが多いです。なんといっても手軽です。
$ php -S 0.0.0.0:8080 -t public/
もちろん、Vagrantでステージングサーバを構築して、試験することも併用しています。
また、プロダクションサーバへのデプロイメントもVagrantで作成したステージングサーバで調整・検証しています。
プロビジョニングには、Ansibleを利用しています。
今後は、LaravelアプリもDockerコンテナ化して、瞬時にデプロイできるように考えています。
プロジェクトネームスペースの定義
プロジェクトの固有のソースコードの配置先を変更し、ネームスペースを分離しています。
まず、プロジェクトのソースコードディレクトリを作成します。
ここではHttpディレクトリだけ作成していますが、概ねLaravelのapp/のディレクトリ構成をそのまま、プロジェクトのネームスペースで作成しています。
editorはお好きなものに置き換えてください。筆者は、atomエディタで開発しています。
ディレクトリを作成したらpsr4でオートロードできるようにcomposer.jsonに追加します。
$ mkdir -p srcs/app/Http
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Project\\": "srcs/app/"
}
},
その後、オートロードファイルを再生成します。
$ composer dump-autoload
Generating autoload files
autoload_classmap.phpを参照すれば、追加されていることが確認できます。
'Project\\' => array($baseDir . '/srcs/app'),
routes.phpの移動
通常、app/Http/routes.phpに配置されていますが、よく参照・変更するファイルなので、プロジェクトのHttpへ移動します。
好みの問題でもありますから、必須というわけではありません。
$ cp app/Http/routes.php srcs/app/Http
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
// require app_path('Http/routes.php'); routes.phpのロケーションを変更します。
require base_path('srcs/app/Http/routes.php');
});
}
コンフィグレーションの設定
日本語ファイルを英語のものから作成しておきます。多国語対応する必要がなくても、メッセージの保守性を向上するために言語ファイルに全てのメッセージを定義しています。
$ cp -a resources/lang/en resources/lang/ja
次に、アプリケーションのコンフィグレーションを設定します。
url、タイムゾーン、ロケールの設定とプロジェクト固有のサービスプロバイダを一つ以上設定しています。
'url' => 'http://www.project.com',
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
'fallback_locale' => 'ja',
'providers' => [
...
Project\Providers\AppServiceProvider::class,
]
サービスプロバイダの定義
プロジェクト固有のサービスプロバイダには、ストレージパスの設定や、bladeで利用するカスタムなディレクティブ、フォームバリデーションで利用する共通のバリデータなどを定義しています。
まず、bootメソッドでストレージパスを変更しています。いままではシンボリックリンクでデプロイごとのストレージが変わらないようしていましたが、今後Dockerコンテナ化も考慮して、任意のパスに変更するようにしました。
注記
このタイミングでstorage_path()を変更しても、storage/framework/{cache,sessions,views},storage/logsのパスには反映されないことがわかりました。
適切かどうか不明ですが、bootstrap/app.php
で$app
を返す前に、$app->useStoragePath('/tmp/storage')
してやると反映されました。
その後、Bladeのカスタムディレクティブやカスタムバリデータを定義しています。数が多くなれば、それぞれ別のプライベートメソッドへ移動したり、別のサービスプロバイダを作成します。
サンプルとして、日付をフォーマットするディレクティブ、電話番号をバリデートするものを用意しました。
registerメソッドでは、サービスインタフェースに対して、DI(Dependency Injection)したいクラスを設定しています。コントローラのコンストラクタの引数にインタフェースをタイプヒンティングしておけば、ここでbindされたクラスインスタンスが自動的にインジェクションされます(コンストラクタインジェクション)。
$ mkdir srcs/app/Providers
<?php namespace Project\Providers;
use Blade;
use Validator;
use Log;
use Input;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
app()->useStoragePath('/tmp/storage');
Blade::directive('date', function($expression) {
return "$expression ? (new DateTime{$expression})->format('Y/m/d') : trans('app.none')";
});
Validator::extend('tel', function($attribute, $value, $parameters, $validator) {
$value = mb_convert_kana($value, 'n', 'utf-8');
return preg_match("/^[0-9]+$/u", $value);
});
}
/**
* Register any application services.
*
* This service provider is a great spot to register your various container
* bindings with the application. As you can see, we are registering our
* "Registrar" implementation here. You can add your own bindings too!
*
* @return void
*/
public function register()
{
$this->app->bind(
\Project\Services\ServiceContract::class, \Projet\Services\Service::class
);
}
}
public function __construct(ServiceContract $service) // Serviceクラスのインスタンスがインジェクトされる。
{
$this->service = $service;
}
ストレージパスが変更できているかtinkerで確認します。
tinkerはREPL(Read-Eval-Print Loop)と呼ばれるインタラクティブシェルのようなものです。Laravel環境で、小さなコードをインタラクティブに動作させることができます。ちょっとしたデバッグやテストに最適で便利です。
$ ./artisan tinker
Psy Shell v0.7.2 (PHP 5.6.19 — cli) by Justin Hileman
>>> storage_path()
=> "/tmp/storage"
>>>
個人的な小さなプロジェクトなら、直接app/にファイルを追加していってもよいのですが、チームで継続して開発するなら、予めこのようなプラクティスを決めておくと、開発効率や保守性が向上するのではないでしょうか。何かの参考になれば、幸いです。