post-image

Những khái niệm cơ bản trong Laravel

Tổng quan

Giới thiệu

Trong bài viết này, mình sẽ giới thiệu tóm tắt nhất về những khái niệm cơ bản trong Laravel. Nội dung chính bao gồm:

  • Middleware
  • CSRF Token
  • Localization
  • Authentication với Authorization
  • Helpers
  • Eloquent với Query Builder
  • Eager Loading
  • Scope
  • Accessors và Mutator
  • Traint

Middleware

1. Khái niệm

Middleware là một thành phần trung gian nữa client và server, dùng để xử lý, lọc các HTTP request đi vào ứng dụng. Nếu request hợp lệ sẽ cho đi tiếp, còn không sẽ bị dừng lại hoặc redirect sang một trang khác.

2. Sử dụng trong Laravel

Khai báo một middleware

php artisan make:middleware CheckAdmin
Code language: CSS (css)
<?php namespace App\Http\Middleware; use Closure; class CheckAdmin { public function handle($request, Closure $next) { // Request sẽ được xử lý trong function handle() } }
Code language: HTML, XML (xml)

Tất cả các middleware được đăng ký trong file App\Http\Kernal.php. Nếu bạn muốn middleware được chạy ở mọi request thì sẽ khai báo trong $middleware property. Còn nếu muốn gán middleware cho một route xác định thì khai báo trong $routeMiddleware property.

protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'admin' => \App\Http\Middleware\Admin::class, ];
Code language: PHP (php)

CSRF Token

Laravel sẽ cung cấp một cách đơn giản để bảo về ứng dụng khỏi tấn công cross-site request forgery (CSRF) – Tấn công mạo danh. CSRF là loại tấn công mà hacker đánh lừa trình duyệt, sử dụng phiên làm việc của người dùng để gửi request lên ứng dụng Web.

Laravel sẽ tự động tạo một CSRF “token” cho mỗi hoạt động của user được quản lý bởi ứng ụng. Token này sẽ được tự động xác nhận khi user gửi request tới ứng dụng, nếu xác thực đúng thì mới được thực hiện.

  • Rất đơn giản để thực hiện, chỉ cần sử dụng @csrf trong form HTML
<form method="POST" action="/profile"> @csrf ... </form>
Code language: HTML, XML (xml)

Localization

Laravel’s localization (i18n) là một các tiện lợi để sử dụng đa ngôn ngữ trong ứng dụng. Các ngôn ngữ sẽ được chứa trong folder resources/lang

/resources /lang /en messages.php /es messages.php

Các ngôn ngữ chỉ cần trả về dạng key – value của một array:

<?php return [ 'welcome' => 'Welcome to our application', ];
Code language: HTML, XML (xml)

Bạn có thể chuyển đổi ngôn ngữ bằng cách sử dụng setLocate method của App facade

Route::get('welcome/{locale}', function ($locale) { App::setLocale($locale); });
Code language: PHP (php)

Để hiển thị ngôn ngữ, bạn có thể sử dụng các cách sau:

echo __('messages.welcome'); {{ __('messages.welcome') }} @lang('messages.welcome') @trans('messages.welcome')
Code language: PHP (php)

Authentication với Authorization

Authentication: là quá trình xác thực, định danh một tào khoản vào hệ thống. Nếu không có bước này, hệ thống sẽ không biết người đang truy cập là ai để có các phản hồi phù hợp. Ví dụ: Kiểm tra người dùng đó đã đăng nhập hay chưa

Authorization: sau khi xác thực được danh tính người dùng, thì bước tiếp theo phải xem người dùng đó có quyền được làm gì trong ứng dụng (phân quyền). Ví dụ: thực hiện phân quyền để không cho user này có thể thực hiện xóa bài viết của user khác.

Helpers

Là những function có thể sử dụng ở mọi nơi trên ứng dụng như là hàm url()dd()session()back(), … Ngoài ra, chúng ta còn có thể tự tạo các helpers function.

Khai báo file khởi tạo helpers bên trong autoload ở file composer.json

"autoload": { "files": [ "app/helpers.php" ], "classmap": [ "database/seeds", "database/factories" ], "psr-4": { "App\\": "app/" } },
Code language: JavaScript (javascript)

Sau đó, bạn cần chạy dump autoload:

composer dump-autoload

Khởi tạo function

if (!function_exists('total')) { function total($arrayCart) { // ... } }
Code language: PHP (php)

Bây giờ chỉ cần gọi tới hàm đó, thực hiện truyền các tham số như 1 hàm bình thường.

Eloquent với Query Builder

1. Bảo mật

  • Eloquent có tính bảo mật hơn Query Builder trong việc phòng chống SQL Injection

2. Tính dễ sử dụng

  • Eloquent ORM dễ sử dụng hơn trong việc truy xuất, thay đổi cơ sở dữ liệu, cú pháp ngắn gọn, đơn giản hơn QueryBuilder.
  • Eloquent ORM dễ dàng kết nối với database hơn QueryBuilder.
  • Về độ phức tạp của một câu SQL mà Eloquent ORM chưa thể đáp ứng thì chúng ta phải sử dụng DB::raw hoặc QueryBuilder.

3. Hiệu suất

  • QueryBuilder có hiệu suất truy vấn dữ liệu nhanh hơn Eloquent ORM bởi vì Eloquent phải thêm một lớp trong ứng dụng và yêu cầu nhiều truy vấn SQL. Đối với các database mà có ít bản ghi hiệu suất của chúng không có quá là nhiều sự chênh lệch, vậy nên đối với những database này tôi khuyên các bạn nên sử dụng Eloquent ORM vì cú pháp đơn giản và ngắn gọn của chúng.

Eager Loading

Dùng để giải quyết vấn đề N + 1 query, ví dụ ta query tất cả các bài viết và tất cả bình luận có quan hệ với bài viết. Vậy nếu có N bài viết thì chúng ta phải thực hiện N + 1 lần query (nếu bài viết càng nhiều thì sẽ query càng nhiều).

<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { public function comments() { return $this->belongsTo('App\Models\Comment'); } }
Code language: HTML, XML (xml)
$posts = App\Models\Post::all(); foreach ($posts as $post) { echo $post->comments->content; }
Code language: PHP (php)

Đây là cách mà câu lệnh hoạt động

SELECT * FROM posts; -- Foreach of the posts, another query to select the comments SELECT * FROM comments WHERE post_id = 1 SELECT * FROM comments WHERE post_id = 2 SELECT * FROM comments WHERE post_id = 3 SELECT * FROM comments WHERE post_id = 4 SELECT * FROM comments WHERE post_id = 5 .....
Code language: PHP (php)

Mỗi lần vòng lặp, ứng dụng sẽ thực hiện 1 query để lấy nội dung comment từ bài post. Để giải quyết vấn đề này, hãy sử dụng Eager Loading.

$posts = App\Models\Post::with('comments')->get(); foreach ($posts as $post) { $comments = $post->comments; // Tiếp tục thực hiện vòng lặp cho comments }
Code language: PHP (php)

Câu lệnh truy vấn sẽ như sau

// Select the posts i.e. Post::all(); SELECT * FROM posts; // Just One time get all comments with for that posts SELECT * FROM comments WHERE post_id IN (1, 2, 3, 4, 5, ...);
Code language: PHP (php)

Eager Loading với nhiều relationships

$posts = Post::with(['comments', 'author'])->get();
Code language: PHP (php)

Sự khác biệt giữa with() là load()

Post::with('comments')->get();
Code language: JavaScript (javascript)
Post::all()->load('comments');
Code language: PHP (php)

Như các bạn thấy thì with sẽ đứng trước từ khóa get, all, first, … nên nó sẽ mặc định thực hiện 2 câu lệnh truy vấn. Còn load đứng sau get, all, first nên sẽ linh hoạt trong việc thực hiện câu lệnh truy vấn thứ 2.

$posts = Post::all(); if $conditional) { $comments = $posts->load('comments'); }
Code language: PHP (php)

Tùy vào trường hợp ta có thể thực hiện giữa 2 câu lệnh này

Scope

Scope được sử dụng để tái sử dụng lại các câu lệnh truy vấn trong một model. Nếu có 1 câu lệnh được dùng đi dùng lại nhiều lần, ta có thể tạo thành scope để tái sử dụng và dễ dàng mở rộng.

Ví dụ: Hiển thị các user có role bằng 0:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function scopeRole($query) { return $query->where('role', 0); } }
Code language: HTML, XML (xml)

Để gọi câu lệnh scope chỉ cần thực hiện:

$user = User::role()->get(); // bạn có thể mở rộng câu lệnh này, ví dụ để hiển thị các user có role bằng 0 và gender = 1 $user = User::role()->where('gender', 1)->get();
Code language: PHP (php)

Truyền param cho scope

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function scopeRole($query, $num) { return $query->where('role', $num); } }
Code language: HTML, XML (xml)

Sử dụng: $user = User::role(0)->get();

Accessors và Mutators

Accessors và Mutators cho phép bạn format các giá trị của Eloquent được lấy ra hoặc thêm vào Model. Ví dụ, bạn muốn mã hóa mật khẩu trước khi thêm vào cơ sở dữ liệu.

1. Accessors

Sẽ được tự động gọi tự động khi thực hiện query, nó sẽ lấy giá trị từ column xác định -> format lại -> hiển thị ra.

Ví dụ: Tạo Accessors cho field full_name của table users

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function getFullNameAttribute($value) { return ucfirst($value); } }
Code language: HTML, XML (xml)

2. Mutators

Ngược lại với Accessors, Mutators dùng để format lại giá trị của một column xác định trước khi truyền vào cơ sở dữ liệu

Ví dụ: Tạo Mutators cho feild full_name

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function setFullNameAttribute($value) { return $this->attributes['full_name'] = strtolower($value); } }
Code language: HTML, XML (xml)

Traint

Train là class mà tương tự như Abstract Class dùng để khai báo các method, property để các các class khác có thể sử dụng. Nhưng Traint khác với Abstract là nó không dựa trên tính chất thừa kế, các class khác chỉ cần sử dụng từ khóa use để sử dụng các method và property của Traint.

Kết

Thế là hết rồi, hy vọng bạn có thể áp dụng được bài viết này vào ứng dụng của bạn.

Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Tham khảo: Viblo

Leave a Reply

Your email address will not be published. Required fields are marked *