Help us understand the problem. What is going on with this article?

Laravel+MySQLでTodoアプリのAPIを作った。

More than 1 year has passed since last update.

やりたいこと

  • フロントエンドとバックエンドを切り分けた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があるという意味です。)

画面

スクリーンショット 2019-03-21 17.34.03.png

ソースコード

■ index.html

解説する必要なし

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内に全てのタスクを追加する関数
script.js
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を作成しました。

ソースコードは下に貼っておきます。

ロードマップ

  1. 環境構築(composer, mySQL)
  2. Laravelでのアプリ新規作成
  3. データベース接続
  4. モデルの作成
  5. マイグレーションの定義
  6. マイグレーション
  7. コントローラの作成
  8. ルートの定義
  9. データベースにシードを与える
  10. ローカルサーバを立てる

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しか使っていません。)

このようなデータ構造をデータベースに作成するためにマイグレーションファイルを以下のように編集します。

xxxx_create_todos_table.php
<?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には下のようなコードが書かれています。

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メソッドの中に流し込むデータを記述します。

シーダーファイルを編集する

TodosTableSeeder.php
<?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と打つと、

スクリーンショット 2019-03-21 22.31.47.png

しっかりと動いてくれていることが確認できます!

あとはフロント側が作成したものをgit cloneでもして、このapiを叩いてくれれば正常に動きます。

最後に

フロントエンドとバックエンドを切り離したWebアプリ作成を作ったことがなかったので、いい練習になりました。かなり楽しかったので、すぐに次のアプリ制作にかかります!今後の僕の成長をどうか見届けてください。

参考

自己紹介

冒頭に書くと邪魔になるので最後にひっそりと自己紹介させてください。

名前 綿岡晃輝
職業 大学院生 (2019年4月から)
分野 機械学習, 深層学習, 音声処理
Twitter @Wataoka_Koki

Twitterフォローしてね!

wataoka
専門は機械学習の公平性です
https://twitter.com/wataoka_koki
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした