やりたいこと
- フロントエンドとバックエンドを切り分けたTodoアプリ制作。
- 自分がバックエンド、友達がフロントエンド。
- ちゃんとデータベースを使う。
- データの通信はJSON形式。
使ったもの
試行錯誤を重ね、以下のものを使用することにしました。
- フロントエンド
- HTML
- JS
- バックエンド
- Laravel
- MySQL
開発環境
- フロントエンド
- Window10のなんか
- バックエンド
- macOS Mojave 10.14.3
- PHP 7.1.23
- Laravel 5.8.5
- MySQL 8.0.15
フロントエンド側
HTMLとJSのみで必要最小限の実装を行いました。
ディレクトリの構成
- todo-front
- index.html
- static / js / script.js
(jsの部分は階層構造をmarkdownで書ききれなかっただけです。staticの中のjsの中にscript.jsがあるという意味です。)
画面

ソースコード
■ index.html
解説する必要なし
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ToDo</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<h2>ToDo</h2>
<hr>
<div class="content">
<div class="post_form">
Taskを追加:
<input type="text" id="new_task">
<input type="submit" value="送信" onclick="postText();">
</div>
<br>
<div>Task一覧:
</div>
<div>
<ul id="list">
</ul>
</div>
</div>
</body>
<script src="./static/js/script.js"></script>
</html>
■ script.js
関数名 | 説明 |
---|---|
getText | 全てのタスクをくれ。って言う関数 |
postText | 一つのタスクをSQLに追加してね。終わったら全てのタスクをくれ。って言う関数 |
showTask | HTML内に全てのタスクを追加する関数 |
var url = "http://127.0.0.1:8000/api/todos";
var tasks = [];
function getText(){
$.ajax({
type: "GET",
url: url,
datatype: JSON,
cache: false,
contentType: false,
processData: false
}).done(function(response){
tasks = [];
for(var i=0; i<response.length; i++)
tasks[i] = response[i].memo;
showTask();
}).fail(function(){
alert('Task受信に失敗しました')
});
}
function postText(){
const new_task = $("#new_task").get(0).value;
if(new_task == ""){
alert("入力してください");
return;
}
console.log(new_task);
var data = {
memo: new_task,
status: 0
};
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
datatype: JSON,
cache: false,
contentType: false,
scriptCharset: 'utf-8'
}).done(function(response){
tasks = [];
for(var i=0; i<response.length; i++)
tasks[i] = response[i].memo;
clearText();
showTask();
}).fail(function(){
alert('Task送信に失敗しました')
});
}
function showTask(){
$("#list").empty('');
var fragment = document.createDocumentFragment();
for(var i=0; i<tasks.length; i++){
var $li = document.createElement('li');
var task = document.createTextNode(tasks[i]);
$li.appendChild(task);
fragment.appendChild($li);
}
$("#list").get(0).appendChild(fragment);
}
function clearText(){
$("#new_task").get(0).value = "";
}
function init(){
getText();
}
init();
バックエンド側
Laravelを使用してAPIを作成しました。
ソースコードは下に貼っておきます。
ロードマップ
- 環境構築(composer, mySQL)
- Laravelでのアプリ新規作成
- データベース接続
- モデルの作成
- マイグレーションの定義
- マイグレーション
- コントローラの作成
- ルートの定義
- データベースにシードを与える
- ローカルサーバを立てる
1.環境構築
composer
mac使いなので楽にbrewでinstallした。
brew install composer
MySQL
mac使いなので楽にbrewでinstallした。
brew install mysql
2. Laravelでのアプリ新規作成
composer create-project laravel/laravel --prefer-dist todo-api
最後のtodo-apiの部分はプロジェクト名です。
これを実行すると、でっかいプロジェクトを生成してくれます。ちょっとビビりましたが、適当に解説記事や公式ドキュメントを読みながら把握していきました。
今回はAPIを作るだけですので、viewなど必要のないファイルだらけです。次からはslimやlumenのようなマイクロフレームワークを使おうかなと思いました。
ただ、この時点でかなりの量のLaravelに関する記事やドキュメントを読み通しましたので、このまま突っ走ることにしました。
3. データベース接続
今回はMySQLを使用することにしました。
MySQLコマンドラインツールを起動
mysql -u root
現在あるデータベースを確認する
mysql> show databases;
本アプリ用のデータベースを作成し、使用する
mysql> CREATE DATABASE todos;
mysql> use todos;
Laravel側から接続する
.envファイルのDB部分を以下のように変更する。
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=todos
DB_USERNAME=root
DB_PASSWORD=
4. モデルの作成
php artisan make:model Todo -m
これでdatabase/migrations/にxxxx_create_todos_table.phpが作成されます。このファイルにデータベースを作成する設計書を記述していきます。(この時点ではデータベースには何も作成されていない
。)
5. マイグレーションの定義
データ構造はとてもシンプルで、
- Todoクラス
- id (int)
- title (string)
- memo (string)
- status (int)
です。
(Todoを完了したのかどうかをstatusで管理しようとか色々考えていたのですが、結局このうちのmemoしか使っていません。)
このようなデータ構造をデータベースに作成するためにマイグレーションファイルを以下のように編集します。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTodosTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('memo')->nullable();
$table->smallInteger('status')->default(0);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('todos');
}
}
6. マイグレーションの実行
先ほど作成したマイグレーションファイルを実行します。
php artisan migrate
7. コントローラの作成
以下のコマンドでコントローラを作成します。
php artisan make:controller TodoController --api --model=Todo
これでapp/Http/ControllersにTodoController.phpが作成されています。
そのファイルを編集して、下のようにします。
<?php
namespace App\Http\Controllers;
use App\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return Todo::all();
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = json_decode(file_get_contents('php://input'), true);
$todo = new Todo;
$todo->memo = $data['memo'];
$todo->save();
return Todo::all();
}
/**
* Display the specified resource.
*
* @param \App\Todo $todo
* @return \Illuminate\Http\Response
*/
public function show(Todo $todo)
{
return $todo;
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Todo $todo
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Todo $todo)
{
$todo->title = $request->title;
$todo->status = $request->status;
$todo->memo = $request->memo;
return $todo;
}
/**
* Remove the specified resource from storage.
*
* @param \App\Todo $todo
* @return \Illuminate\Http\Response
*/
public function destroy(Todo $todo)
{
$todo->delete();
}
}
8. ルートの定義
さて、さてさて。
Laravelを勉強していて一番感動した所にやっと来ました。ルーティングです。
先ほどのコントローラの部分はartisanで生成した時点で関数を用意してくれていました。その関数の中身を実装するのが僕の役目でした。apiが叩かれた時にどの関数を実行するかを振り分ける作業をするわけですが、元からroutes/api.phpには下のようなコードが書かれています。
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
このファイルの一番下に、、、
Route::apiResource('todos', 'TodoController');
ヒョイっと一行追加するだけで、
method | URI | action |
---|---|---|
GET | /todos | index |
GET | /todos/{id} | show |
POST | /todos | store |
PUT | /todos/{id} | update |
DELETE | /todos/{id} | destroy |
というルーティングが定義できるのです!!!
もう一度言います。
僕の行ったことは、
- コントローラを作成する。(コマンドでindex, show, store, update, destroy関数は自動生成してくれる。)
- それぞれの関数を編集する。
- ルーティングに一行加える。
だけです!!!
9. データベースにシードを与える
LaravelにはSeederという機能があり、実験的にデータベースにデータを入れたいときに活用できる。
シーダーファイルを作る
php artisan make:seeder TodosTableSeeder
これでdatabase/seeds
の中にTodosTableSeeder.php
というファイルができます。そのファイルのrunメソッドの中に流し込むデータを記述します。
シーダーファイルを編集する
<?php
use Illuminate\Database\Seeder;
class TodosTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('todos')->insert([
['memo' => 'aaaa', 'status' => 0],
['memo' => 'bbbb', 'status' => 0],
['memo' => 'cccc', 'status' => 0]
]);
}
}
ちなみに、runメソッドの一行目に
DB::table('todos')->truncate();
と書くと、今までに作ったデータベースを綺麗にすることができます。
シーダーファイルを実行する
php artisan db:seed --class=TodosTableSeeder
これでデータベースにデータが流し込まれたはずです。
10. ローカルサーバを立てる
下のコマンドでローカルサーバが立ちます。
php artisan serve
適当にブラウザでhttp://<localhost名>/api/todos
と打つと、

しっかりと動いてくれていることが確認できます!
あとはフロント側が作成したものをgit cloneでもして、このapiを叩いてくれれば正常に動きます。
最後に
フロントエンドとバックエンドを切り離したWebアプリ作成を作ったことがなかったので、いい練習になりました。かなり楽しかったので、すぐに次のアプリ制作にかかります!今後の僕の成長をどうか見届けてください。
参考
- 環境構築
- Laravel
自己紹介
冒頭に書くと邪魔になるので最後にひっそりと自己紹介させてください。

名前 | 綿岡晃輝 |
---|---|
職業 | 大学院生 (2019年4月から) |
分野 | 機械学習, 深層学習, 音声処理 |
@Wataoka_Koki |
Twitterフォローしてね!