こんにちはみなさん
Laravelは割と自由に書かせてくれるので、今作っている分を実装するには楽なんですが、全体として実装が微妙にブレることがあるので、後々変な不整合が出そうで怖くなります。
CakePHPはそのあたりをルールによって縛っていて、よりコード量が少なくなるほど彼らの提供する正しい実装になるようになっています。
まあ、何が言いたいかって言うと、自分の実装をあまり信用していないので、ある程度自動生成してもらえれば、やりやすいんじゃないかなぁって思った次第。
そんなわけで、Laravelで大事なコマンドである make:model
に注目していきます。
三行で
- Laravel artisan コマンドの make:model でモデルを自動生成
- make:model のオプションで必要なファイルのガワを作れる
- モデルの名前空間を変えたい場合はコマンド自作して上書き
make:model の基本
make:model
はEloquent
モデルの自動生成コマンドです。
php artisan make:model Post
これを実行すると、app直下に以下のファイルが生成されます。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
//
}
app直下に入れたくない場合は名前空間含めて名前を付ける必要があります。
php artisan make:model Entities/Post
これで、app/Entities配下にPost.phpが生成されます。名前空間も合わせて作られています。
make:model のオプションで付随したファイルを自動生成
モデルというのは、プロダクトの中心にあるものですので、こいつをもとにしていろんな処理を作っていくことになると思っています。モデルを作ったら、そいつを取得するためのコントローラやデータベースの作成、テスト用のファクトリーとかを作っていくことになるわけですが、そういうのはモデルと一緒に作ってしまえばいいのではと考えるわけです。
どんなオプションがあるかは -h
オプションで見れます。
php artisan make:model -h
Description:
Create a new Eloquent model class
Usage:
make:model [options] [--] <name>
Arguments:
name The name of the class
Options:
-a, --all Generate a migration, factory, and resource controller for the model
-c, --controller Create a new controller for the model
-f, --factory Create a new factory for the model
--force Create the class even if the model already exists
-m, --migration Create a new migration file for the model
-p, --pivot Indicates if the generated model should be a custom intermediate table model
-r, --resource Indicates if the generated controller should be a resource controller
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
まあ、all使えばいいのでは、ってことです。
-m: マイグレーションを一緒に作る
EloquentモデルはORMなので、たいていなにかのテーブルとひも付きます。また、Eloquentモデルは、テーブル名の指定がない場合は自身の名前の複数形のテーブルを参照するのですが、そのあたりを考えたくない場合は、その規約にあった名前のテーブルのマイグレーションを予め作っておくのが吉です。
というわけで、マイグレーションを一緒に作ります。
# php artisan make:model Post -m
Model created successfully.
Created Migration: 2020_01_19_073425_create_posts_table
すると、以下のようなファイルができています。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
本当はDjangoみたいにモデルの方でデータ型を指定したいところですが。。。こっちのほうがいい部分もあるので、一概にどっちがいいとは言えませんな。
-f: ファクトリーを一緒に作る
モデルを作ったら、そいつのファクトリーを一緒に作っておくのがマナーってやつですよね(????)。
それならいっそ、モデルと一緒に作っちゃえばいいでしょう。
# php artisan make:model Post -f
Model created successfully.
Factory created successfully.
これで次のファイルができています。
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\Post;
use Faker\Generator as Faker;
$factory->define(Post::class, function (Faker $faker) {
return [
//
];
});
まあ、ただの空箱ですが。
-c: コントローラを一緒に作る
Webアプリは、極論、Webのリソースに対する操作になりますので、中心となるモデルをどんなふうにいじるかを決定するコントローラを一緒に作る場合があります。
それなら、やっぱり一緒に作っちゃうのが良いのではってことになります。
# php artisan make:model Post -c
Model created successfully.
Controller created successfully.
これででいるわけですが。。。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
//
}
もう少し、こう、scaffolding じみた感じに色々作ってくれていいのだが。。。
-r: リソースコントローラも一緒に作る
-c
オプションだと、ただの空箱コントローラが作られましたが、-r
オプションを付ければリソースコントローラを作ることができます。
fully.
root@334281a14de2:/var/www# php artisan make:model Post -r
Model created successfully.
Controller created successfully.
コンソールの結果は何も変わりませんが、出力結果が変わります。
<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
//
}
}
ここまで作ってくれるのなら、デフォルトのコードも作ってくれればいいのに。。。
もちろん、これを作っただけでは動かないので、あとでrouter
に登録するのを忘れないようにしましょう。
Route::resource('post', 'PostController');
で行けるはずです。
-a: -m, -f, -r 全部入り
ここまでやってきたやつを全部入れるのなら、-a
オプションが便利です。
# php artisan make:model Post -a
Model created successfully.
Factory created successfully.
Created Migration: 2020_01_19_081214_create_posts_table
Controller created successfully.
モデル名さえ決めていれば、残りのファイルは一括自動生成!
これが楽だと思います。
もちろん、プロダクトが成長していき、単純な構造ではすまなくなってしまえば、このようにコントローラまで一緒に全部作るというのは厳しいこともあるかもですが、仮説検証のようなとりあえず試してみたいというときであればこれで良いのではと思います。
初期の名前空間を変える
make:model
はモデル名を指定すると、そのままapp直下にクラスファイルが生成されるわけですが、これがLaravelの教えだとしても、個人的にはモデルにそれなりの名前空間をつけておきたいところ。
例えば、モデルは必ずApp\Entities
に入れるというのであれば、毎回モデルを作るごとにEntities\ModelName
って入力するのは面倒です。
なので、こんなコードをapp/Console/Commands
配下に入れます。
<?php
namespace App\Console\Commands;
use Illuminate\Foundation\Console\ModelMakeCommand;
class MyMakeModel extends ModelMakeCommand
{
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Entities';
}
}
あとは、普通にphp artisan make:model ModelName
というコマンドを叩くだけで、先に設定した名前空間付きのモデルが作られます。
なお、-r
や-f
などで、リソースコントローラやファクトリを一緒に作った場合は、モデルの名前空間もちゃんと踏襲してくれていますので、おすすめです。
まとめ
というわけで、Laravelにおけるモデルの自動生成のちょっとした使い方を見てみました。自分でやってて、割と発見があったかなぁという印象です。
機械的に作れるところはとっとと自動生成しちゃって、肝心のモデルの設計を頑張ろうってところでしょうか。
今回はこんなところです。