Laravel CRUD
Aug 23, 2020
PHP
Laravel
Validation
Database
crud
Introduction
I will make CRUD with Laravel.
Do not do
- Does not deal with authentication.
- I will not create the function realized by JavaScript such as confirmation before deletion this time.
What to make
Action | Screen presence | Content |
---|---|---|
index | screen available | list display screen |
create | Has screen | New entry form |
store | No screen | Additional processing (create registration button) |
show | Has screen | Show details |
edit | With screen | Change form (with existing values) |
update | No screen | Change process (edit update button) |
destroy | No screen | Delete process (show delete button) |
index (list) ┳ create (new creation screen) ━ store (new save)
┗ show (detailed display) ┳ edit (edit screen) ━ update (overwrite save)
▼ ┗ destroy (delete)
Preparation
Create table
Table to create
id | name | telephone | created_at | updated_at | ||
---|---|---|---|---|---|---|
ID | Name | Phone Number | Email Address | Created Date | Updated Date |
Creating model and migration files
php artisan make:model Models/Member -m
A migration file is also created with the -m option.
The following two files will be created. app\Models\Member.php database\migrations\xxxx_xx_xx_xxxxxx_create_members_table.php
Editing the migration file
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->id();
$table->string('name',20);
$table->string('telephone',13)->nullable()->unique();
$table->string('email',255)->nullable()->unique();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('members');
}
Run migration
php artisan migrate
The members table is created.
Insert record
Put a record in the members table for display confirmation.
Create seeder file
php artisan make:seeder MembersTableSeeder
database\seeds\MembersTableSeeder.php is created.
Edit seeder file
public function run()
{
DB::table('members')->insert(
[
[
'name'=>'Yamada',
'telephone'=>'xxxx-xxxxx',
'email'=>'[email protected]',
'created_at'=>now(),
'updated_at'=>now(),
],
]
);
}
Registration with Database Seeder
Register the created MembersTableSeeder in DatabaseSeeder.
public function run()
{
$this->call(MembersTableSeeder::class);
}
Run seeder file
php artisan db:seed
The record is entered in the members table.
Creating a #### controller
php artisan make:controller MemberController --resource
With the –resource option, a template of 7 actions is prepared in advance.
Edit #### controller Templates of 7 actions are prepared in advance.
//add to
use Illuminate\Support\Facades\DB;
use App\Models\Member;
public function index()
{
//
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
//
}
List screen (index)
Add routing
Add a route for accessing /member/index.
// Addition
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
});
Edit ### controller Fetch data from the members table and pass it to view.
public function index()
{
// store name, telephone, email from member table in $members
$members=DB::table('members')
->select('id','name','telephone','email')
->get();
//return view (pass $members to view with compact)
return view('member/index', compact('members'));
}
create new view
<h1>List display</h1>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>phone number</th>
<th>Email address</th>
</tr>
@foreach($members as $member)
<tr>
<td>{{$member->id}}</td>
<td>{{$member->name}}</td>
<td>{{$member->telephone}}</td>
<td>{{$member->email}}</td>
</tr>
@endforeach
</table>
Confirmation
Start a simple server.
php artisan serve
Access http://127.0.0.1:8000/member/index with a browser and confirm that the list is displayed. Terminate the simple server with Ctrl+C.
New registration (create)
Add routing
Add a route for accessing /member/create.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
// Addition
Route::get('create','MemberController@create')->name('member.create');
});
Edit ### controller Returns create.blade.php.
public function create()
{
return view('member/create');
}
create new view
Create a new screen. Only the name is required.
<h1>New creation</h1>
<form method="POST" action="">
@csrf
<div>
<label for="form-name">name</label>
<input type="text" name="name" id="form-name" required>
</div>
<div>
<label for="form-tel">phone number</label>
<input type="tel" name="telephone" id="form-tel">
</div>
<div>
<label for="form-email">email address</label>
<input type="email" name="email" id="form-email">
</div>
<button type="submit">Register</button>
</form>
```### Conductor (index → create)
It is a link from the list display screen to the new creation screen.
```:resources\views\member\index.blade.php
<a href="{{ route('member.create') }}">{{ __('Create new') }}</a>
Conductor (create → index)
It is a link from the new creation screen to the list display screen.
//add to
<a href="{{ route('member.index') }}">{{ __('back to list') }}</a>
Confirmation
Start a simple server.
php artisan serve
Access http://127.0.0.1:8000/member/create with a browser and confirm that the new input screen is created. (At this point, an error will occur even if you press the register button.) Terminate the simple server with Ctrl+C.
New store
Save the value entered in the Add New screen in DB.
Add routing
Add a route for accessing /member/store.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
//add to
Route::post('store','MemberController@store')->name('member.store');
});
Edit ### controller Store the values entered in the form in the members table.
public function store(Request $request)
{
$member=new Member;
$member->name=$request->input('name');
$member->telephone=$request->input('telephone');
$member->email=$request->input('email');
$member->save();
// redirect to the list display screen
return redirect('member/index');
}
create new view
None
Conductor (create → store)
It is a link from the list display screen to the new creation screen.
//<form method="POST" action="">
//↓ Change the form destination
<form method="POST" action="{{route('member.store')}}">
Conductor (store → index)]
The controller has already described the redirect.
Confirmation
Start a simple server.
php artisan serve
When you access http://127.0.0.1:8000/member/create with a browser, enter a value and send it, you will be redirected to member/index and confirm that the value is in the members table. Terminate the simple server with Ctrl+C.
Detailed display (show)
Add routing
Add a route for accessing /member/show/id.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
Route::post('store','MemberController@store')->name('member.store');
//add to
Route::get('show/{id}','MemberController@show')->name('member.show');
});
Edit ### controller Performs the process to display the details page of the member with the specified ID.
public function show($id)
{
$member=Member::find($id);
return view('member/show', compact('member'));
}
create new view
<h1>Detailed display</h1>
<div>
name
{{$member->name}}
</div>
<div>
phone number
{{$member->telephone}}
</div>
<div>
mail address
{{$member->email}}
</div>
Conductor (index → show)
Add one column to the list display screen and add a link to the detail screen.
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>phone number</th>
<th>Email address</th>
<th>Details</th>
</tr>
@foreach($members as $member)
<tr>
<td>{{$member->id}}</td>
<td>{{$member->name}}</td>
<td>{{$member->telephone}}</td>
<td>{{$member->email}}</td>
<td><th><a href="{{route('member.show',['id'=>$member->id])}}">Details</a></th></td >
</tr>
@endforeach
</table>
Conductor (show → index)
<a href="{{ route('member.index') }}">{{ __('back to list') }}</a>
Confirmation
Start a simple server.
php artisan serve
Go to http://127.0.0.1:8000/member/index in your browser and press Details to see the details screen is displayed. Terminate the simple server with Ctrl+C.
edit
Add routing
Add a route for accessing /member/edit/id.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
Route::post('store','MemberController@store')->name('member.store');
Route::get('show/{id}','MemberController@show')->name('member.show');
//add to
Route::get('edit/{id}','MemberController@edit')->name('member.edit');
});
Edit ### controller
public function edit($id)
{
$member=Member::find($id);
return view('member/edit', compact('member'));
}
create new view
<h1>Edit</h1>
<form method="POST" action="">
@csrf
<div>
name
<input type="text" name=name value="{{$member->name}}">
</div>
<div>
phone number
<input type="text" name=telephone value="{{$member->telephone}}">>
</div>
<div>
mail address
<input type="text" name=email value="{{$member->email}}">
</div>
<input type="submit" value="Update">
</form>
Conductor (show → edit)
//add to
<a href="{{route('member.edit',['id'=>$member->id])}}">{{ __('edit') }}</a>
Conductor (edit → show)
//add to
<a href="{{route('member.show',['id'=>$member->id])}}">{{ __('back to details') }}</a>
Confirmation
Start a simple server.
php artisan serve
Go to http://127.0.0.1:8000/member/index in your browser and make sure you can see the edit form which goes to Details → Edit. (At this point, an error will occur even if you press the update button.)
updateSet the operation when you press the “Update” button on the edit screen.
Add routing
Add a route for accessing /member/update/id.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
Route::post('store','MemberController@store')->name('member.store');
Route::get('show/{id}','MemberController@show')->name('member.show');
Route::get('edit/{id}','MemberController@edit')->name('member.edit');
//add to
Route::post('update/{id}','MemberController@update')->name('member.update');
});
Edit ### controller
public function update(Request $request, $id)
{
$member=Member::find($id);
$member->name=$request->input('name');
$member->telephone=$request->input('telephone');
$member->email=$request->input('email');
// Save to DB
$member->save();
// After processing, redirect to member/index
return redirect('member/index');
}
create new view
None
Conductor (edit → update)
Specify the destination of the send button of edit.
//<form method="POST" action="">
//↓
<form method="POST" action="{{route('member.update',['id' =>$member->id])}}">
Conductor (update → index)
redirected by controller
Confirmation
Start a simple server.
php artisan serve
Access http://127.0.0.1:8000/member/index with a browser, go to the details screen → edit screen, change the value and press the “Update” button, and the data of /member/index is changed. Check that Terminate the simple server with Ctrl+C.
Delete (destroy)
Add routing
Add a route for accessing /member/destroy/id.
Route::group(['prefix'=>'member'], function () {
Route::get('index','MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
Route::post('store','MemberController@store')->name('member.store');
Route::get('show/{id}','MemberController@show')->name('member.show');
Route::get('edit/{id}','MemberController@edit')->name('member.edit');
Route::post('update/{id}','MemberController@update')->name('member.update');
//add to
Route::post('destroy/{id}','MemberController@destroy')->name('member.destroy');
});
Edit ### controller Write the process to delete the specified ID.
public function destroy($id)
{
$member=Member::find($id);
$member->delete();
return redirect('member/index');
}
create new view
None
Conductor (show → destroy)
//add to
<form method="POST" action="{{route('member.destroy',['id'=>$member->id])}}">
@csrf
<button type="submit">Delete</button>
</form>
Conductor (destroy → index)
redirected by controller
Confirmation
Start a simple server.
php artisan serve
Access http://127.0.0.1:8000/member/index with a browser, go to the details screen, click the “Delete” button, and confirm that the data in /member/index has been deleted. Terminate the simple server with Ctrl+C.
Preparation for validation
Localization of error messages
Place the following ja folder in resources/lang/ in the same hierarchy as the en folder. https://github.com/minoryorg/laravel-resources-lang-ja
- You can further customize the message by editing the files in the ja folder.
//'attributes' => [],
//↓
'attributes' => ['email'=>'email address',
'name'=>'name'
],
Validation (new save)
form request creation
php artisan make:request StoreMember
app\Http\Requests\StoreMember.php is newly created.
edit form request
Specify validation rules.
//add to
use Illuminate\Validation\Rule;
public function authorize()
{
//return false;
//↓ change false to true
return true;
}
public function rules()
{
return [
//add to
'name' => [
'string',
'required',
'max:20'
],
'telephone' => [
'string',
'nullable',
'max:13',
'unique:members'
],
'email' => [
'nullable',
'max:255',
'email',
'unique:members'
]
];
}
Keywords | Content |
---|---|
required | Required |
max | maximum length |
unique: table name | unique for the specified table |
nullable | nullable |
accepted | Checked |
string | string type |
email type | |
url | url type |
controller
//add to
use App\Http\Requests\StoreMember;
//public function store(Request $request)
//↓ change
public function store(StoreMember $request)
view
Place the error message where you want it to appear.
<form method="POST" action="{{route('member.store')}}">
@csrf
<div>
<label for="form-name">name</label>
// <input type="text" name="name" id="form-name" required>
// Add ↓value to hold the input value.
<input type="text" name="name" id="form-name" required value="{{old('name')}}">
//add to
@error('name')
{{$message}}
@enderror
</div>
<div>
<label for="form-tel">phone number</label>
//<input type="tel" name="telephone" id="form-tel">
// Add ↓value to hold the input value.
<input type="tel" name="telephone" id="form-tel" value="{{old('telephone')}}">
//add to
@error('telephone')
{{$message}}@enderror
</div>
<div>
<label for="form-email">email address</label>
//<input type="email" name="email" id="form-email">
// Add ↓value to hold the input value.
<input type="email" name="email" id="form-email" value="{{old('email')}}">
//add to
@error('email')
{{$message}}
@enderror
</div>
<button type="submit">Send</button>
</form>
Validation (save)
If you keep validating the new registration, you will need to change the phone number and email address that you want to make unique.
form request creation
php artisan make:request UpdateMember
app\Http\Requests\UpdateMember.php is newly created.
edit form request
It’s almost the same as a new validation, but it’s modified to allow existing values as well.
//add to
use Illuminate\Validation\Rule;
public function authorize()
{
//return false;
//↓ change false to true
return true;
}
public function rules()
{
return [
//add to
'name' => [
'string',
'required',
'max:20'
],
'telephone' => [
'string',
'nullable',
'max:13',
//Allow existing values
Rule::unique('members')->ignore($this->id)
],
'email' => [
'nullable',
'max:255',
'email',
//Allow existing values
Rule::unique('members')->ignore($this->id)
]
];
}
controller
//add to
use App\Http\Requests\UpdateMember;
//public function update(Request $request, $id)
//↓ change
public function update(UpdateMember $request, $id)
view
Place the error message where you want it to appear.
<form method="POST" action="{{route('member.update',['id' =>$member->id])}}">
@csrf
<div>
name
<input type="text" name=name value="{{$member->name}}">
@error('name')
{{$message}}
@enderror
</div>
<div>
phone number
<input type="text" name=telephone value="{{$member->telephone}}">>
@error('telephone')
{{$message}}
@enderror
</div>
<div>
mail address
<input type="text" name=email value="{{$member->email}}">
@error('email')
{{$message}}
@enderror
</div>
<input type="submit" value="Update">
</form>
Pagination
controller
When the number of items displayed in the list increases, divide the page.
public function index()
{
$members=DB::table('members')
->select('id','name','telephone','email')
//->get();
//↓ Specify the number of items to be displayed on one page
->paginate(20);
//return view (pass $members to view with compact)
return view('member/index', compact('members'));
}
view
Add page feed UI to the list screen.
//add to
{{$members->links()}}
The description is one line, but the html is generated as shown below, so please arrange it with CSS.
<nav>
<ul class="pagination">
<li class="page-item disabled" aria-disabled="true" aria-label="« Previous"> <span class="page-link" aria-hidden="true"> ‹</span></ li>
<li class="page-item active" aria-current="page">
<span class="page-link">1</span>
</li>
<li class="page-item">
<a class="page-link" href="http://127.0.0.1:8000/member/index?page=2">2</a>
</li>
<li class="page-item">
<a class="page-link" href="http://127.0.0.1:8000/member/index?page=2" rel="next" aria-label="Next »">›</a>
</li>
</ul>
</nav>
Search function
Add routing
Route::group(['prefix'=>'member'], function () {
Route::get('index''MemberController@index')->name('member.index');
Route::get('create','MemberController@create')->name('member.create');
Route::post('store','MemberController@store')->name('member.store');
Route::get('show/{id}','MemberController@show')->name('member.show');
Route::get('edit/{id}','MemberController@edit')->name('member.edit');
Route::post('update/{id}','MemberController@update')->name('member.update');
Route::post('destroy/{id}','MemberController@destroy')->name('member.destroy');
//add to
Route::get('search','MemberController@search')->name('member.search');
});
Edit ### controller
public function search(Request $request)
{
$serach=$request->input('q');
$query=DB::table('members');
// Convert full-width space of search word to half-width space
$serach_spaceharf=mb_convert_kana($serach,'s');
// Separate search words with a space
$keyword_array=preg_split('/[\s]+/', $serach_spaceharf, -1, PREG_SPLIT_NO_EMPTY);
// Rotate the search word in a loop to find a matching record
foreach ($keyword_array as $keyword) {
$query->where('name','like','%'.$keyword.'%');
}
$query->select('id','name','telephone','email');
$members=$query->paginate(20);
return view('member/index', compact('members'));
}
edit view
Add a search form to the list display screen.
//add to
<form method="GET" action="{{route('member.search')}}">
@csrf
<div>
<label for="form-search">Search</label>
<input type="search" name="q" id="form-search">
</div><button type="submit">検索</button>
</form>