P06 Database Basics
P06 Database Basics
Database Basics
use Illuminate\Http\Request;
Using this extension, you can import a class by right-click on the class name and choose Import Class.
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ExampleController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Why?
Laravel do this automatically to prevent Cross site request forgery (CSRF) attack. Will be explained in detail
after we see how laravel create cookies.
For now, do the work-around by editing homepage.blade.php
homepage.blade.php
…
<form action="/register" method="POST" id="registration-form">
@csrf
<div class="form-group">
…
UserController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
Why?
Since we send an array with multiple data to database using this line User::create($incomingFields),
Laravel checks first that all fields exist.
User.php
…
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'username',
'email',
'password',
];
…
But, most importantly, you need to check your data is entered into database.
Voilà!!! Now you’ve successfully connected your front-end with database.
For unique, we can use a static method unique() in Laravel class Rule with two arguments – table name in
database and field name in table.
To use this class, import the class (right click on the class name, Import Class, then choose Illuminate\
Validation\Rule.
UserController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
homepage.blade.php
…
<div class="form-group">
<label for="password-register" class="text-muted mb-1"><small>Password</small></label>
<input name="password" id="password-register" class="form-control" type="password"
placeholder="Create a password" />
</div>
<div class="form-group">
<label for="password-register-confirm" class="text-muted mb-1"><small>Confirm
Password</small></label>
<input name="password_confirmation" id="password-register-confirm" class="form-control"
type="password" placeholder="Confirm password" />
</div>
By using the postfix _confirmation, laravel will automatically check for similarity.
However, there is a major security issue here which is storing the plain password text.
So, let’s fix this issue by hashing the password using bcrypt().
UserController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
$incomingFields['password'] = bcrypt($incomingFields['password']);
User::create($incomingFields);
return 'Hello from register function';
}
}
homepage.blade.php
…
<div class="form-group">
<label for="username-register" class="text-muted mb-1"><small>Username</small></label>
<input name="username" id="username-register" class="form-control" type="text"
placeholder="Pick a username" autocomplete="off" />
@error('username')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>
…
@ in blade is how you run directive or command
<div class="form-group">
<label for="password-register" class="text-muted mb-1"><small>Password</small></label>
<input name="password" id="password-register" class="form-control" type="password"
placeholder="Create a password" />
@error('password')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>
<div class="form-group">
<label for="password-register-confirm" class="text-muted mb-1"><small>Confirm
Password</small></label>
<input name="password_confirmation" id="password-register-confirm" class="form-control"
type="password" placeholder="Confirm password" />
@error('password_confirmation')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>
…
homepage.blade.php
…
<div class="form-group">
<label for="username-register" class="text-muted mb-1"><small>Username</small></label>
<input value="{{old('username'}}" name="username" id="username-register" class="form-
control" type="text" placeholder="Pick a username" autocomplete="off" />
@error('username')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>
<div class="form-group">
<label for="email-register" class="text-muted mb-1"><small>Email</small></label>
<input value="{{old('email'}}" name="email" id="email-register" class="form-control"
type="text" placeholder="[email protected]" autocomplete="off" />
@error('email')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>
…
Note: Laravel does not support old() for password field.
Notice the value of username and email fields are kept when we received error.
Authentication Basics
Before we start with this lesson, let’s clean up our database first since it contains unwanted records like those
with password that is not being hashed.
This can be done by
i. manually
ii. using migrate:fresh
Note: Do not use this command if you have records in your database that you don’t want to lose.
Great!
First, create a user record that we’re going to use for the rest of this lesson.
3.1 Logging In
First, we need to know the location where the form is posted to.
layout.blade.php
…
<form action="/login" method="POST" class="mb-0 pt-2 pt-md-0">
@csrf
<div class="row align-items-center">
<div class="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input name="loginusername" class="form-control form-control-sm input-dark" type="text"
placeholder="Username" autocomplete="off" />
</div>
<div class="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input name="loginpassword" class="form-control form-control-sm input-dark"
type="password" placeholder="Password" />
</div>
<div class="col-md-auto">
<button class="btn btn-primary btn-sm">Sign In</button>
</div>
</div>
</form>
…
web.php
…
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ExampleController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
UserController.php
…
class UserController extends Controller
{
public function login(Request $request) {
$incomingFields = $request->validate([
'loginusername' => 'required',
'loginpassword' => 'required'
]);
if(auth()->attempt([
'username'=>$incomingFields['loginusername'],
'password'=>$incomingFields['loginpassword']])) {
return 'Congrats!!!';
} else {
return 'Sorry!!!';
}
}
…
Laravel has a globally available function auth() (do not need to import the namespace) that returns an object.
Inside the object, we’re using a method called attempt() that will try login using the given username and
password.
$request is an object. Inside the object, there is a method called session() that returns an object. Inside that
object regenerate().
Login again go to Inspect – Application. Notice the laravel-session. This cookies is what prove to Laravel that
we are the user that we just logged in with.
Note: Cookies are automatically sent along from browser to server on every request
Laravel provide a simple way for this using directive @auth with the following format:
@auth
// logged in
@else
// not logged in
@endauth
</div>
</header>
…
Next, let’s work on the body.
This is a little bit trickier from header because it is not controlled in layout.blade.php file.
To control the body of a page based on user logged in or not, let’s create a method in UserController.php.
But first, let’s edit the route.
web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ExampleController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
auth()->check() will return true or false depending on whether you are logged in or not.
So we can use it in our if-else statement.
UserController.php
…
class UserController extends Controller
{
public function showCorrectHomepage() {
if (auth()->check()) {
return 'You are logged in';
} else {
return view('homepage');
}
}
…
homepage-feed.blade.php
<x-layout>
<div class="container py-md-5 container--narrow">
<div class="text-center">
<h2>Hello <strong>username</strong>, your feed is empty.</h2>
<p class="lead text-muted">Your feed displays the latest posts from the people you
follow. If you don’t have any friends to follow that’s okay; you can use the
“Search” feature in the top menu bar to find content written by people with
similar interests and then follow them.</p>
</div>
</div>
</x-layout>
Finally, let’s personalize this page for the user using property username of object from method user() in
global function auth().
homepage-feed.blade.php
<x-layout>
<div class="container py-md-5 container--narrow">
<div class="text-center">
<h2>Hello <strong>{{auth()->user()->username}}</strong>, your feed is empty.</h2>
<p class="lead text-muted">Your feed displays the latest posts from the people you
follow. If you don’t have any friends to follow that’s okay; you can use the
“Search” feature in the top menu bar to find content written by people with
similar interests and then follow them.</p>
</div>
</div>
</x-layout>
3.3 Logging Out
First, let’s work on the Sign Out button. This button is supposed to destroy a user’s session so that the user is
no longer logged in.
layout.blade.php
…
@auth
<div class="flex-row my-3 my-md-0">
<a href="#" class="text-white mr-2 header-search-icon" title="Search" data-toggle="tooltip"
data-placement="bottom"><i class="fas fa-search"></i></a>
<span class="text-white mr-2 header-chat-icon" title="Chat" data-toggle="tooltip" data-
placement="bottom"><i class="fas fa-comment"></i></span>
<a href="#" class="mr-2"><img title="My Profile" data-toggle="tooltip" data-
placement="bottom" style="width: 32px; height: 32px; border-radius: 16px"
src="https://gravatar.com/avatar/f64fc44c03a8a7eb1d52502950879659?s=128" /></a>
<a class="btn btn-sm btn-success mr-2" href="#">Create Post</a>
<form action="/logout" method="POST" class="d-inline">
@csrf
<button class="btn btn-sm btn-secondary">Sign Out</button>
</form>
</div>
@else
…
web.php
...
Route::post('/register', [UserController::Class, 'register']);
Route::post('/login', [UserController::Class, 'login']);
Route::post('/logout', [UserController::Class, 'logout']);
UserController.php
…
class UserController extends Controller
{
public function logout() {
auth()->logout();
return 'You are now logged out';
}
Having to manually go back to the homepage is awkward. Let’s fix that using redirect.
3.4 Redirect
UserController.php
…
public function logout() {
auth()->logout();
return redirect('/');
}
…
public function login(Request $request) {
$incomingFields = $request->validate([
'loginusername' => 'required',
'loginpassword' => 'required'
]);
if(auth()-
>attempt(['username'=>$incomingFields['loginusername'],'password'=>$incomingFields['loginpass
word']])) {
$request->session()->regenerate();
return redirect('/');
} else {
return redirect('/');
}
}
…
3.5 Flash Message
It is good to give a message to user when redirect. This can be done using a flash message. A flash message
is a message that only appears for one request then it gets cleared from session data. Laravel makes this very
easy to set up.
UserController.php
…
public function logout() {
auth()->logout();
return redirect('/')->with('success','You have sucessfully logged out');
}
…
public function login(Request $request) {
$incomingFields = $request->validate([
'loginusername' => 'required',
'loginpassword' => 'required'
]);
if(auth()-
>attempt(['username'=>$incomingFields['loginusername'],'password'=>$incomingFields['loginpass
word']])) {
$request->session()->regenerate();
return redirect('/')->with('success','You have sucessfully logged in');
} else {
return redirect('/')->with('failure','Invalid login');
}
}
…
Next, we need to tell Laravel how and where to display this message.
layout.blade.php
…
<!-- header ends here -->
@if (session()->has('success'))
<div class="container container--narrow">
<div class="alert alert-success text-center">
{{session('success')}}
</div>
</div>
@endif
@if (session()->has('failure'))
<div class="container container--narrow">
<div class="alert alert-danger text-center">
{{session('failure')}}
</div>
</div>
@endif
{{ $slot }}
Great! We’re done with login form. Let’s work on registration form. Instead of returning a message 'Hello
from register function', let’s do the following:
i. redirect to homepage
ii. automatically login the user after successfully register before redirect to homepage
UserController.php
…
public function register(Request $request) {
$incomingFields = $request->validate([
'username' => ['required','min:3','max:20', Rule::unique('users', 'username')],
'email' => ['required','email', Rule::unique('users', 'email')],
'password' => ['required', 'min:8', 'confirmed']
]);
$incomingFields['password'] = bcrypt($incomingFields['password']);
$user = User::create($incomingFields);
auth()->login($user);
return redirect('/')->with('success','Thank you for creating an account.');
}
…
Wonderful! Now we’re automatically logged in and redirected to homepage with a flash message.
3.6 Miscellaneous
Before we finish, let’s do some touch ups on our website.
1. Make copyright year to be dynamic
layout.blade.php
…
<!-- footer begins -->
<footer class="border-top text-center small text-muted py-3">
<p class="m-0">Copyright © {{date('Y')}} <a href="/" class="text-muted">OurApp</a>.
All rights reserved.</p>
</footer>
…
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
End