ホーム » Laravelを利用したCRUDアプリケーションの作成方法

Laravelを利用したCRUDアプリケーションの作成方法

データ表示(Read)

 

①テーブルをtailwindcssのサンプルからコピーする

1.下記からテーブルっぽいサンプルを見つけて、コピーする。

https://tailblocks.cc/

2.テーブルより上のsectionとdivタグはコメントアウトする。

3.tailwindcssを適用させるには下記npmコマンドを実行する。
ちなみに、tailwindcssとは、class名に特定のclassを指定することでStyle(デザイン)を当てていくCSSフレームワークです。

1度だけコンパイルする。
$ sail npm run dev

変更があるたびにコンパイルする。
$ sail npm run watch

②テーブルを整える

1. theadのthタグに「名前」「ステータス」などのカラム名を指定する。
2.tbodyのtdタグを、thタグの個数と合わせる。
3.「border-gray-200」が機能するのを確認するために、trタグは2行分追加する。

 

③foreachで囲う

下記みたいな感じで、各カラムをforeachで囲っていきます。(ソースの一部だけ表示させています)

@foreach($books as $book) <tr>
 <td class="text-sm border-t-2 border-gray-200 px-4 py-3">{{ $book->id }}</td>
 <td class="text-sm border-t-2 border-gray-200 px-4 py-3">{{ $book->name }}</td>
 </tr>
@endforeach

④日付形式を変更する

<td class="text-sm border-t-2 border-gray-200 px-4 py-3">{{ Carbon\Carbon::parse($book->read_at)->format('Ynj') }}</td>

⑤適切な長さで文字を区切る

<td class="text-sm border-t-2 border-gray-200 px-4 py-3">{{ Str::limit($book->note, 40, $end='...') }}</td>

⑥ページネーション

1.Controllerを下記にする

$books = Book::paginate(10);

2.books.index.blade.phpに書きを追加する

{{ $users->links() }}

3.ページネーション用のCSSを当てる

sail php artisan vendor:publish --tag=laravel-pagination

※tailwind.blade.phpがデフォルトで適用される。

4.26〜40行目をコメントアウト

5.25行目を変更する

<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-center">

6. ja.jsonを変更する(示すこと → 全 に変更する)

"Showing": ""

7.108行目あたりに下記を追加する

<div class="mt-4">
  <p class="text-sm text-gray-700 leading-5">
    {!! __('Showing') !!}  
    <span class="font-medium">{{ $paginator->total() }}</span>
    件中 
    @if ($paginator->firstItem()) 
      <span class="font-medium">{{ $paginator->firstItem() }}</span>
       
      <span class="font-medium">{{ $paginator->lastItem() }}</span>  
    @else  
    {{ $paginator->count() }}  
    @endif 
        </p>  
</div>

8. navに、flex-colをつける

<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="flex-col flex items-center justify-between">

⑦ダッシュボードをbookにする

1.resources/views/layouts/navigation.bladeの14〜18行目を変更する

<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
 <x-nav-link :href="route('book')" :active="request()->routeIs('book')">  
 {{ __('Book') }}  
 </x-nav-link> 
</div>

2.resouces/views/book/index.bladeの4行目を変更する

{{ __('本の管理') }

3.app/Providers/RouteServiceProvider.phpを変更する

public const HOME = '/book';

 

データの詳細(Detail)

 

①一覧ページに詳細ページへのボタンを追加する

1.theadのtrの部分の最後のthに下記を追加する

<th class="px-4 py-3 title-font tracking-wider font-medium text-gray-900 text-sm bg-gray-100"></th>

2.tbodyのtrの最後の部分にtdを追加する

<td class="border-t-2 border-gray-200 px-4 py-3"> <button onclick="location.href='/book/detail/{{$book->id }}'" class="text-sm shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">詳細</button>
</td>

②詳細ページのMVC設定

1.index.blade.phpを元にdetail.blade.phpをコピーする

2.web.phpのbook配下のグループに下記を追加する

Route::get('/detail/{id}', [BookController::class, 'detail'])->name('book.detail');  

3.bookcontroller.phpに下記を追加する

public function detail($id) 
{ 
    $book = Book::find($id);
    return view('book.detail', [
        'book' => $book, 
    ]); 
}

③詳細ページのMVCデータの割当

1.下記からコードをコピーする
https://tailwindui.com/#product-application-ui

2.bookの情報を割り当てていく<div class=”bg-white shadow overflow-hidden sm:rounded-lg”>

<div class="px-4 py-5 sm:px-6">
        <h3 class="text-lg leading-6 font-medium text-gray-900">本の詳細</h3>
    </div>
    <div class="border-t border-gray-200">
        <dl>
            <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">ID</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->id }}</dd>
            </div>
            <div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">名前</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->name }}</dd>
            </div>
            <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">ステータス</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->status }}</dd>
            </div>
            <div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">著者</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->author }}</dd>
            </div>
            <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">出版</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->publication }}</dd>
            </div>
            <div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">読破日</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{ Carbon\Carbon::parse($book->read_at)->format('Ynj') }}</dd>
            </div>
            <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                <dt class="text-sm font-medium text-gray-500">メモ</dt>
                <dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{$book->note }}</dd>
            </div>
        </dl>
    </div>
</div>

④戻る変更ボタン配置

<div class="flex justify-center">
    <button onclick="history.back()" class="mt-4 mr-4 shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">{{ __('戻る') }}</button> 
    <button onclick="location.href='/book/edit/{{ $book->id }}'" class="mt-4 mr-2 shadow bg-orange-500 hover:bg-orange-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">変更</button> 
</div>

データ編集(edit)

①MVC設定_input配置

1.detail.blade.phpを元にedit.blade.phpをコピーする

2.web.phpのbook配下のグループに下記を追加する

Route::get('/edit/{id}', [BookController::class, 'edit'])->name('book.edit');

3.bookcontrollerに追加する

public function edit($id) 
{ 
    $book = Book::find($id); 
    return view('book.edit', [
        'book' => $book, 
    ]); 
}

4.フォームを作成していく

https://tailwindui.com/components/application-ui/forms/form-layouts

リンクを元にformタグをコピーして、edit.blade.phpの各箇所にコピーしていく(name、idは変える)

<div class="col-span-6 sm:col-span-3"> 
    <input type="text" name="name" id="name" autocomplete="given-name" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md"> 
</div>

②textarea配置

<div class="mt-1">
    <textarea id="note" name="note" rows="3" class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"></textarea>
</div>

③selectbox配置

<select id="status" name="status" autocomplete="country-name" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
    <option>United States</option>
    <option>Canada</option>
    <option>Mexico</option>
</select>

④値を配置

1.下記の様に各inputタグに値を埋め込んでいきます。

value="{{ $book->name }}"

2.textareaは、タグの間に値を入れます。

<textarea>{{ $book->note }}</textarea>

3.textareaのrows=”3″をrows=”5″にします。

⑤selectboxの値を設定

1.定数を定義する

public const BOOK_STATUS_READING = 1;
public const BOOK_STATUS_UNREAD = 2;
public const BOOK_STATUS_DONE = 3;
public const BOOK_STATUS_WANT_READ = 4;

public const BOOK_STATUS_NAME_READING = '読書中';
public const BOOK_STATUS_NAME_UNREAD = '未読';
public const BOOK_STATUS_NAME_DONE = '読破';
public const BOOK_STATUS_NAME_WANT_READ = '読みたい';

public const BOOK_STATUS_OBJECT = [
    self::BOOK_STATUS_READING => self::BOOK_STATUS_NAME_READING,
    self::BOOK_STATUS_UNREAD => self::BOOK_STATUS_NAME_UNREAD,
    self::BOOK_STATUS_DONE => self::BOOK_STATUS_NAME_DONE,
    self::BOOK_STATUS_WANT_READ => self::BOOK_STATUS_NAME_WANT_READ,
];

public const BOOK_STATUS_ARRAY = [
    self::BOOK_STATUS_READING,
    self::BOOK_STATUS_UNREAD,
    self::BOOK_STATUS_DONE,
    self::BOOK_STATUS_WANT_READ,
];

2.selectboxにforeachでbookの値を設定する

@foreach(App\Models\Book::SKILL_STATUS_OBJECT as $key => $value)
    <option value="{{ $key }}" @if($key === $book->status) selected @endif>{{ $value }}</option>
@endforeach

⑥submitの実装

1.book.edit.bladeの13行目あたりに下記を追加する。

<form class="w-full" action="{{ route('book.update') }}" method="POST">
    @csrf
    @method('PATCH')

2.formの閉じタグを下から4番目のdivタグの上に記述する

</form>

3.form内にhiddenでidを記述する

<input value="{{ $book->id }}" name="id" type="hidden">

4.bookcontrollerにupdateを追加する

use Illuminate\Support\Facades\DB;


public function update(Request $request)
{
  try {
        DB::beginTransaction();
        $book = Book::find($request->input('id'));
        $book->name = $request->input('name');
        $book->status = $request->input('status');
        $book->author = $request->input('author');
        $book->publication = $request->input('publication');
        $book->read_at = $request->input('read_at');
        $book->note = $request->input('note');
        $book->save();
        DB::commit();
        return redirect('book')->with('status', '本を更新しました。');
    } catch (\Exception $ex) {
        DB::rollback();
        logger($ex->getMessage());
        return redirect('book')->withErrors($ex->getMessage());
    }
}

⑦csrfについて

@csrf
これは、csrf攻撃を防止するためのセキュリティ対策です

csrfとは?
webを利用した攻撃方法の1つです。

画面表示時に、csrfトークンをlaravelが発行して、その値と、サーバー側で持っているcsrfトークンの値があっているかを検討します。
違う場合は、419エラーになります。

 

⑧httpメソッドについて

get:取得
post:新規追加
put:まるごと更新、一括書き換え
patch:一部を更新
delete:削除

 

データの作成(Create)

①MVCの設定

1.web.phpにルーティングを追加する

Route::get('/new', [BookController::class, 'new'])->name('book.new');

2.bookcontroller.phpにnewを追加する

public function new() 
{ 
    return view('book.new'); 
}

3.edit.blade.phpからnew.blade.phpをコピーする

4.新規作成ボタンを一覧ページに追加する。

<button onclick="location.href='/book/new/'" class="text-base ml-5 shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">新規作成</button> 

5.valueを消していく

6.@method(‘PATCH’)を消す

7.post時のルーティングを追加する

Route::post('/create', [BookController::class, 'create'])->name('book.create');

createとfillable

1.bookcontrollerにcreateを追加

public function create(Request $request) 
    { 
       try { 
           Book::create($request->all()); 
           return redirect('book')->with('status', '本を作成しました。'); 
       } catch (\Exception $ex) { 
           logger($ex->getMessage()); 
           return redirect('book')->withErrors($ex->getMessage()); 
       } 
    }

2.models/book.phpに下記を追加する

protected $fillable = ['name', 'status'];

データの削除(Delete)

1.delete用のルーティングを追加する。

Route::delete('/remove/{id}', [BookController::class, 'remove'])->name('book.remove'); 

2.bookcontrollerにremoveを追加する。

public function remove($id) 
    { 
        try { 
           Book::find($id)->delete(); 
           return redirect('book')->with('status', '本を削除しました。'); 
         } catch (\Exception $ex) { 
           logger($ex->getMessage()); 
           return redirect('book')->withErrors($ex->getMessage()); 
         } 
    }  

3.削除用のボタンを追加する

<div class="absolute inset-y-0 right-0"> 
    <form action="/book/remove/{{ $book->id }}" method="POST"> 
        @csrf 
        @method('delete') 
        <button type="submit" class="mt-4 mr-4 shadow bg-red-500 hover:bg-red-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">削除</button> 
    </form> 
</div>

4.ボタンを囲っているdivにrelative追加する

<div class="flex justify-center relative">

フラッシュメッセージを表示する

1.ui/flash-message.blade.phpファイルを作成して、下記をコピペします。

<div x-show="isOpen" x-data="display()" class="bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded relative" role="alert">
  <span class="block sm:inline">{{ $attributes->get('message') }}</span>
  <span class="absolute top-0 bottom-0 right-0 px-4 py-3">
    <svg x-on:click="close()" class="fill-current h-6 w-6 text-blue-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg>
  </span>
</div>

<script>
function display() {
    return {
        show: true,
        close() { this.show = false },
        isOpen() { return this.show === true },
    }
}
</script>

2.book/index.blade.phpの上の方に下記を追加します。

@if(session('status'))
  <x-ui.flash-message message="{{ session('status') }}"></x-ui.flash-message>
@endif

※期間限定クーポンコード適用中です。