こんにちは、吉岡(@yoshiokatsuneo)です。
Webサービスを作成する時に迷うのが、「どのWebアプリケーションフレームワークを使うか?」ですよね。
今からWebサービスを作るなら、Ruby on Rails, Django, Laravelが主流となる3大フレームワークかと思われます。
いずれもフルスタックフレームワークと呼ばれるもので、Web開発に必要な機能を一通り揃えていますが、もちろんそれぞれ開発言語、機能、構成などは異なります。
どれも有名なフレームワークなので、名前だけならすべて知っているという人も多いかと思いますが、実際に全てを使ったことがある人は少ないのではないでしょうか。
すでにどれかを使って開発している人も、ほかのフレームワークに触れてみることで、違った角度から開発の考え方や構成などを知ることができるようになります。
とはいえ、単に機能一覧を眺めてみるだけでは、なかなか特徴や雰囲気をつかむことは難しいので、今回は実際にデータベースを使ったToDoリストサービスを作りながら、Ruby on Rails, Django, Laravelの特徴や違いなどを比べてみます。
開発環境を構築しなくてもブラウザ上でWeb開発ができるPaizaCloudを利用しながら進めていきますので、皆さんもぜひ実際にそれぞれのフレームワークに触れながら比べてみてください。
トレンド
まずはRails・Django・Laravelのトレンドについて、Google Trends, Stackoverflow Trendsで見てみましょう。
(Google Trends より)
( Stack Overflow Trends より )
いずれも拮抗していますね。
成熟したRuby on Rails、安定のDjango、伸びているLaravelと言えるかと思います。
比較
それぞれのフレームワークの違いを表にしてまとめてみました。
Ruby on Rails、Djangoはほぼ同時期に発表されていますが、Laravelは比較的新しいフレームワークです。
Ruby on Rails, Laravelはコードの自動生成などの機能が豊富で、コードをほとんど書かなくてもある程度の機能を実現できます。対してDjangoは必要なコードを明示的に書かなければならない部分が多く、魔法的な要素も少ないため、コードの見た目はわかりやすくなります。
|
|
|
|
---|---|---|---|
言語 | Ruby | Python | PHP |
発表 | 2005年12月13日 | 2005年7月21日 | 2011年6月中 |
最新版 (2018年5月時点) |
5.2 | 2.1 | 5.6 |
知名度 | ★★★ | ★★ | ★★ |
機能 | ★★★ | ★★ | ★★★ |
コード自動生成 | ★★★ | ★ | ★★ |
わかりやすさ | ★★ | ★★★ | ★★ |
AI・機械学習 | ★★ | ★★★ | ★ |
事例 | Cookpad, GitHubなど | Instagram, 日経新聞など | STARTUPS.CO, LaravelIOなど |
哲学 | - 設定より規約(CoC) - 繰り返しを避けろ(DRY) |
- 暗黙より明示 - 疎結合と高凝集性 |
- 幸せな開発者が最高のコードを作る - 表現力、エレガント |
開発環境の準備 (PaizaCloud)
3つ分の開発環境を用意するのは大変ですから、今回はクラウド上の開発環境PaizaCloudで開発しましょう。
PaizaCloudでは、ブラウザ上でWeb開発できる環境で、ファイル管理、ファイル編集、ターミナル、Web閲覧などもブラウザ上で利用できるようになっています。もちろんRuby on Rails, Django, Laravelの開発環境もあらかじめ用意されているため、ローカルに開発環境を構築しなくてもすぐにWeb開発を始められます。
それでは、始めていきましょう。まずは、PaizaCloudにログインします。
PaizaCloud Cloud IDEのサイトはこちらです。
メールアドレスなどを入力して登録すると、登録確認メールが送られてきます。GitHubやGoogle(Gmail)ログインを利用すると、ボタン一つで登録することもできます。
次に、開発環境となるサーバを作りましょう。
「新規サーバ作成」ボタンを押して、サーバ作成画面を開きます。
データベースを利用できるように、phpMyAdmin, MySQLをクリックして「新規サーバ作成」ボタンを押します。
3秒程度で、Ruby on Rails, Django, Laravelを使える開発環境がブラウザ上にできあがります。
これで開発環境ができたので、各フレームワークに触れていきましょう!
Ruby on Rails - 設定より規約, 繰り返しを避けろ
言語: Ruby
発表: 2005年12月13日
最新版: 5.2
知名度: ★★★
機能: ★★★
コード自動生成: ★★★
わかりやすさ: ★★
AI・機械学習: ★★
事例: Cookpad, GitHubなど
哲学: 設定より規約(CoC), 繰り返しを避けろ(DRY)
Webアプリケーションフレームワークの王道とも言えるのがRuby on Railsです。
Ruby on Railsが現れるまでは、Webアプリケーションを自分で作ろうと思ったら、簡単なアプリ向けのPHPか、大規模開発向きだけど複雑なJavaか…といった選択肢ぐらいしかなく、個人やスタートアップ企業が簡単にWebアプリケーションを作れるような状況ではありませんでした。
そこに颯爽と登場したのが、「15分で本格的ウェブアプリが作れる」というRuby on Railsです。
Ruby on Railsは、膨大な設定が必要なJavaフレームワークを反面教師に、「繰り返しを避ける(DRY, Don't Repeat Yourself)」「設定より規約(CoC, Convention over Configuration)」という哲学を持っています。
「設定より規約」というだけあって、Ruby on Railsが引いた「レール」に乗っていくだけで、本格的なWebアプリケーションが自然と作れるような仕組みが用意されています。
Ruby on Railsは、Web開発を効率化するための豊富な機能を持ち、MVC、スキャッフォルド、ジェネレータ、マイグレーション、ルーティング、モデル、コントローラ、ORM(Active Record)…といった機能は、それまでのWeb開発手法を大きく変えました。また、オブジェクト指向をスクリプト言語で実現したRubyを使ったことで、スピード感と柔軟性が必要なWeb開発との相性も抜群です。
加えて、Rubyが日本で開発された言語ということもあり、RubyもRuby on Railsも、日本語の情報が豊富です。
Railsはすでに広く使われており市場も成熟していますが、いまだに開発は活発で、最近ではwebpack等、フロントエンド開発向けの機能も取り入れられています。
では、実際にRailsを使って開発してみましょう。
まずは、PaizaCloudの画面左側のターミナルアイコンのボタンをクリックして起動します。
"myapp"プロジェクトを作成します。ここでは、データベースにmysqlを指定しておきましょう。
$ rails new myapp --database=mysql
次に、"rails generate scaffold"で、データベースのマイグレーション、コントローラ、ビュー、モデル、ルーティングを一気に作ります。
$ cd myapp $ rails generate scaffold todo body:text
"rake db:migrate"でデータベースマイグレーションを実行し、データベースにテーブルを作成します。
$ rake db:migrate
"rails server"でサーバを3000番ポートで起動します。
$ rails server
このコマンドだけで完成です。
1行目の"rails new"ではプロジェクトディレクトリと、その中に雛形となるファイルを作成しています。 3行目の"rails generate scaffold"では、データベースのマイグレーション、コントローラ、ビュー、モデル、ルーティングを一気に作ります。 4行目の"rake db:migrate"では、マイグレーションを実行し、データベースにテーブルを作成します。 5行目の"rails server"ではサーバを3000番ポートで起動します。
PaizaCloudで左側の3000と書かれたアイコンをクリックして、URL欄にhttp://localhost/todos/ と入れると、ToDoリストが表示されます。
ファイル管理ビューでファイル構造を見てみましょう。appディレクトリ内に、コントローラ、モデル、ビューが配置されています。
モデルを見てみましょう。実質的にコードはゼロです。ActiveRecordという仕組みで、データベースの構造がオブジェクトの構造に反映されるので、コードの記述が不要になっています。
myapp/app/models/todo.rb:
class Todo < ApplicationRecord end
コントローラを見てみましょう。データの作成、表示、更新、削除(CRUDと呼ばれる)に対応したアクションが定義されています。@変数名"というインスタンス変数がビューから参照できるので、この変数を操作します。
myapp/app/controllers/todos_controller.rb:
class TodosController < ApplicationController before_action :set_todo, only: [:show, :edit, :update, :destroy] # GET /todos # GET /todos.json def index @todos = Todo.all end # GET /todos/1 # GET /todos/1.json def show end # GET /todos/new def new @todo = Todo.new end # GET /todos/1/edit def edit end # POST /todos # POST /todos.json def create @todo = Todo.new(todo_params) respond_to do |format| if @todo.save format.html { redirect_to @todo, notice: 'Todo was successfully created.' } format.json { render :show, status: :created, location: @todo } else format.html { render :new } format.json { render json: @todo.errors, status: :unprocessable_entity } end end end # PATCH/PUT /todos/1 # PATCH/PUT /todos/1.json def update respond_to do |format| if @todo.update(todo_params) format.html { redirect_to @todo, notice: 'Todo was successfully updated.' } format.json { render :show, status: :ok, location: @todo } else format.html { render :edit } format.json { render json: @todo.errors, status: :unprocessable_entity } end end end # DELETE /todos/1 # DELETE /todos/1.json def destroy @todo.destroy respond_to do |format| format.html { redirect_to todos_url, notice: 'Todo was successfully destroyed.' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_todo @todo = Todo.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def todo_params params.require(:todo).permit(:body) end end
ビューを見てみましょう。HTMLにERB記法を用いて、"<% %>"、"<%= %>"でコードを埋め込んでいます。"<% %>"ではRubyのコードを実行します。"<%= %>"では、実行した結果をHTML中に埋め込み、ブラウザ上で表示します。
myapp/app/views/todos/index.html.erb
<p id="notice"><%= notice %></p> <h1>Todos</h1> <table> <thead> <tr> <th>Body</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @todos.each do |todo| %> <tr> <td><%= todo.body %></td> <td><%= link_to 'Show', todo %></td> <td><%= link_to 'Edit', edit_todo_path(todo) %></td> <td><%= link_to 'Destroy', todo, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New Todo', new_todo_path %>
RailsでWebサービスを開発する方法について、詳しくはこちらの記事でも書いています。 paiza.hatenablog.com
Django - 暗黙より明示
言語: Python
発表: 2005年7月21日
最新版: 2.1
知名度: ★★
機能: ★★
コード自動生成: ★
わかりやすさ: ★★★
AI・機械学習: ★★★
事例: Instagram, 日経新聞など
哲学: 疎結合と高凝集性(loose coupling and tight cohesion)、暗黙より明示(Explicit is better than implicit)
Djangoは、Pythonの有名なWebアプリケーションフレームワークです。Pythonは人気のスクリプト言語ですが、特に最近は、機械学習やAIの開発といえばPython…と言ってよいほど浸透しています。
Ruby on Railsのように魔法みたいなコード生成はしてくれないため、最初から自分である程度コードを書く必要がありますが、無駄のないわかりやすいコードを書いてWeb開発をすることができます。
Djangoも、一般的なWebアプリケーション開発に必要な機能はひと通り揃っています。また、機械学習などにもよく使われるPythonの豊富なライブラリを利用できるのが大きな特徴です。
ほかにも、Djangoには管理画面が組み込まれており、データベースの閲覧・編集などの管理画面が簡単に作れるというのも特徴的です。
開発も活発で、最新のDjango2.1は2018年8月にリリースされています。Python開発の場合、よく「Python2系を使うか?Python3系を使うか?」が議論になりますが、Django2では、Python3にのみ対応していくことで終止符が打たれていますので、迷わずPython3が使えます。
では、実際にDjangoを使って開発してみましょう。
まずは、PaizaCloudの画面左側のターミナルアイコンのボタンをクリックして起動します。
$ django-admin startproject mysite $ python3 manage.py startapp todo
Djangoでは、プロジェクトの中に複数のアプリケーションを入れることができるようになっていますので、ここでは"mysite"というプロジェクトの中に"todo"というアプリケーションを作成します。
ジェネレータはないので、ファイルを修正していきましょう。
サイト全体のルーティングでは、todoアプリのパスを設定します。
mysite/urls.py:
from django.urls import include, path from django.contrib import admin from django.views.generic import RedirectView urlpatterns = [ path('todo/', include('todo.urls')), path('admin/', admin.site.urls), path('', RedirectView.as_view(url='/todo/')), ]
アプリケーションのルーティングでは、URLパス"/todo"のアクションで"views.index"関数を呼び出すようにします。
mysite/todo/urls.py:
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
データベース設定では、MySQLの設定を行います。特に設定しない場合はSQLiteが使われます。"pymysql.install_as_MySQLdb()"の追加を忘れないようにしましょう。
mysite/mysite/settings.py:
# Database # https://docs.djangoproject.com/en/2.1/ref/settings/#databases import pymysql pymysql.install_as_MySQLdb() DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mydb', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': '3306', } }
そしてサイト全体の設定で、todoアプリを追加するため、INSTALLED_APPSに'todo.apps.TodoConfig'を追加します。
mysite/mysite/settings.py:
INSTALLED_APPS = [ 'todo.apps.TodoConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
モデルを作成します。モデルクラスでは、データベーステーブルのフィールドの型に対応した変数を定義します。
mysite/todo/models.py:
from django.db import models class Post(models.Model): body = models.CharField(max_length=200)
Djangoでは、このモデルファイルからマイグレーションファイルを自動的に生成します。
$ python3 manage.py makemigrations todo
マイグレーションを実行します。
$ python3 manage.py migrate
ビューも作成します。Ruby on Railsではコントローラと呼ばれている部分になります。Djangoでは、HTMLテンプレート中で利用する変数はrender関数のコンテキストとして明示的に渡します。
mysite/todo/views.py:
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse from django.urls import reverse from .models import Post from .forms import PostForm # Create your views here. def index(request): posts = Post.objects.all() form = PostForm() context = {'posts': posts, 'form': form, } return render(request, 'todo/index.html', context) def create(request): form = PostForm(request.POST) form.save(commit=True) return HttpResponseRedirect(reverse('todo:index')) def delete(request, id=None): post = get_object_or_404(Post, pk=id) post.delete() return HttpResponseRedirect(reverse('todo:index'))
テンプレートファイルも作成します。ここでは、MilligramというCSSフレームワークも使ってみます。
テンプレート中では、Pythonのインデントを使ったコードはそのままでは書けないため、テンプレート用の記法を使います。
Djangoのテンプレートファイルでは"{% %}"、"{{ }}"という記法でテンプレート中に操作を記述したり、値を表示したりすることができます。
レイアウトファイル(base.html)を記述します。
mysite/todo/templates/todo/base.html:
{% load staticfiles %} <!DOCTYPE html> <html> <head> <title>Todo List</title> <!-- CSS And JavaScript --> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> <link rel="stylesheet" href="//cdn.rawgit.com/necolas/normalize.css/master/normalize.css"> <link rel="stylesheet" href="//cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css"> <link rel="stylesheet" href="{% static 'css/todo.css' %}"> </head> <body> <div class="container"> {% block content %} {% endblock %} </div> </body> </html>
表示するHTMLに対応するテンプレートファイル(index.html)を記述します。
mysite/todo/templates/todo/index.html:
{% extends 'todo/base.html' %} {% block content %} <h1>Todo List</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="{% url 'todo:create' %}" method="post"> {% csrf_token %} <!-- Todo Name --> <div class="form-group"> <label for="todo" class="col-sm-3 control-label">Todo</label> <div class="col-sm-6"> {{ form.body }} </div> </div> <!-- Add Todo Button --> <div class="form-group"> <div class="col-sm-offset-3 col-sm-6"> <button type="submit" class="btn btn-default"> <i class="fa fa-plus"></i> Add Todo </button> </div> </div> </form> <!-- Current Todos --> <h2>Current Todos</h2> <table class="table table-striped todo-table"> <thead> <th>Todos</th><th> </th> </thead> <tbody> {% for post in posts %} <tr> <!-- Todo Name --> <td> <div>{{ post.body }}</div> </td> <td> <form action="{% url 'todo:delete' post.id %}" method="post"> {% csrf_token %} <button>Delete</button> </form> </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
Djangoでは、HTMLフォームをフォームクラスとして定義しておき、そこからHTMLの入力フォームを生成することができます。Postフォームのクラスを定義しておきます。
mysite/todo/forms.py:
from django import forms from .models import Post class PostForm(forms.ModelForm): class Meta: model = Post fields = ('body',)
以上で完成です。 開発用サーバを8000番ポートで起動します。
$ python3 manage.py runserver
サーバが8000番ポートで起動します。PaizaCloud画面の左側に"8000"と表示されたブラウザアイコンが表示されます。クリックすると画面が表示されます。
DjangoでWebサービスを開発する方法について、詳しくはこちらの記事でも書いています。 paiza.hatenablog.com
Laravel - 幸せな開発者が最高のコードを作る
言語: PHP
発表: 2011年6月中
最新版: 5.6
知名度: ★★
機能: ★★★
コード自動生成: ★★
わかりやすさ: ★★
AI・機械学習: ★
事例: STARTUPS.CO, LaravelIOなど
哲学: 表現力、エレガント(expressive, elegant syntax), 幸せな開発者が最高のコードを作る(Happy developers make the best code.)
PHPにおいては、RubyにおけるRailsのような圧倒的なフレームワークはなく、CakePHP、Zend Framework、Code Igniter、Symfony…といったさまざまなフレームワークが群雄割拠していました。
その中で、比較的新しいフレームワークとして登場したLaravelは、Railsをはじめとするほかのフレームワークのよいところを取り入れることで、先進的で豊富な機能の搭載を実現しました。
コミュニティ運営が活発なこともあってか、Laravelは知名度をぐんぐん広げ、一気に有名フレームワークの仲間入りをしています。Google Trendsを見ても、PHPフレームワークの中ではLaravelの伸びが圧倒的であることがわかります。
(Google Trends より)
PHPはもともとHTMLテンプレートとして作られた言語で、Web開発向きの言語としては最も古いものの一つです。開発自体は比較的簡単に始めることができますが、コードは複雑でわかりにくいものになってしまいがちです。
ただ、Laravelの場合はオブジェクト指向やパッケージマネージャ(composer)といった最新の機能を使い、さらにMVC、ジェネレータ、モデル、マイグレーション、ORM(Eloquent)、テンプレートエンジン(Blade)、DIといった機能も取り入れることで、わかりやすいコードを書きつつ本格的なWebアプリケーションが作れるようになっています。
PHPは、CMSやWordPressの開発にも採用されるなど広く使われていますが、LaravelではこのPHPを使ったWeb開発の資産やノウハウを流用できるというのも魅力のひとつです。
では、実際にLaravelを使って開発してみましょう。
まずはPaizaCloudで、ターミナルアイコンをクリックしてコマンドを入力します。
"myapp"という名前でプロジェクトを作成します。
$ laravel new myapp $ cd myapp $ php artisan serve
データベースを作成します。
$ mysql -u root create database mydb;
データベース設定ファイルを編集します。PaizaCloudのファイル管理ビューで右クリックから「隠しファイルを表示」を選択し、ドット(".")で始まるファイルを表示しておきます。
myapp/.env:
DB_DATABASE=mydb DB_USERNAME=root # DB_PASSWORD=secret
モデル、コントローラ、マイグレーションファイルを一気に作成します。
$ php artisan make:model Task -m -c -r
マイグレーションファイルに"$table->string('name');"を追加することで、データベーステーブルのnameフィールドを追加します。
database/migrations/2018_xx_xx_xxxxxxxx_create_tasks_table:
public function up() { Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); }
マイグレーションを実行します。
$ php artisan migrate
ルーティングファイルを編集し、"GET /tasks", "POST /tasks", "DELETE /tasks/{id}"に対応したTaskController内のアクションを呼び出すようにします。
routes/web.php:
Route::get('/', function(){return redirect('/tasks');}); Route::get('/tasks', 'TaskController@index'); Route::post('/tasks', 'TaskController@store'); Route::delete('/tasks/{id}', 'TaskController@destroy'); \URL::forceScheme('https');
ページを表示する時に呼ばれるアクションをコントローラとして記述します。Eloquentモデルを使うことで、テーブル内のフィールドを"$task->name"のように、オブジェクトのインスタンス変数として参照できます。
app/Http/Controllers/TaskController.php:
<?php namespace App\Http\Controllers; use App\Task; use Illuminate\Http\Request; class TaskController extends Controller { public function index() { $tasks = Task::all(); return view('tasks', ['tasks' => $tasks]); } public function store(Request $request) { $task = new Task; $task->name = request('name'); $task->save(); return redirect('/tasks'); } public function destroy(Request $request, $id, Task $task) { $task = Task::find($id); $task->delete(); return redirect('/tasks'); } }
ビューファイルを作成します。
PHP自身はもともとテンプレートエンジンですが、記述が冗長でわかりにくくなってしまいがちな部分があります。
ただ、LaravelではBladeというテンプレートエンジンを用いることで、HTML中に操作を記述したり、値を表示したりといったことが簡潔にできるようになっています。
モデルファイルを見てみましょう。
app/Task.php:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // }
…といってもModelクラスを拡張したクラスがあるだけで、中身はカラです。
LaravelではEloquentというORMを利用することで、データベーステーブル上のカラムの値を、モデルオブジェクトからプロパティ名を使って参照できるようになっています。
以上で完成です。
サーバを動かしてみましょう。
$ cd ~/myapp $ php artisan serve
サーバは8000番ポートで起動しています。PaizaCloud画面の左側の"8000"と書かれたブラウザアイコンをクリックすると、作成したWebアプリが表示されます。
LaravelでWebサービスを開発する方法について、詳しくはこちらの記事でも書いています。 paiza.hatenablog.com
まとめ
というわけで、Ruby on Rails・Django・Laravelの機能を比較しつつ、実際にデータベースを使ったWebアプリケーションを作ってみました。それぞれ特徴がありますが、いずれも機能豊富なWebアプリケーションフレームワークです。
今回の記事のようにPaizaCloudを使うと、面倒な環境構築なしで、ブラウザだけでさまざまなフレームワークを使ってみることができます。書籍や記事を読むだけよりも、実際に触ってみることで雰囲気や特徴などがつかめるようになるので、ぜひ使ってみてください。
「PaizaCloud」は、環境構築に悩まされることなく、ブラウザだけで簡単にウェブサービスやサーバアプリケーションの開発や公開ができます。
「paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。
そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。