top of page
Search

Updated: Dec 13, 2022

Eloquent ORM: is an object-relational mapper which included by default within the Laravel framework. Eloquent ORM is communicate with database tables and provide an object-oriented approach to CRUD operations. Also through Eloquent ORM it is easy to work with multi database at same time.


When using the Eloquent, each table has corresponding Model to interact and retrieve records from the database. Eloquent model allows the user to store, update, and delete records.

make:model Artisan command is used to create model. After creating the model by default, it lives in the app\Models.

I have used the below command to create contact model and table.

php artisan make:model Contact -m Laravel by default uses the plural name of the class as table name; therefore, in my case Laravel migrated contacts table.


contacts table

ree

I have created the columns for table, used the unsignInteger method for user_id column because it defines the relationship with users table. I have also used the foreign method to reference user_id column with id column on users table.

php artisan migrate – execute migrate artisan command to run outstanding migration.


Contact Model

ree

Laravel mass assignment is a process of sending an array of data that will be saved to the specified model at once. It is a fast and easy-to-use procedure but there is possible security threat behind it. So fillable attribute allows the user to specify which fields is mass-assignable in model, and the guarded is the reverse of fillable.


In Contact model I have used the guarded attribute instead of fillable.


protected $guarded = ['id']; - it means only id field is not mass-assignable, id field is auto increment.


belongsTo method defines child -> parent relationship, this method defines in child (Contact) model. belongsTo is about having one, for about having many there is an other method called blongsToMany().

ree

In one to many relationship there is single model as parent and one or more child models. hasMany method defines in User model to build relationship between Contact model and User model.


Tinker

Tinker help me to interact with entire Laravel project through command line, including eloquent models. Laravel Tinker is a powerful REPL (Read-Evaluate-Print-Loop) for the Laravel framework, powered by the PsySH package.

ree

 
 
 
  • Nov 7, 2022
  • 4 min read

Updated: Dec 14, 2022

Controllers assemble related request handling logic into a single class, ContactController class handles all incoming requests related to contacts, including storing, showing, updating, and deleting contacts. By default, controllers are stored in the app/Http/Controllers directory.

I have used resource controller. It means Laravel resource routing assigned the typical CRUD routes to the ContactController.

make: controller - Artisan command, --resource or -r options – to generate resource controller

php artisan make:controller ContactController -r

I have used above command to generate ContactController.

php artisan route:list

This way we can check actions handled by resource ContactController.


ree

Inside the ContactController, I have imported the below classes.

use Illuminate\Http\Request class provide an object-oriented approach to communicate with current HTTP request, it retrieve the input, cookies and files that were carry by request.

use Illuminate\Support\Facades\Auth class will check the incoming HTTP request if it is authenticated return true other wise redirect the user to login page.

use Illuminate\Support\Facades\File class exends the PHP SplFileInfo class and offer several methods for interacting with the file


Protecting Routes

Route middleware only allow authenticated user to access a given route. In Laravel the auth middleware defined at Illuminate\Auth\Middleware\Authenticate. also the middleware is registered in HTTP kernel; therefore, Inside controller's constructor, I have attached the middleware and passed an array to make sure authenticated user with verified email can access the routes.


public function __construct() { $this->middleware(['auth', 'verified']); }


Index Method

I have retrieved all records and passed them into $contacts variable, and through compact () method passed all the data to view. In Laravel, you can use compact () method to pass an array of the variables from controller to view.


public function index() { $contacts = Contact::all(); return view('home', compact('contacts')); }


Create Method

I have just returned create view.


public function create() { return view('create'); }


Validation: Laravel provides several different approaches to validate incoming HTTP requests, the validate method has been provided by the Illuminate\Http\Request object. we can use the validation in differently way either inside the controller's method or create a FormRequest class to validate the incoming requests. If validation fails then Illuminate\Validation\ValidationException exception throws an error message. Here i have applied the validation rules inside the controllers method.


Authorization: Laravel provides an easy way to authorize user action. Through authorization we can limit even authenticated users access. There are two main ways of authorizing actions, gates and policies. Here in ContactController, I have authorized user action directly within the methods without using policy.


Stored Method

To store new contact into the contacts table:

- I created $request variable.

- For name and mobile fields, I have set validation rule required and, for photo field, I have validated the mime type of file to make sure the user is only able to upload specific file types.

- I created $contacts variable and set input request for each field.

- I created $fileName as a variable and passed file request on it. As GetClientOriginalName() method is considered unsafe and it is possible for malicious users to detect it, I have used hashName() method to get file name including current time and an extension for the given file upload.

- I defined the storage path. I have asked upload orphan image in public/storage/media, I have used storeAs () method. In this way, I will have more control and filename will not be automatically assigned to the stored file. There is another method putFileAs which has similar functionality.

- I have authorized the action of authenticate user - $contacts->user_id = Auth::user()->id; This way ensures only authenticated users whose id matches contact user_id can store the record.

- I saved new record.

- And I returned with success message.

-


public function store(Request $request) { $this->validate($request, [ 'name' => 'required|regex:/^[\pL\s\-]+$/u', 'mobile' => 'required|numeric|digits:11', 'photo' => 'required|mimes:jpeg,bmp,png,jpg', ]); $contacts = new Contact; $contacts->name = $request->input('name'); $contacts->mobile = $request->input('mobile'); //GetClientOriginalName() method is considered unsafe //and it is possible for malicious users to detect it $fileName = time().$request->file('photo')->hashName(); $path = $request->file('photo')->storeAs('media', $fileName, 'public'); $contacts['photo'] = '/storage/'.$path; $contacts->user_id = Auth::user()->id; $contacts->save(); return back()->with('success', 'Contact created successfully'); }


The Public Disk

The public disk is part of application's filesystems configuration file and it is publicly accessible. the public disk by default use the local driver and stores its file in Storage/app/public/media. however; to make the files accessible from browser need to create a symbolic link from public/storage to storage/app/public/media.


To create the symbolic link, in terminal run the following command: php artisan storage:link


dd () method

dd () is stand for Dump and Dies, this method dumps and end execution of the script, i have used this method for debugging purpose.


Show Method

- I have set WHERE condition base on record id to retrieve specific contact.

- Also I used WHERE condition to authorize only authenticate user, whose id = contact user_id

- I used the firstOrFail() method, it will abort if no record is found in query.

- I passed the query to delete view by compact () method.


public function show($id) { $contacts = Contact::where('id', $id)->where('user_id', Auth::user()->id)->firstOrFail(); return view('delete', compact('contacts')); }


Edit Method

- I have set WHERE condition base on record id to retrieve specific contact.

- Also I used WHERE condition to authorize only authenticate user, whose id = contact user_id.

- I used the firstOrFail() method. It will abort if no record found in query.

- I passed the query to edit view by compact () method.


public function edit($id) { $contacts = Contact::where('id', $id)->where('user_id', Auth::user()->id)->firstOrFail(); return view('edit', compact('contacts')); }


Update Method

- I set validation for name and mobile fields.

- I set input request for name and mobile fields.

- For photo field, I have set if () condition. If request contains file, in this case first delete file from storage and then update.

- I also set authorization for user.

- I saved new changes.

- Then I returned with success message.


public function update(Request $request, $id) { $this->validate($request, [ 'name' => 'required|regex:/^[\pL\s\-]+$/u', 'mobile' => 'required|numeric|digits:11', 'photo' => 'mimes:jpeg,bmp,png,jpg', ]);

$contacts = Contact::findOrFail($id); $contacts->name = $request->input('name'); $contacts->mobile = $request->input('mobile'); if($request->hasfile('photo')){ $path=public_path($contacts->photo); if(File::exists($path)){ File::delete($path); } $fileName = time().$request->file('photo')->hashName(); $path = $request->file('photo')->storeAs('media', $fileName, 'public'); $contacts ['photo'] = '/storage/'.$path; } $contacts->user_id = Auth::user()->id; $contacts->save(); return back()->with('success', 'Contact updated successfully'); }

Destroy Method

- I have set WHERE condition base on record id to retrieve specific contact.

- Also I used WHERE condition to authorize only authenticate user, whose id = contact user_id

- I used the firstOrFail() method, it will abort if no record found in query.

- Then I first deleted photo (orphan) from storage.

- After that I deleted the record from database.

- Lastly I returned to user dashboard and display success message.


public function destroy($id) { $contacts = Contact::where('id', $id)->where('user_id', Auth::user()->id)->firstOrFail(); unlink(public_path($contacts->photo)); $contacts->delete(); return redirect()->route('user.index')->with('success', 'Item deleted successfully'); }

Orphan Images Short Demo


 
 
 
  • Nov 6, 2022
  • 3 min read

Updated: Dec 13, 2022

First I have needed to add new column ‘role’ in users table. To do so, I used the bellow command in terminal to create migration.

php artisan make:migration add_role_to_users_table --table=users


I opened the migration and added role column.

$table->boolean('role')->default(0);

ree

Now from terminal migrate, this way I added role column into the users table.

php artisan migrate


In Model/User add role column in fillable

ree

To create middleware for admin I used the below command.

php artisan make:middleware role

In app/Http/Middleware/role.php: set a condition if role ==1 then move on otherwise redirect to user dashboard.

ree

To create middleware for user, I used the below command.

php artisan make:middleware user

In app/Http/Middleware/user.php: set condition if role ==0 then move on otherwise redirect to admin dashboard.

ree

app/Http/Kernel.php

Every application contains a HTTP kernel, it is live in app/Http/Kernel.php. The HTTP kernel or the console kernel serve as the central location, the incoming request is either sent to HTTP kernal or the console kernel. The HTTP kernel extents the Illuminate\Foundation\Http\Kernel class, it define an array of bootstrappers to configure error handling, configure logging, and implement other important tasks before the request is handled. Also HTTP kernel define a list of HTTP middleware to make sure requests must pass before being handled by application.

ree

I have added role and user middlewares in kernel.php.


In app/Http/Controller/HomtController: created methods for admin and user to handle the request.

I have renamed the index method to userIndex and redirect it to index method in ContactController.

ree

For admin, I have created adminIndex method, it retrieves all contacts, authenticates the user based on value of role column, and passes the retrieved data to admin-home view.

ree

I made sure to import below instances and class into HomeController.

use Illuminate\Support\Facades\Auth class will check the incoming HTTP request if it is authenticated return true.

use App\Models\Contact - Contact Model

use App\Models\User - User Model


In app/Http/Controller/Atuh/LoginController

- I created login method and defined request as variable.


public function login(Request $request){

}

- Inside the login method, I created $input variable and got all requests.

$input = $request->all();


- I set validation.

$this->validate($request,[

'email'=>'required|email',

'password'=>'required'

]);


- I set condition, if user role is = 1 then redirect to admin dashboard otherwise redirect to user dashboard.

if(auth()->attempt(array('email'=>$input['email'],'password'=>$input['password'] ))){

if(auth()->user()->role ==1){

return redirect()->route('admin.home');

}else{

return redirect()->route('home');

}

}else{

return redirect()->route('login');

}

ree

Make sure import use Illuminate\Http\Request; instance


Set up Route

Route/web.php: Rename index to userIndex from defined route and apply user middleware on it.

Route::get('/home', [App\Http\Controllers\HomeController::class, 'userIndex'])->name('home')

->middleware('user');


Define new route for admin and apply role middleware on it.

Route::get('/admin', [App\Http\Controllers\HomeController::class, 'adminIndex'])->name('admin.home')->middleware('role');


HTTP Exceptions

some exceptions explain HTTP error codes from the server. to generate error need to use the abort helper. In Laravel error (404) means "page not found" or error (401) means "unauthorized error"


In resources/views/home.blade.php

- Home page beside login and registration page by default have been created when I installed Laravel/ui package. I will build up this page as user dashboard and will use HTML code of this page as a template for other blade pages.

- @extends('layouts.app') - This way extends the app template, I defined a child view

- The body content will be place within @section and @endsection directives

- @if (session('status')) – It is used to display message for several purposes including redirecting, forgot password, reset password, email verification, success message for reset password. However, here in admin-home page, the @if (session('status')) has been used to displaying message for redirecting and deleting record.

- @foreach () - Blade provides this directive for looping purpose. I have used this directive to iterate the data and display them in table.

@can () - I have used this blade directive to the gate called facade.

- route () - Instead of URL helper method, I have used Named routes to generate url.

- @php($count=1) - Defined $count variable and looped it within for each loop to auto increment the table row in user dashboard.

ree


Gates - It is a primary way of authorizing actions that provides a simple and closure-based approach. I have define the gate within the boot method of the app -> Provider - > AuthServiceProvider class. Then through blade directive (@can), I have applied it in home.blade.php to authorize each user can only access their own contact list.

ree

In resources/views/admin-home.blade.php

I have copied HTML code of home.blade.php and pasted into admin-home with a few changes.

- @extends('layouts.app') // This way extends the app template, defines a child view

- The body content was placed within @section and @endsection directives

- @if (session('status')) – It is used to display message for several purposes including redirecting, forgot password, reset password, email verification, success message for reset password. However, here in admin-home page, the @if (session('status')) has been used to display message for redirecting.

- @foreach () - Blade provide this directive for looping purpose. I have used this directive to iterate the data and display them in table.


ree

Short Demo of Admin and User Login


 
 
 

Thanks for submitting!

© 2023 by DO IT YOURSELF. Proudly created with Wix.com

bottom of page