5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel / Git】LivewireでTodoリストを実装 ~ひとりチーム開発やってみた~

Posted at

##やりたいこと
今回のテーマは、以下の2つです。

  • LaravelのLivewireの使い方を、CRUD機能を持ったTodoリストを実装しながら解説する
  • Todoリストの実装を、チーム開発を想定したGit flowの流れに沿ってソースコード管理する

Gitの基本的な使い方やチーム開発の運用について学んだので、コミットしてプッシュしてプルリクエストを作成して…というような手順を実践してみたいなと思っていました。

せっかくならGitの練習のためだけのサンプルコードで行うより、実際に何か開発しながらチーム開発を想定してソースコード管理をやってみようということで、Todoリストの実装をGit flowに沿って管理してみます。

##全体の流れ
###Todoリスト作成の手順

  1. Laravelの新規プロジェクト作成
  2. Livewireを使う準備
  3. CREATE機能(新規作成)の実装
  4. READ機能(一覧表示)の実装
  5. UPDATE機能(更新)の実装
  6. DELETE機能(削除)の実装

これらの各機能を実装する度に、下記「Gitでのチーム開発の手順」を繰り返し、ソースコード管理を行なっていきます。

###Gitでのチーム開発の手順

  1. ローカルリポジトリでdevelop(開発)ブランチに入る
  2. リモートリポジトリのdevelopブランチをローカルのdevelopブランチにプルして、ローカルのdevelopブランチを最新の状態にする。
  3. ローカルでdevelopブランチからfeature(機能)ブランチを作り、そこで開発する。
  4. 変更点をローカルでcommitする。
  5. 作業が終わったら、ローカルのdevelopブランチを再度最新の状態にして、featureブランチに developブランチを取り込む。(rebase or merge)
  6. ローカルのfeatureブランチの内容を、リモートリポジトリの同名のブランチへpushする。 
  7. リモートのfeatureブランチからリモートのdevelopブランチへ、プルリクエストを発行する。
  8. コードレビューをしてもらう。
  9. コードレビューが通れば、レビュアーがリモートのdevelopブランチへ featureブランチをmergeする。
  10. リモートのdevelopブランチをローカルのdevelopブランチへ取り込んで、 ローカルのdevelopブランチを最新の状態にする。

##1. Laravelの新規プロジェクト作成
###【開発】 新規プロジェクト作成
まずは以下のコマンドで新規プロジェクトを作成し、プロジェクトディレクトリに移動します。
Livewireを使うために、composerを使ってLivewireをインストールします。

$ laravel new livewire_todo
$ cd livewire_todo

Livewireをインストール
$ composer require livewire/livewire

現在のディレクトリをVScodeで開く
$ code .    

これで、$ php artisan serve とすれば、localhost:8000でlaravelのwelcomeページを表示できるようになっています。

###【Git】 バージョン管理を開始
Gitでの管理を始めます。

通常はプロジェクトに途中から参加することが多いかと思うので、その場合はリモートリポジトリの開発用ブランチ(develop)をローカルにクローンするところから始めることになります。

ですが今回は新しいプロジェクトのためGitHubにリモートリポジトリは無いので、あらかじめGitHubでリモートリポジトリを作成しておきます。

####ローカルリポジトリ作成
GitHubで作成したリモートリポジトリのCode > Clone or downloadより、リポジトリのURLをコピーしておきます。

//ローカルでのGit管理開始・コミット作成
$ git init
$ git add .
$ git commit

//リモートリポジトリとローカルリポジトリを紐づけ、originというショートカット名で登録
$ git remote add origin リモートリポジトリのURL

####SSHで接続する場合
pushする際、GitHubのユーザー名とパーソナルアクセストークンでの認証が必要となります。

GitHub > Settings > Developper settings > Personal access tokens > Generate new token

上記より、パーソナルアクセストークンを発行しておきます。

####リモートリポジトリへプッシュ
GitHub上で作成したリモートリポジトリには、まだ何のコードも保存されていないので、新規作成したLaravelのプロジェクトをmasterブランチにプッシュします。

$ git push origin master
//実行すると、ユーザー名と上記のパーソナルアクセストークンを求められるので入力する。

リモートリポジトリにmasterブランチが作成されました。

Git flowでは原則、masterブランチはリリースに用い、開発はdevelopブランチで行います。
今回はdevelopブランチがまだ無いので、ローカルでdevelopブランチを作成してリモートに登録しておきます。

//developブランチを作成し、developブランチへ移動
$ git checkout -b develop

//リモートにdevelopブランチを登録
$ git push -u origin develop

GitHubで確認すると、画像のようにdevelopブランチが作成されています。
スクリーンショット 2021-10-12 11.39.45.png

これで、Gitでバージョン管理をする準備が整いました。

####開発用のブランチを切る
コードに変更を加える際は、必ず一度developに戻ってからブランチを切り直します
(つい何らかの変更をしてしまいdevelopに戻れなくなった場合は、git stashで作業を待避してからもう一度git checkout developします。)

$ git checkout develop

コードを変更する前に、ローカルのdevelopブランチを最新状態に更新するため、リモートのdevelopブランチをプルします。

//origin上のdevelopブランチを、現在チェックアウトしているブランチ(= develop)に取り込む
$ git pull origin develop

ローカルのdevelopブランチを最新状態にできたら、機能を実装するためのfeatureブランチを作ります。
featureブランチの命名規則はチームに寄りけりかと思いますが、今回はfeature/xxxに統一します。

//ブランチを作り、作ったブランチに移動する
$ git checkout -b feature/start_livewire

ブランチができているか、また作成したブランチに移動できているか確認します。

$ git branch
* feature/start_livewire
  develop 
  master

これで、コードを編集するためのfeatureブランチが準備できました。

##2. Livewireを使う準備
###【開発】 Livewireを使う準備
####ビューの親ファイルの作成
今回のTodoリスト作成において、作成する画面は、

  • 一覧表示
  • 新規作成
  • 更新

の3つです。

この3つの共通部分となるビューの親ファイルを作成します。

$ mkdir resources/views/layouts
$ touch resources/views/layouts/app.blade.php

作成したファイルを編集します。

resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>livewire_todo</title>
    @livewireStyles
</head>
<body>
    @yield('content') 
    @livewireScripts
</body>
</html>

【コードの解説】

  • livewireを使うため、以下の2点を記述します。
    ①headタグ内に@livewireStyles
    ②bodyの閉じタグ直前に@livewireScripts

  • @yield('content')の部分に、後ほど作成するlivewireコンポーネントを埋めることができます。

###【Git】 コミット作成・プルリク作成・次のブランチを切る

  • 作業が終わったら、ローカルのdevelopブランチを再度最新の状態にして、featureブランチに developブランチを取り込みます。
$ git checkout develop
$ git pull origin develop

//featureブランチへ戻る
$ git checkout feature/start_livewire
  • commitを作成します。
//今いるブランチと変更内容を確認
$ git status

//commit作成
$ git add .
$ git commit
  • リモートへpushします。
$ git push origin feature/start_livewire 
  • プルリクエストを作成します。
  1. Githubのリポジトリページを開く。
  2. [Compare & pull request]を押す。
  3. Reviewerを指定し、プルリクエストのメッセージを書く。(base:develop / compare:feature/start_livewire を選択する)
  4. [Create pull request]を押す。

File changedタブを開くと、ファイルの変更差分を見ることができます。
余計なデバッグコードやコメントが書かれたままになっていないか、コミットのもれや誤りが無いかなど、再度確認しておきます。

またFile changedの画面で各行にマウスカーソルを合わせると、"+"ボタンが出てくるので、これをクリックするとレビューを書くことができます。

レビューが通れば、featureブランチをdevelopブランチにmergeします。

  • 次の機能を実装するためのfeatureブランチを切ります。
    また一旦developブランチに戻り、ローカルを最新の状態に更新して、新しくfeatureブランチを切ります。
//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//新しいfeatureブランチを作成
$ git checkout -b feature/todo_create
Switched to a new branch 'feature/todo_create'

##3. CREATE機能(新規作成)の実装
###【開発】 CREATE機能を実装するコンポーネントの作成

Livewireでは$ php artisan make:livewireコマンドでコンポーネントを作成します。

$ php artisan make:livewire todo-create
COMPONENT CREATED  🤙

CLASS: app/Http/Livewire/TodoCreate.php
VIEW:  resources/views/livewire/todo-create.blade.php

コマンドを実行すると、ターミナルに表示されている2つのファイルが作成されます。
作成されたファイルのデフォルトの状態は、以下の通りです。

TodoCreate.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class TodoCreate extends Component
{
    public function render()
    {
        return view('livewire.todo-create');
    }
}

Livewireのコンポーネントには、このようにrender関数があり、一緒に作成されたviewを返します。

todo-create.blade.php
<div>
    {{-- Stop trying to control. --}}
</div>

先述の通り、ビューの親ファイルであるresources/views/layouts/app.blade.phpにlivewireを使うための設定を記述し、@yield('content')を埋め込んであるので、この親ビューを継承する必要があります。

各ファイルを編集していきます。

todo-create.blade.php
<div>
    <form wire:submit.prevent="save">
        <div>
            <p>タイトル</p>
            <input type="text" wire:model="title">
        </div>

        <div>
            <p>内容</p>
            <textarea wire:model="content"></textarea>
        </div>

        <button type="submit">保存</button>
    </form>
</div>

【コードの解説】

  • Livewireでは、wire:イベント.修飾子でイベントをハンドリングすることができます。
    ここではwire:submit.prevent="save"として、formのsubmitが押された時にコンポーネントのsaveメソッド(後述)を実行しています。

  • wire:modelを使用してデータの双方向バインディングを行うことができます。
    Livewireはinput要素のイベントをリッスンし、イベントが発動すると、AJAXリクエストを送信して新しいデータでコンポーネントを再レンダリングします。

TodoCreate.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Todo;

class TodoCreate extends Component
{
    public string $title ="";
    public string $content ="";

    protected array $rules = [
        'title' => 'required|string|max:255',
        'content' => 'required|string|max:255',
    ];

    public function render()
    {
	return view('livewire.todo-create')
            ->extends('layouts.app');
    }

    public function save()
    {
        $this->validate();

        Todo::create([
            "title" => $this->title,
            "content" => $this->content
        ]);

        $this->reset();
    }
}

【コードの解説】

  • Livewireでは、protectedプロパティに配列の$rulesを定義することで、FormRequestのようにバリデーションを実装できます。
  • renderメソッドのビューを返す処理に->extends('layouts.app')として、livewireを使う準備を仕込んだ親ファイルを継承します。
  • todo-create.blade.phpのformにてwire:submit.prevent="save"と呼び出したsaveメソッドを記述しています。
    入力された内容がバリデーションを通れば、データをDBに保存します。
    Livewireではこのようにresetメソッドを使用して各プロパティを初期値に戻すことができます。

####ルーティングの設定

web.php
<?php

use App\Http\Livewire\TodoCreate;

Route::get('todos/create', TodoCreate::class)->name('todos.create');  

localhost:8000/todos/createにアクセスすると、フォームが画面表示されます。

スクリーンショット 2021-10-13 7.29.57.png

###【Git】 コミット作成・プルリク作成・次のブランチを切る
CREATE機能を実装したのでGitにあげます。
繰り返しになるので簡単に書いていきます。

//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//featureブランチへ戻る
$ git checkout feature/todo_create

//今いるブランチと変更内容を確認
$ git status

//commit作成
$ git add .
$ git commit

//リモートへpush
$ git push origin feature/todo_create

プッシュできたら、GitHubにてプルリクエストを作成します。
File changedタブでコードを確認するのも忘れずに。

そして次の機能実装に入るため、featureブランチを切ります。

//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//新しいfeatureブランチを作成
$ git checkout -b feature/todo_read

##4. READ機能(一覧表示)の実装
###【開発】 READ機能を実装するコンポーネントの作成
次に一覧表示の機能を実装します。
まずは下記コマンドでコンポーネントを作成します。

$ php artisan make:livewire TodoList
COMPONENT CREATED  🤙

CLASS: app/Http/Livewire/TodoList.php
VIEW:  resources/views/livewire/todo-list.blade.php

作成された2つのファイルを編集します。

todo-list.blade.php
<div>
    <ul>
        @foreach ($todos as $todo)
        <li>
            <a>{{ $todo->title }}</a>
        </li>
        @endforeach
    </ul>
    <a href="{{ route('todos.create') }}">作成</a>
</div>

【コードの解説】

  • DBに保存されている全てのTodoを$todosで受け取り、foreach文でリスト表示しています。
  • 先に作成した、Todo新規作成画面へのリンクを設置しています。
TodoList.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Todo;

class TodoList extends Component
{
    public $todos;

    public function mount()
    {
        $this->todos = Todo::all();
    }

    public function render()
    {
        return view('livewire.todo-list')
            ->extends('layouts.app');
    }
}

【コードの解説】

  • TodoList.phpファイルの中で、ビューへ受け渡す$todosを取得する必要があります。
    取得にはライフサイクルフックのmountメソッドを利用します。Livewireでは、mountメソッドがコンストラクターの働きをします。

  • 新規作成画面と同様に、レンダリングするviewのレイアウトファイルをextendsで指定しています。

####ルーティングの設定

web.php
use App\Http\Livewire\TodoList;

Route::get('todos', TodoList::class)->name('todos');

localhost:8000/todosへアクセスすると、作成したTodoのタイトル一覧が表示されます。スクリーンショット 2021-10-12 8.37.28.png

###【Git】 コミット作成・プルリク作成・次のブランチを切る
READ機能を実装したのでGitにあげます。

//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop

もしこの時、自分が作業をしている間に別の人がdevelopブランチを更新していたとすると、ローカルのdevelopブランチを最新の状態にした上でfeatureブランチに取り込む必要があります。

//ローカルのdevelopブランチを最新状態に更新
$ git pull origin develop

//featureブランチに取り込む
$ git checkout feature/todo_read
$ git rebase develop

featureブランチに、最新のdevelopブランチの内容を取り込んだ上で、commitを作成します。

//今いるブランチと変更内容を確認
$ git status

//commit作成
$ git add .
$ git commit

//リモートへpush
$ git push origin feature/todo_read

プッシュできたら、GitHubにてプルリクエストを作成します。
File changedタブでコードを確認するのも忘れずに。

そして次の機能実装に入るため、featureブランチを切ります。

//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//新しいfeatureブランチを作成
$ git checkout -b feature/todo_update

##5. UPDATE機能(更新)の実装
###目標の確認
先に、今から作りたいUPDATE機能の完成形を確認しておきます。

  • 一覧画面では、Todoのタイトルをクリックすると、更新画面に遷移できるようにします。
    スクリーンショット 2021-10-12 8.38.03.png

  • 一覧画面から更新したいTodoをクリックすると、選択したTodoが表示され、内容を書き換えて更新することができます。
    スクリーンショット 2021-10-12 8.39.10.png

###【開発】 UPDATE機能を実装するコンポーネントの作成
完成形を確認したところで、更新機能を実装していきます。
まずは下記コマンドで、更新機能用のコンポーネントを作成します。

$ php artisan make:livewire todo-update

COMPONENT CREATED  🤙

CLASS: app/Http/Livewire/TodoUpdate.php
VIEW:  resources/views/livewire/todo-update.blade.php

作成されたファイルを編集します。

todo-update.blade.php
<div>
    <form wire:submit.prevent="update">
        <div>
            <p>タイトル</p>
            <input type="text" wire:model="todo.title">
        </div>

        <div>
            <p>内容</p>
            <textarea wire:model="todo.content">
            </textarea>
        </div>

        <button type="submit">更新</button>
    </form>
</div>

【コードの解説】
内容は、CREATEの画面と非常に似ています。

  • wire:submit.prevent="update"として、formのsubmitが押された時にコンポーネントのupdateメソッド(後述)を実行しています。

  • wire:modelを使用してデータのバインディングを行っています。

TodoUpdate.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Todo;

class TodoUpdate extends Component
{
    public Todo $todo;

    protected array $rules = [
        'todo.title' => 'required|string|max:255',
        'todo.content' => 'require|string|max:255',
    ];

    public function render()
    {
        return view('livewire.todo-update')
            ->extends('layouts.app');
    }

    public function update()
    {
        $this->validate();
        $this->todo->update();
    }
}
```
【コードの解説】

* publicプロパティの$todoを定義していますが、Livewireではこのようにpublicプロパティにタイプヒンティングを用いてEloquentを設定しておくと、Laravelの暗黙的結合のようにルートのパラメータとモデルのインスタンスを自動的に結合させることができます。

試しに$todoをデバッグしてみると、以下の通りです。

```
//一覧画面で、idが4のTodoタイトルをクリックした場合

local.DEBUG: {"id":4,"title":"Todo1","content":"Todo1\u306e\u5185\u5bb9","created_at":"2021-10-12T00:43:36.000000Z","updated_at":"2021-10-12T00:43:36.000000Z"}  
```

* updateメソッドでは、バリデーション通ればDBの内容を書き換えています。

####ルーティングの設定
ルートパラメーターにTodoのデータのidを受け取るようにします。

```web.php
use App\Http\Livewire\TodoUpdate;

Route::get('todos/{todo}', TodoUpdate::class)->name('todos.update');
```

一覧画面から更新画面へのリンクを設定します。
更新したいTodoのタイトルをクリックすると、そのTodoの更新画面へ遷移します。
その際データのidをパラメータとして渡します。

```php:todo-list.blade.php
<div>
    <ul>
        @foreach ($todos as $todo)
        <li>
            <a href="{{ route('todos.update',['todo'=>$todo->id]) }}">
            {{ $todo->title }}
            </a>
        </li>
        @endforeach
    </ul>
    <a href="{{ route('todos.create') }}">作成</a>
</div>
```

これでlocalhost:8000/todosにアクセスすると、下記のようにTodoのタイトルをクリックできるようになっています。

![スクリーンショット 2021-10-12 8.38.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/a14914ec-4079-8e23-f214-c3208c407618.png)


更新したいTodoのタイトルをクリックすると、更新画面へ遷移します。
内容を書き換えて更新ボタンを押すと、リロードされることなくDBのデータが更新されます。
![スクリーンショット 2021-10-12 8.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/f1262428-5694-c239-a591-4718ff0fa284.png)

###【Git】 コミット作成・プルリク作成・次のブランチを切る
UPDATE機能を実装したのでGitにあげます。

```
//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//featureブランチへ戻る
$ git checkout feature/todo_update

//今いるブランチと変更内容を確認
$ git status

//commit作成
$ git add .
$ git commit

//リモートへpush
$ git push origin feature/todo_update
```

プッシュできたら、GitHubにてプルリクエストを作成します。
File changedタブでコードを確認するのも忘れずに。

そして次の機能実装に入るため、featureブランチを切ります。

```
//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//新しいfeatureブランチを作成
$ git checkout -b feature/todo_delete
```

##6. DELETE機能(削除)の実装 
###【開発】 一覧画面に削除ボタンを設置
現在、一覧画面には保存されているTodoのタイトルがリスト表示されています。
このタイトルの横に、削除ボタンを設置します。

今回は新しく作るコンポーネントはありません。既存ファイルを修正します。

```php:todo-list.blade.php
<div>
    <ul>
        @foreach ($todos as $todo)
        <li>
            <a href="{{ route('todos.update',['todo'=>$todo->id]) }}">{{ $todo->title }}</a>
            <button wire:click="delete({{ $todo->id }})">削除</button>
        </li>
        @endforeach
    </ul>
    <a href="{{ route('todos.create') }}">作成</a>
</div>
```
削除ボタンのクリックイベントが発動すると、該当のデータのidを引数として、TodoListコンポーネントのdeleteメソッドが呼び出されます。

このdeleteメソッドをコンポーネントに追加します。

```TodoList.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Todo;

class TodoList extends Component
{
    public $todos;

    public function mount()
    {
        $this->todos = Todo::all();
    }

    public function render()
    {
        return view('livewire.todo-list')
            ->extends('layouts.app');
    }

    public function delete($id)     //追記部分
    {
        Todo::find($id)->delete();
        $this->todos = Todo::all();
    }
}
```
削除ボタンを押したTodoをdeleteメソッドで削除します。

ただしこれだけでは、DBからはデータが消えるもののページ上には削除したTodoも表示され続けるため、再度DBに保存されているTodoを取得しています。

これで、削除ボタンを押せば該当のTodoが削除されるようになりました。

![スクリーンショット 2021-10-12 9.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/132ff432-34bc-726e-949d-c15757bc6797.png)

###【Git】 コミット作成・プルリク作成・次のブランチを切る
DELETE機能を実装したのでGitにあげます。

```
//ローカルのdevelopブランチを最新の状態に更新
$ git checkout develop
$ git pull origin develop

//featureブランチへ戻る
$ git checkout feature/todo_delete

//今いるブランチと変更内容を確認
$ git status

//commit作成
$ git add .
$ git commit

//リモートへpush
$ git push origin feature/todo_delete
```

プッシュできたらGitHubにてプルリクエストを作成します
File changedタブでコードを確認するのも忘れずに


CRUD機能が実装できたのでこれで終わります


<br><br>
##参考記事

https://laravel-livewire.com/

https://readouble.com/livewire/2.x/ja/rendering-components.html

https://reffect.co.jp/laravel/laravel-livewire

https://kobatech-blog.com/livewire/

https://qiita.com/siida36/items/880d92559af9bd245c34#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%A7master%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E6%9B%B4%E6%96%B0%E3%81%8C%E3%81%82%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B

https://qiita.com/shh-nkmr/items/fde133cbdfa5f0092be1

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?