LaravelとRailsの機能を比較!ルーティング・ORM・DIなどをまとめてみました
こんにちは!開発チームのさいとーです。
近年、PHPのフレームワーク界隈では「Laravel」が盛り上がっていますね。
ラクーンではLaravelを使用したサービスの開発は行ってはいないのですが、
今後の開発の選択肢の1つとして挙げられるようにと、一通りの機能をリサーチしました。
「Ruby on Rails」(以下Rails)と似ているとは聞いていたのですが、実際使ってみると本当に似ていました。
一方で、言語仕様や思想の違いから異なる部分も見えてきました。
ということで今回は「Laravel」と「Rails」を機能毎に比較し、似ている部分、異なる部分をまとめてみました!
※Laravel5.7 と Rails5.2.2 を比較しています。
ルーティング編
まずはルーティングです。
ルーティングの記述
Laravel
- routes/web.php
<?php
Route::get('/', 'HogeController@fuga');
Rails
- config/routes.rb
Rails.application.routes.draw do
get '/', to: 'hoge#fuga'
end
これは、'/'にgetでアクセスが来たときに、hogeコントローラーのfugaメソッドを実行するという処理になります。
片方を知っていたら、もう片方も理解できるような記述ですよね?
getの他にpost,put,patch,deleteなど指定でき、RESTルーティングが一気に定義できる「resource」もLaravel、Rails共に使えます。
ORM編
次にORMです。
それぞれORMフレームワークには、Laravelは「Eloquent」、Railsは「ActiveRecord」という名称がつけられています。
どちらもActive Recordパターンを実装したORMです。
基本的にはModelクラスを生成し、そのModelクラスを使ってメソッドを実行することでCRUD操作ができます。
Modelの生成からCRUDの基本操作まで、簡単に見てみましょう!
Modelの生成
どちらもModelは基本的にコマンドで生成します。(コマンドについては後述します)
ここでは生成された初期状態のModelの定義を見てみます。
※usersというテーブルに紐づくUserモデルを例にしています。
Laravel
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
//
}
Rails
class User < ApplicationRecord
end
言語仕様による記述量の違いはありますが、基本的にこれだけでテーブルのCRUD操作が出来てしまいます。
操作の例を以下に記述します。
Laravel | Rails | |
---|---|---|
create | $user = new User; $user->name = 'saito; $user->save(); |
user = User.new user.name = 'saito' user.save |
read | $users = User::all(); $user = User::find(1); |
users = User.all user = User.find(1) |
update | $user = User::find(1); $user->name = 'tanaka; $user->save(); |
user = User.find(1) user.name = 'tanaka' user.save |
delete | $user = User::find(1); $user->delete(); |
user = User.find(1) user.destroy |
非常に似ていますね。
他にもたくさん書き方はありますが、大体は同じような書き方ができると思います。
このあたりの機能の違いとしては、Laravelには論理削除機能が標準搭載されているということでしょうか。
Railsではgemを入れれば実現はできます。
標準搭載ということはLaravelのバージョンアップによって不意に機能が使えなくなるという事態が起きにくいので、
使う側からすると安心がありますよね。
マイグレーション編
マイグレーションはデータベーススキーマを管理するためのDSLですが、こちらもLaravel、Rails両方に実装されています。
作成や実行はコマンドで行うので、コマンド編で比較します。
ここでは、マイグレーションファイルの中身を見てみましょう。
マイグレーションファイル
先ほどのORM編で扱ったUserモデルと紐づいている、userテーブルを作成するマイグレーションを
Laravel、Railsでそれぞれ記述してみます。
userテーブルの定義は以下とします。
※mysqlでの定義とします
userテーブル定義
カラム名 | データ型 | NULL | Key | Default | 属性 |
---|---|---|---|---|---|
id | int | NO | PRI | NULL | auto_increment |
name | varchar | NO | NULL | ||
varchar | NO | NULL | unique | ||
password | varchar | NO | NULL | ||
comment | text | YES | NULL | ||
create_at | timestamp | NO | NULL |
上記usersテーブルを作成する際の、それぞれのマイグレーションファイルは以下のようになります。
Laravel
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->text('comment')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Rails
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name, null: false
t.string :email, unique: true, null: false
t.string :password, null: false
t.text :comment
t.timestamps null: false
end
end
end
テーブル作成のマイグレーションファイルをコマンド作成すると、
Railsはchangeメソッドがデフォルトで記述されたものが生成され、
Laravelはupメソッドとdownメソッドがデフォルト記述されたものが生成されます。
とはいえ、Railsにもupメソッドとdownメソッドを記述する場合もあり、Laravelのup,downはそれと同じような動作をします。
記述方法はパッと見で似ていますね。
細かい違いですが、
Laravelはプライマリーキーになる'id'カラムの定義を記述しているのに対し、Railsは何も記述していなくても、'id'カラムが作成されます。
Laravelではマイグレーションファイルを生成した時点で'id'は既に定義されているので、スタート地点は同じっちゃ同じですが。
※ちなみに、これらをmigrateすると、Laravelの'id'は「int(10) unsigned」となり、Railsの'id'は「bigint(20)」となるので、実は同じテーブルにはなりません。これらを対象に外部キー制約を付けるときなどは気をつけましょう。
また、LaravelはデフォルトでNOT NULL制約がつくので、NULLを許可するカラムに「nullable()」を付けるのに対し、
Railsは「null: false」を付けたものにNOT NULL制約が定義されるという違いもあります。
DI編
LaravelにはDIの機能が用意されていますが、RailsにはDIの機能は用意されていません。(もちろん自前で実装は可能です)
LaravelのDI機能の使い方を簡単に説明をすると、下記の通りです。
- Laravelアプリケーションの起動処理(サービスプロバイダと呼ばれる)の中で、DIするオブジェクトを格納するコンテナ(サービスコンテナと呼ばれる)へオブジェクトを登録する。
- サービスコンテナからオブジェクトを呼び出す。
今回のテーマは”比較”なので、詳しい説明は省かせてください。
まとめると
Laravel | Rails |
---|---|
サービスプロバイダ、サービスコンテナを を用いて実装 |
機能なし |
となります。
Validation編
LaravelとRailsのバリデーションは結構違います。
何が違うって、まず推奨されている実行タイミングが違います。
バリデーションの記述場所や行うタイミング
Laravel | Rails | |
---|---|---|
記述場所 | Controller(FormRequest) | Model |
推奨実行タイミング | Controllerのメソッド内任意 | Modelのcreateやsave,updateの実行時 |
あくまで推奨実行タイミングなので、実際はどこでバリデーションをしてもいいのですが、
フレームワークとしては、上記表の箇所で実行した方が見た目がスッキリしそうですね。
Laravelの記述場所になっている「FormRequest」ですが、
これを使うとControllerのメソッドに入ったタイミングで既にバリデーションが終わっているという優れものです。
Controllerでバリデーションを行いたくない場合は、FormRequestを使用することをお勧めします。
コード
記述する場所が違うので、コードの見た目も違います。
下記バリデーションを実装するコードを実際に見てみましょう。
バリデーション定義
項目名 | バリデーション |
---|---|
name | 必須,100文字以下 |
必須,100文字以下,メール形式,usersテーブルのemailカラムに同じ値が存在しない | |
password | 必須,6文字以上, 12文字以下 |
Laravel
- UserRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => ['required', 'max:100'],
'email' => ['required', 'max:100', 'email', unique:users],
'password' => ['required', 'min:6', 'max:12'],
];
}
}
Rails
- User.rb
class User < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, presence: true, length: { maximum: 100 }
validates :email, presence: true, length: { maximum: 100 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: true
validates :password, presence: true, length: { in: 6..12 }
end
見た目は違えど、記述量はそこまで変わらないようです。
Laravelはメールアドレスの形式チェックが最初から用意されているように、
バリデーションの種類が豊富なので、なかなか使いやすい印象でした。
コマンド編
LaravelもRailsも、様々な操作をコマンドで行います。
各操作毎にコマンドをまとめてみました。
操作 | Laravel | Rails |
---|---|---|
ルート確認 | php artisan route:list | rails routes |
Controller作成 | php artisan make:controller コントローラー名 | rails generate controller コントローラー名 |
Model作成 | php artisan make:model モデル名 | rails generate model モデル名 |
マイグレーションファイル作成 | php artisan make:migration マイグレーションファイル名 | rails generate migration マイグレーションファイル名 |
マイグレーション実行 | php artisan migrate | rails db:migrate |
シーディング実行 | php artisan db:seed | rails db:seed |
サーバ起動 | php artisan serve | rails server |
REPL | php artisan tinker | rails console |
多少の違いはあれど、やっぱり似ていますね。
LaravelにはあってRailsにはない、サービスプロバイダやフォームリクエストもコマンドで生成します。
操作 | Laravel |
---|---|
サービスプロバイダ作成 | php artisan make:provider サービスプロバイダ名 |
FormRequest作成 | php artisan make:request フォームリクエスト名 |
基本は同じようなコマンドになっているので、何のコマンドなのか想像しやすいですね。
まとめ
LaravelとRailsの基本的な機能を比較してみましたが、記述の仕方などを含め驚くほど似ていましたね。
こうして同じ動作をするコードを並べててみると、Railsの方がコード量が少なく記述的には簡単そうかなという印象を受けましたが、
実際はコマンド生成でひな形は出来上がるので、小さめのアプリケーションならそこまで差はなさそうです。
また、Laravelは今回紹介した機能以外にも、認証系(ユーザ登録/ログイン/ログアウト/パスワード再設定)の機能や、ページネーションを備えており、Railsと比べると、フレームワーク自体に備わっている機能は多いように感じました。
今後ラクーンでLaravelを使った開発が行われるかはわかりませんが、
Homestead(Laravel公式のvagrant box)などを使用すれば、簡単に開発環境の構築ができますので、
一度使ってみてはいかがでしょうか?