データ表示(Read)
①テーブルをtailwindcssのサンプルからコピーする
1.下記からテーブルっぽいサンプルを見つけて、コピーする。
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('Y年n月j日') }}</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('Y年n月j日') }}</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
※期間限定クーポンコード適用中です。