Table of contents
1.
how to start
2. create a basic user creation page
3.
create unit tests for Laravel 5.7
Create tables
At first, we will create these tables:
- user table
- password reset table
Actually these tables are prepared by default in /vagrant/laravel/database/migrations
folder.
Open the "2014_10_12_000000_create_users_table.php". You can see the code inside:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
The function up() is executed to apply changes to the database when this file is migrated by the "migration" command of artisan. The function down() is executed when you revert the migration. Let's migrate the migration files. But before migrating, as of Laravel Framework 5.7.25, according to this
stackoverflow question, we need to modify and add some code to a file.
Open /vagrant/laravel/app/Providers/AppServiceProvider.php
. Change it as follows:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema; //Here. Import Schema!!!!!
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191); //Increase the StringLength!!!!
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
Now you can migrate the migration files:
$ cd /vagrant/laravel
$ php artisan migrate
Then the tables are created in the database:
Create a new migration file and a table
To create new migration file, just run this command:
$ php artisan make:migration {table name}
To create a table named "articles", run this command:
$ php artisan make:migration articles
Then the migration file for articles table will be added:
2019_02_10_131250_articles.php
is the migration file for the articles table. Open the migration file for articles and change it as follows:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Articles extends Migration
{
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('name');
$table->string('detail');
$table->rememberToken();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->index('user_id');
});
}
public function down()
{
Schema::table('articles', function($table) {
$table->dropForeign('articles_user_id_foreign');
$table->dropIndex('articles_user_id_index');
$table->dropColumn('user_id');
});
Schema::dropIfExists('articles');
}
}
Now migrate it:
$ php artisan migrate
Then the articles table is added in the database.
Create models and controllers
We will make corresponding models:
$ php artisan make:model User
$ php artisan make:model Article
And controllers:
$ php artisan make:controller UserController
$ php artisan make:controller ArticleController
For your information, to make models and controllers at the same time:
$ php artisan make:model User -c
$ php artisan make:model Article -c
Create factories for testing:
$ php artisan make:factory UserFactory
$ php artisan make:factory ArticleFactory
Now seeders:
$ php artisan make:seeder UsersTableSeeder
$ php artisan make:seeder ArticlesTableSeeder
You can see the
models in /vagrant/laravel/app/
controllers in /vagrant/laravel/app/Http/Controller/
Factories in /vagrant/laravel/database/factories/
Seeders in /vagrant/laravel/database/seeds/
.
Create 10 users for testing
Let's make 10 users for testing. Open the UsersTableSeeder and change the run() function as follows:
public function run()
{
factory(App\User::class, 10)->create();
}
Open the DatabaseSeeder.php
and change the run function as follows:
public function run()
{
$this->call(UsersTableSeeder::class);
}
Then migrate it with seed option:
$ php artisan migrate --seed
10 users are created in the database:
You can initialize all the tables and insert the 10 users at the same time with migrate:fresh:
$ php artisan migrate:fresh --seed
Access DB and pass the data to View in Web.php
Open
/vagrant/laravel/routes/web.php
. If you followed instructions written
here, the code inside should be like this:
<?php
Route::get('/', function () {
return view('welcome');
});
Route::get('/test', function () {
return view('test');
});
Change it as follows:
<?php
Route::get('/', function () {
$users = \App\User::all();
return view('welcome', ['users' => $users]);
});
Route::get('/test', function () {
return view('test');
});
Now you can use the $users variable in the welcome page's view. Add the following somewhere in the body of /vagrant/laravel/resources/views/welcome.blade.php
.
<ul>
@foreach ($users as $user)
<li>{{ $user->name }}</li>
@endforeach
<ul>
Like this:
Page to create users
At first, we will create a view for the page. Save the following as layout.blade.php
in /vagrant/laravel/resources/views/
.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title')</title>
</head>
<body>
<div class="container">
@yield('content')
</div>
</body>
Then save the following as submit.blade.php
in /vagrant/laravel/resources/views/
.
@extends('layout')
@section('title', 'submit')
@section('content')
<div class="container">
<div class="row">
<h1>Submit a user</h1>
<form action="/submit" method="post">
{!! csrf_field() !!}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="name">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" id="email" name="email" placeholder="email">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="text" class="form-control" id="password" name="password" placeholder="password">
</div>
<button id="submitBtn" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
@endsection
We will add the following in /vagrant/laravel/routes/web.php
.
use Illuminate\Http\Request;
Route::get('/submit', function () {
return view('submit');
});
Route::post('/submit', function (Request $request) {
$data = $request->validate([
'name' => 'required | max:255',
'email' => 'required | max:255',
'password' => 'required | max:255',
]);
$user = new App\User($data);
$user->save();
return redirect('/');
});
Like this:
<?php
use Illuminate\Http\Request;
Route::get('/', function () {
$users = \App\User::all();
return view('welcome', ['users' => $users]);
});
Route::get('/submit', function () {
return view('submit');
});
Route::post('/submit', function (Request $request) {
$data = $request->validate([
'name' => 'required | max:255',
'email' => 'required | max:255',
'password' => 'required | max:255',
]);
$user = new App\User($data);
$user->save();
return redirect('/');
});
Route::get('/test', function () {
return view('test');
});
Route:get is the function to be executed when user access the url with the GET method. Route:get is the function to be executed when user access the url with POST method.
See http://192.168.33.10/submit
from your browser and you can see users can be now added.
Refactoring the code
We have a working code now, but all of the process is written in the web.php, which is not the correct way to implement. To write clean code, we must separate operation in Model, Controller (and in Request).
Request
At first, we will move the validation process to Request. To make Request for the users table, run the following command:
$ php artisan make:request UserRequest
You can find the UserRequest in /vagrant/laravel/app/Http/Requests/
. Open and change it as follows:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required | max:255',
'email' => 'required | max:255',
'password' => 'required | max:255',
];
}
}
You can see that $validator->fails()
is not implemented in the file because Laravel automatically prevents users to go to the page where users are supposed to go only if the validation is success. Also you can use $errors
variable in the view without defining it here.
Controller
Open /vagrant/laravel/app/Http/Controller/UserController.php
and change it as follows:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Http\Requests\UserRequest;
class UserController extends Controller
{
public function submitGet(Request $request){
return view('/submit');
}
public function submitPost(UserRequest $request){
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password = $request->password;
$user->save();
return redirect('/');
}
}
By using UserRequest for the type hinting of submitPost() function, only if the validation process has no error, the process inside the function is executed.
Routing
Now open the /vagrant/laravel/routes/web.php
and change it as follows:
<?php
use Illuminate\Http\Request;
Route::get('/', function () {
$users = \App\User::all();
return view('welcome', ['users' => $users]);
});
Route::get('/submit','UserController@submitGet');
Route::post('/submit','UserController@submitPost');
Route::get('/test', function () {
return view('test');
});
Check if these work
You can see the created user is added in the database: