Database: Seeding

Database: Seeding

01.08.2024
Author: ADMIN

Seeding trong Laravel là một cách để tự động thêm dữ liệu mẫu vào cơ sở dữ liệu của bạn. Điều này hữu ích khi bạn cần tạo ra dữ liệu thử nghiệm hoặc khởi tạo dữ liệu mặc định cho ứng dụng.

Tạo Seeder

Bạn có thể tạo một seeder mới bằng cách sử dụng lệnh Artisan:

php artisan make:seeder UsersTableSeeder

Lệnh này sẽ tạo một file seeder mới trong thư mục database/seeders.

Định Nghĩa Seeder

Khi bạn mở file seeder, nó sẽ trông giống như sau:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // Đoạn mã để chèn dữ liệu mẫu vào bảng users
    }
}

Bạn có thể sử dụng phương thức DB::table hoặc các phương thức của Eloquent để chèn dữ liệu vào bảng:

public function run()
{
    DB::table('users')->insert([
        'name' => Str::random(10),
        'email' => Str::random(10).'@gmail.com',
        'password' => bcrypt('password'),
    ]);
}

Hoặc sử dụng model Eloquent:

public function run()
{
    \App\Models\User::create([
        'name' => 'John Doe',
        'email' => 'johndoe@example.com',
        'password' => bcrypt('password'),
    ]);
}

Gọi Seeder

Sau khi định nghĩa seeder, bạn cần gọi nó trong lớp DatabaseSeeder để nó được chạy khi bạn chạy lệnh seed:

// database/seeders/DatabaseSeeder.php

public function run()
{
    $this->call(UsersTableSeeder::class);
}

Chạy Seeder

Bạn có thể chạy tất cả các seeder bằng lệnh Artisan:

php artisan db:seed

Hoặc chạy một seeder cụ thể:

php artisan db:seed --class=UsersTableSeeder

Tái Tạo Cơ Sở Dữ Liệu

Nếu bạn muốn làm mới cơ sở dữ liệu và chạy lại các seeder, bạn có thể sử dụng lệnh migrate:fresh:

php artisan migrate:fresh --seed

Lệnh này sẽ xóa tất cả các bảng trong cơ sở dữ liệu của bạn và chạy lại tất cả các migration và seeder.

Tùy chọn --seeder có thể được sử dụng để chỉ định một seeder cụ thể để chạy:

php artisan migrate:fresh --seed --seeder=UserSeeder

Sử Dụng Factory trong Seeder

Laravel có thể tích hợp factory với seeder để tạo ra dữ liệu mẫu phong phú hơn. Ví dụ, bạn có thể sử dụng factory để tạo nhiều người dùng một cách dễ dàng:

public function run()
{
    \App\Models\User::factory(10)->create();
}

Forcing Seeders to Run in Production

Khi làm việc với Laravel, bạn có thể muốn chạy seeder (tạo dữ liệu mẫu) ngay cả khi ứng dụng đang ở môi trường production. Điều này thường bị ngăn chặn để tránh nguy cơ làm hỏng dữ liệu thực tế. Tuy nhiên, đôi khi bạn vẫn cần phải chạy seeder trong môi trường production, và Laravel cung cấp cách để làm điều này một cách an toàn.

php artisan db:seed --force

Cờ --force sẽ bỏ qua cảnh báo và cho phép seeder chạy ngay cả khi ứng dụng đang ở môi trường production.

Ví dụ Thực Tế

Giả sử bạn có một seeder gọi là DatabaseSeeder và bạn muốn chạy nó trong môi trường production. Bạn chỉ cần chạy lệnh sau từ dòng lệnh:

php artisan db:seed --class=DatabaseSeeder --force

Lệnh trên sẽ thực hiện seeding dữ liệu từ DatabaseSeeder vào cơ sở dữ liệu hiện tại, ngay cả khi ứng dụng đang ở môi trường production.

Chạy Seeder Cụ Thể

Nếu bạn chỉ muốn chạy một seeder cụ thể trong môi trường production, bạn có thể chỉ định seeder đó với cờ --class cùng với --force. Ví dụ:

php artisan db:seed --class=UsersTableSeeder --force

Điều này sẽ chỉ chạy seeder UsersTableSeeder.

Sử Dụng Migrate với Seeder

Nếu bạn muốn chạy migration kèm theo seeder trong môi trường production, bạn có thể sử dụng lệnh migrate:fresh hoặc migrate cùng với cờ --seed--force:

php artisan migrate:fresh --seed --force
// or 
php artisan migrate --seed --force

Cả hai lệnh trên sẽ chạy migration để tạo lại hoặc cập nhật các bảng trong cơ sở dữ liệu và sau đó chạy seeder.

Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN

# Hiển Thị Biến Trong Blade

Trong Laravel Blade, việc hiển thị biến rất đơn giản và trực quan. Blade cung cấp cú pháp dễ đọc và sử dụng để nhúng các biến PHP vào trong HTML.

Cú Pháp Cơ Bản

Sử Dụng Cặp Dấu Ngoặc Nhanh {{ }}

Để hiển thị giá trị của một biến trong Blade, bạn chỉ cần sử dụng cặp dấu ngoặc nhanh {{ }}.

Ví Dụ

Giả sử bạn có một biến $name được truyền từ controller đến view:

public function show()
{
    $name = 'John Doe';
    return view('greeting', compact('name'));
}

Trong file view greeting.blade.php, bạn có thể hiển thị giá trị của biến $name như sau:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Greeting Page</title>
</head>
<body>
    <h1>Hello, {{ $name }}!</h1>
</body>
</html>

Escape HTML Đầu Vào

Khi sử dụng cặp dấu ngoặc nhanh {{ }}, Blade sẽ tự động escape (chuyển đổi các ký tự đặc biệt thành các thực thể HTML) để bảo vệ chống lại các cuộc tấn công XSS.

Ví Dụ

<?php $name = '<script>alert("XSS")</script>'; ?>

<h1>Hello, {{ $name }}!</h1>

Kết quả hiển thị sẽ là:

<h1>Hello, &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;!</h1>

Hiển Thị Biến Mà Không Escape HTML

Nếu bạn muốn hiển thị giá trị của biến mà không escape HTML, bạn có thể sử dụng cú pháp {!! !!}.

<?php $name = '<strong>John Doe</strong>'; ?>

<h1>Hello, {!! $name !!}!</h1>

Kết quả hiển thị sẽ là:

<h1>Hello, <strong>John Doe</strong>!</h1>

Hiển Thị Các Giá Trị Mặc Định

Bạn có thể hiển thị các giá trị mặc định khi biến không tồn tại hoặc rỗng bằng cách sử dụng toán tử null coalescing ??.

Ví Dụ

<h1>Hello, {{ $name ?? 'Guest' }}!</h1>

Nếu biến $name không tồn tại hoặc có giá trị là null, chuỗi 'Guest' sẽ được hiển thị.

Hiển Thị Mảng và Đối Tượng

Bạn có thể truy cập và hiển thị các phần tử của mảng hoặc thuộc tính của đối tượng một cách dễ dàng.

Ví Dụ Mảng

<?php $user = ['name' => 'John Doe', 'email' => 'john@example.com']; ?>

<h1>Name: {{ $user['name'] }}</h1>
<p>Email: {{ $user['email'] }}</p>

Ví Dụ Đối Tượng

<?php $user = (object) ['name' => 'John Doe', 'email' => 'john@example.com']; ?>

<h1>Name: {{ $user->name }}</h1>
<p>Email: {{ $user->email }}</p>

Tóm Tắt

  • Cú pháp cơ bản: Sử dụng {{ $variable }} để hiển thị giá trị của biến và tự động escape HTML.
  • Không escape HTML: Sử dụng {!! $variable !!} để hiển thị giá trị của biến mà không escape HTML.
  • Giá trị mặc định: Sử dụng {{ $variable ?? 'default' }} để hiển thị giá trị mặc định khi biến không tồn tại hoặc rỗng.
  • Mảng và đối tượng: Truy cập và hiển thị các phần tử của mảng hoặc thuộc tính của đối tượng bằng cú pháp {{ $array['key'] }}{{ $object->property }}.

Việc sử dụng các cú pháp này giúp bạn dễ dàng và an toàn khi hiển thị dữ liệu trong các view Blade của Laravel.

Một số lệnh Artisan Make với các tham số

Một số lệnh Artisan Make với các tham số

01.08.2024
Author: ADMIN

Laravel cung cấp nhiều lệnh Artisan để tạo các thành phần khác nhau trong ứng dụng. Dưới đây là danh sách các lệnh make cùng với các tham số phổ biến mà bạn có thể sử dụng.

1. Make Controller

php artisan make:controller {name} [--resource] [--api] [--invokable] [--model[=MODEL]] [--parent] [--requests] [--singleton] [--force]
  • --resource: Controller sẽ chứa một phương thức cho mỗi hoạt động tài nguyên có sẵn - index(), create(), store(), show(), edit(), update(), destroy().
  • --api: Tương tự như -resource ở trên, nhưng chỉ tạo ra 5 phương thức: index(), store(), show(), update(), destroy(). Bởi vì các biểu mẫu tạo/sửa không cần thiết cho API.
  • --invokable: Tạo một controller với một phương thức __invoke duy nhất.
  • --model[=MODEL]: Tạo controller với mô hình được liên kết.
  • --requests: Tạo các lớp request form cho controller.

2. Make Model

php artisan make:model {name} [--migration] [--controller] [--resource] [--factory] [--seed] [--policy] [--all] [--pivot]
  • --migration: Tạo migration cho mô hình.
  • --controller: Tạo controller cho mô hình.
  • --resource: Tạo controller tài nguyên cho mô hình.
  • --factory: Tạo factory cho mô hình.
  • --seed: Tạo seeder cho mô hình.
  • --policy: Tạo policy cho mô hình.
  • --all: Tạo migration, factory, seeder, policy, và controller cho mô hình.
  • --pivot: Tạo mô hình pivot.

3. Make Migration

php artisan make:migration {name} [--create[=TABLE]] [--table[=TABLE]] [--path[=PATH]] [--realpath] [--fullpath]
  • --create[=TABLE]: Tạo migration cho bảng mới.
  • --table[=TABLE]: Tạo migration để cập nhật bảng hiện có.

4. Make Seeder

php artisan make:seeder {name}

5. Make Factory

php artisan make:factory {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết factory với mô hình.

6. Make Middleware

php artisan make:middleware {name}

7. Make Request

php artisan make:request {name}

8. Make Event

php artisan make:event {name}

9. Make Listener

php artisan make:listener {name} [--event[=EVENT]]
  • --event[=EVENT]: Liên kết listener với sự kiện.

10. Make Job

php artisan make:job {name} [--sync]
  • --sync: Tạo job đồng bộ.

11. Make Notification

php artisan make:notification {name}

12. Make Mail

php artisan make:mail {name} [--markdown[=MARKDOWN]]
  • --markdown[=MARKDOWN]: Tạo email với template markdown.

13. Make Command

php artisan make:command {name} [--command[=COMMAND]]
  • --command[=COMMAND]: Tên của lệnh console.

14. Make Policy

php artisan make:policy {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết policy với mô hình.

15. Make Provider

php artisan make:provider {name}

16. Make Test

php artisan make:test {name} [--unit] [--pest]
  • --unit: Tạo test đơn vị.
  • --pest: Tạo test Pest.

17. Make Rule

php artisan make:rule {name}

18. Make Observer

php artisan make:observer {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết observer với mô hình.

19. Make Channel

php artisan make:channel {name}

20. Make Resource

php artisan make:resource {name}

Trên đây là một số command mà tôi hay sử dụng, ngoài các command này, bạn có thể sử dụng command php artisan list để liệt kê tất cả command artisan tính đến thời điểm hiện tại

Database: Pagination

Database: Pagination

01.08.2024
Author: ADMIN

# Database: Pagination

Phân trang (pagination) là một kỹ thuật quan trọng để phân chia dữ liệu lớn thành các trang nhỏ hơn, giúp người dùng dễ dàng duyệt qua dữ liệu mà không phải tải toàn bộ dữ liệu cùng một lúc. Laravel cung cấp các phương pháp đơn giản để thực hiện phân trang với Eloquent và Query Builder.

1. Phân Trang Với Eloquent

Khi sử dụng Eloquent để truy vấn dữ liệu, bạn có thể sử dụng phương thức paginate để phân trang kết quả. Ví dụ, giả sử bạn có một model Post, bạn có thể phân trang các bài viết như sau:

// Lấy 10 bài viết mỗi trang
$posts = App\Models\Post::paginate(10);
// or 
$users = DB::table('users')->paginate(10);
  • paginate($perPage): Phương thức này trả về một đối tượng LengthAwarePaginator, chứa các bài viết cho trang hiện tại và thông tin phân trang.

Bạn có thể sử dụng biến $posts trong view Blade để hiển thị dữ liệu và các liên kết phân trang:

@foreach ($posts as $post)
    <div>{{ $post->title }}</div>
@endforeach

{{ $posts->links() }}

2. Phân Trang Tuỳ Chỉnh

Bạn có thể tùy chỉnh phân trang bằng cách thay đổi số lượng bản ghi trên mỗi trang hoặc thêm các tham số khác:

// Lấy 15 bản ghi mỗi trang và tùy chỉnh các tham số khác
$posts = App\Models\Post::paginate(15, ['*'], 'page', $currentPage);

$currentPage: Bạn có thể chỉ định số trang hiện tại nếu cần thiết.

# Tùy Chỉnh URL Phân Trang

Laravel cho phép bạn tùy chỉnh URL phân trang để phù hợp với các yêu cầu hoặc cấu trúc URL của ứng dụng. Đây là các cách bạn có thể thực hiện việc này:

1. Tùy Chỉnh Tham Số URL

Bạn có thể tùy chỉnh các tham số của URL phân trang bằng cách sử dụng phương thức appends để thêm các tham số bổ sung vào các liên kết phân trang. Ví dụ, nếu bạn muốn giữ lại các tham số truy vấn hiện tại trong URL phân trang:

$posts = App\Models\Post::paginate(10)->appends(['sort' => 'desc']);
  • appends($array): Thêm các tham số bổ sung vào URL phân trang.

Ví dụ trong view Blade:

@foreach ($posts as $post)
    <div>{{ $post->title }}</div>
@endforeach

{{ $posts->appends(['sort' => 'desc'])->links() }}

2. Tùy Chỉnh Đường Dẫn Phân Trang

$users->withPath('/admin/users');

withPath('/admin/users'): Phương thức này được sử dụng để tùy chỉnh đường dẫn phân trang. Thay vì sử dụng đường dẫn mặc định, bạn có thể chỉ định một đường dẫn khác cho các liên kết phân trang.

# Các Phương Thức Của Paginator / LengthAwarePaginator

Khi làm việc với phân trang trong Laravel, bạn sẽ thường xuyên sử dụng các phương thức của lớp Paginator hoặc LengthAwarePaginator. Dưới đây là các phương thức chính và cách sử dụng chúng:

$users = User::paginate(15);

// Số mục trên trang hiện tại
$count = $users->count();

// Số trang hiện tại
$currentPage = $users->currentPage();

// Số thứ tự của mục đầu tiên
$firstItem = $users->firstItem();

// Các tùy chọn phân trang
$options = $users->getOptions();

// Dãy URL từ trang 1 đến trang 5
$urls = $users->getUrlRange(1, 5);

// Kiểm tra có nhiều trang không
$hasPages = $users->hasPages();

// Kiểm tra có còn trang kế tiếp không
$hasMore = $users->hasMorePages();

// Các mục trên trang hiện tại
$items = $users->items();

// Số thứ tự của mục cuối cùng
$lastItem = $users->lastItem();

// Số trang cuối cùng
$lastPage = $users->lastPage();

// URL của trang kế tiếp
$nextPageUrl = $users->nextPageUrl();

// Kiểm tra có đang ở trang đầu tiên không
$onFirstPage = $users->onFirstPage();

// Số lượng mục trên mỗi trang
$perPage = $users->perPage();

// URL của trang trước đó
$previousPageUrl = $users->previousPageUrl();

// Tổng số mục
$total = $users->total();

// URL của trang số 2
$url = $users->url(2);

// Biến truy vấn để lưu trữ số trang
$pageName = $users->getPageName();

// Đặt tên biến truy vấn để lưu trữ số trang
$users->setPageName('page');

// Chuyển đổi từng mục để chỉ lấy tên người dùng return $user->name;
$transformedUsers = $users->through(function ($user) {
    return $user->name;
});

# Các Phương Thức Của CursorPaginator

Method Description
$paginator->count()
Số mục trên trang hiện tại
$paginator->cursor()
Đối tượng con trỏ hiện tại
$paginator->getOptions()
Các tùy chọn phân trang
$paginator->hasPages()
Kiểm tra có nhiều trang không
$paginator->hasMorePages()
Kiểm tra có còn mục nào không
$paginator->getCursorName()
Biến truy vấn để lưu trữ con trỏ
$paginator->items()
Các mục trên trang hiện tại
$paginator->nextCursor()
Con trỏ cho tập hợp mục tiếp theo
$paginator->nextPageUrl()
URL của trang kế tiếp
$paginator->onFirstPage()
Kiểm tra có đang ở trang đầu tiên không
$paginator->onLastPage()
Kiểm tra có đang ở trang cuối cùng không
$paginator->perPage()
Số lượng mục trên mỗi trang
$paginator->previousCursor()
Con trỏ cho tập hợp mục trước đó
$paginator->previousPageUrl()
URL của trang trước đó
$paginator->setCursorName()
Đặt tên biến truy vấn để lưu trữ con trỏ
$paginator->url($cursor)
 URL cho con trỏ cụ thể
File Uploads

File Uploads

01.08.2024
Author: ADMIN

# File Uploads

Trong ứng dụng web, một trong những trường hợp sử dụng phổ biến nhất để lưu trữ tệp là lưu trữ các tệp được người dùng tải lên như hình ảnh và tài liệu. Laravel làm cho việc lưu trữ các files được upload rất dễ dàng bằng cách sử dụng phương thức store với tệp đã được upload. Gọi phương thức store với đường dẫn mà bạn muốn lưu trữ tệp được tải lên:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
 
class UserAvatarController extends Controller
{
    /**
     * Update the avatar for the user.
     */
    public function update(Request $request): string
    {
        $path = $request->file('avatar')->store('avatars');
 
        return $path;
    }
}

Có một số điều quan trọng cần lưu ý về ví dụ này. Lưu ý rằng chúng ta chỉ chỉ định tên thư mục, không phải tên tệp. Theo mặc định, phương thức store sẽ tạo ra một ID duy nhất để làm tên tệp. Phần mở rộng của tệp sẽ được xác định bằng cách kiểm tra loại MIME của tệp. Đường dẫn đến tệp sẽ được trả về bởi phương thức store để bạn có thể lưu trữ đường dẫn, bao gồm tên tệp được tạo ra, trong cơ sở dữ liệu của bạn. Bạn cũng có thể gọi phương thức putFile trên Storage facade để thực hiện cùng một hoạt động lưu trữ tệp như ví dụ trên:

$path = Storage::putFile('avatars', $request->file('avatar'));

# Chỉ định một tên tệp

Nếu bạn không muốn tự động gán tên tệp cho tệp đã lưu của mình, bạn có thể sử dụng phương thức storeAs, nhận đường dẫn, tên tệp và ổ đĩa (tùy chọn) là đối số của nó:

$path = $request->file('avatar')->storeAs(
    'avatars', $request->user()->id
);

Bạn cũng có thể sử dụng phương thức putFileAs trên Storage facade, sẽ thực hiện cùng một hoạt động lưu trữ tập tin như ví dụ trên:

$path = Storage::putFileAs(
    'avatars', $request->file('avatar'), $request->user()->id
);

# Chỉ định một ổ đĩa

Theo mặc định, phương thức lưu trữ của tệp tải lên này sẽ sử dụng ổ đĩa mặc định của bạn. Nếu bạn muốn chỉ định một ổ đĩa khác, hãy truyền tên ổ đĩa như là đối số thứ hai cho phương thức lưu trữ:

$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

// or
$path = $request->file('avatar')->storeAs(
    'avatars',
    $request->user()->id,
    's3'
);

# Thông tin file đã upload

// Lấy tên gốc của tập tin
$originalName = $file->getClientOriginalName();

// Lấy phần mở rộng của tập tin
$extension = $file->getClientOriginalExtension();

// Lấy kích thước của tập tin (đơn vị: byte)
$size = $file->getSize();

// Lấy MIME type của tập tin
$mimeType = $file->getMimeType();

// Lưu tập tin
$path = $file->store('uploads', 'public');

Tuy nhiên, hãy nhớ rằng các phương thức getClientOriginalName và getClientOriginalExtension được coi là không an toàn, vì tên tập tin và phần mở rộng có thể bị người dùng độc hại can thiệp. Vì lý do này, bạn nên thường chọn phương thức hashName và phần mở rộng để có được tên và phần mở rộng cho tệp tải lên cụ thể:

$file = $request->file('avatar');
 
$name = $file->hashName(); // Generate a unique, random name...
$extension = $file->extension(); // Determine the file's extension based on the file's MIME type...

# File Visibility

Trong tích hợp Flysystem của Laravel, "visibility" là một sự trừu tượng hóa của các quyền tập tin trên nhiều nền tảng khác nhau. Các tập tin có thể được khai báo là công khai (public) hoặc riêng tư (private). Khi một tập tin được khai báo là công khai, bạn đang chỉ định rằng tập tin đó thường nên được truy cập bởi những người khác. Ví dụ, khi sử dụng driver S3, bạn có thể lấy URL cho các tập tin công khai.

Thiết Lập Tính Năng Hiển Thị Tập Tin

Lưu Trữ Tập Tin Công Khai

Bạn có thể lưu trữ một tập tin và chỉ định nó là công khai như sau:

use Illuminate\Support\Facades\Storage;

$content = 'Nội dung của tập tin';
Storage::put('file.jpg', $content, 'public');

Nếu tập tin đã được lưu trữ, bạn có thể lấy và thiết lập tính năng hiển thị của nó thông qua các phương thức getVisibilitysetVisibility.

$visibility = Storage::getVisibility('file.jpg');

Storage::setVisibility('file.jpg', 'public');

Khi làm việc với các tập tin được tải lên, bạn có thể sử dụng các phương thức storePubliclystorePubliclyAs để lưu trữ tập tin với tính năng hiển thị công khai.

Phương Thức storePublicly

Phương thức storePublicly sẽ lưu trữ tập tin được tải lên với tính năng hiển thị công khai.

$path = $request->file('avatar')->storePublicly('avatars', 's3');

Phương Thức storePubliclyAs

Phương thức storePubliclyAs cho phép bạn chỉ định tên tập tin khi lưu trữ với tính năng hiển thị công khai.

$path = $request->file('avatar')->storePubliclyAs(
    'avatars',
    $request->user()->id,
    's3'
);

Tập Tin Cục Bộ và Tính Năng Hiển Thị

Khi sử dụng driver cục bộ (local), tính năng hiển thị công khai được dịch thành quyền 0755 cho thư mục và 0644 cho tập tin. Bạn có thể chỉnh sửa các phép ánh xạ quyền này trong tệp cấu hình filesystems của ứng dụng của bạn.

Cấu Hình filesystems.php

Trong tệp config/filesystems.php, bạn có thể cấu hình quyền truy cập cho driver cục bộ như sau:

'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
    'permissions' => [
        'file' => [
            'public' => 0644,
            'private' => 0600,
        ],
        'dir' => [
            'public' => 0755,
            'private' => 0700,
        ],
    ],
],

Giải Thích

  • Driver: local là driver cục bộ mà Laravel cung cấp để lưu trữ tập tin trên hệ thống tệp cục bộ.
  • Root: Đường dẫn gốc nơi các tập tin sẽ được lưu trữ. Mặc định là storage_path('app'), nghĩa là thư mục storage/app trong ứng dụng của bạn.
  • Permissions: Đây là nơi bạn có thể chỉ định quyền truy cập cho tập tin và thư mục dựa trên tính năng hiển thị của chúng.
    • File:
      • public (0644): Quyền truy cập công khai cho tập tin, cho phép chủ sở hữu có thể đọc và ghi, trong khi người dùng khác chỉ có thể đọc.
      • private (0600): Quyền truy cập riêng tư cho tập tin, chỉ cho phép chủ sở hữu có thể đọc và ghi.
    • Dir:
      • public (0755): Quyền truy cập công khai cho thư mục, cho phép chủ sở hữu có thể đọc, ghi và thực thi, trong khi người dùng khác chỉ có thể đọc và thực thi.
      • private (0700): Quyền truy cập riêng tư cho thư mục, chỉ cho phép chủ sở hữu có thể đọc, ghi và thực thi.

# Deleting Files

Trong Laravel, bạn có thể dễ dàng xóa các tập tin đã được lưu trữ bằng cách sử dụng các phương thức được cung cấp bởi Storage facade. Dưới đây là các phương pháp phổ biến để xóa tập tin trong Laravel.

Xóa Tập Tin Đơn Lẻ

Để xóa một tập tin đơn lẻ, bạn có thể sử dụng phương thức delete:

use Illuminate\Support\Facades\Storage;

Storage::delete('path/to/file.jpg');

Xóa Nhiều Tập Tin

Nếu bạn cần xóa nhiều tập tin cùng lúc, bạn có thể truyền một mảng các đường dẫn tập tin vào phương thức delete:

use Illuminate\Support\Facades\Storage;

Storage::delete([
    'path/to/file1.jpg',
    'path/to/file2.jpg',
    'path/to/file3.jpg'
]);

Kiểm Tra Tập Tin Trước Khi Xóa

Bạn có thể kiểm tra xem tập tin có tồn tại hay không trước khi xóa bằng cách sử dụng phương thức exists:

use Illuminate\Support\Facades\Storage;

if (Storage::exists('path/to/file.jpg')) {
    Storage::delete('path/to/file.jpg');
}

Xóa Tập Tin Cục Bộ

Nếu bạn đang làm việc với các tập tin cục bộ và muốn xóa chúng, bạn có thể sử dụng phương thức unlink của PHP. Tuy nhiên, sử dụng Storage facade của Laravel là cách tiếp cận tốt hơn vì nó trừu tượng hóa các chi tiết của hệ thống tập tin cơ bản:

use Illuminate\Support\Facades\Storage;

Storage::disk('local')->delete('path/to/file.jpg');

Xóa Thư Mục

Bạn có thể xóa cả một thư mục và tất cả các tập tin trong đó bằng phương thức deleteDirectory:

use Illuminate\Support\Facades\Storage;

Storage::deleteDirectory('path/to/directory');

Lấy Tất Cả Các Tập Tin Trong Một Thư Mục

Để lấy danh sách tất cả các tập tin trong một thư mục, bạn có thể sử dụng phương thức files của Storage facade:

use Illuminate\Support\Facades\Storage;

$files = Storage::files('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các tập tin trong thư mục được chỉ định.

Lấy Tất Cả Các Tập Tin Kể Cả Trong Các Thư Mục Con

Nếu bạn muốn lấy tất cả các tập tin bao gồm cả trong các thư mục con, bạn có thể sử dụng phương thức allFiles:

use Illuminate\Support\Facades\Storage;

$allFiles = Storage::allFiles('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các tập tin, kể cả trong các thư mục con của thư mục được chỉ định.

Lấy Tất Cả Các Thư Mục Con Trong Một Thư Mục

Để lấy danh sách tất cả các thư mục con trong một thư mục, bạn có thể sử dụng phương thức directories:

use Illuminate\Support\Facades\Storage;

$directories = Storage::directories('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các thư mục con trong thư mục được chỉ định.

Lấy Tất Cả Các Thư Mục Con Bao Gồm Cả Trong Các Thư Mục Con Khác

Nếu bạn muốn lấy tất cả các thư mục con bao gồm cả trong các thư mục con khác, bạn có thể sử dụng phương thức allDirectories:

use Illuminate\Support\Facades\Storage;

$allDirectories = Storage::allDirectories('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các thư mục con, kể cả trong các thư mục con khác của thư mục được chỉ định.

Tạo Một Thư Mục

Để tạo một thư mục mới, bạn có thể sử dụng phương thức makeDirectory:

use Illuminate\Support\Facades\Storage;

Storage::makeDirectory('path/to/directory');

-----------------------------------------------------------------------------------------------------------------------------------------

# Example:

Trước khi bắt đầu, hãy chắc chắn rằng thư mục lưu trữ tập tin tải lên có quyền ghi. Thư mục mặc định là storage/app/public.

Tạo symbolic link: Chạy lệnh sau để tạo một symbolic link từ public/storage tới storage/app/public:

php artisan storage:link

Tạo Form Để Tải Lên Tập Tin

Đầu tiên, bạn cần tạo một form để người dùng có thể chọn tập tin để tải lên.

Ví Dụ Form Trong Blade:
<form action="{{ route('upload') }}" method="POST" enctype="multipart/form-data">
    @csrf
    <div>
        <label for="file">Choose file</label>
        <input type="file" id="file" name="file">
        @error('file')
            <div class="error">{{ $message }}</div>
        @enderror
    </div>
    <button type="submit">Upload</button>
</form>

Lưu ý rằng bạn cần sử dụng enctype="multipart/form-data" trong thẻ <form> để có thể tải lên tập tin.

Xử Lý Yêu Cầu Tải Lên Trong Controller

Tiếp theo, tạo một phương thức trong controller để xử lý việc tải lên tập tin.

Ví Dụ Trong Controller:
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class FileUploadController extends Controller
{
    public function upload(Request $request)
    {
        // Kiểm tra dữ liệu
        $request->validate([
            'file' => 'required|file|mimes:jpg,png,pdf|max:2048',
        ]);

        // Lưu tập tin
        if ($request->file('file')->isValid()) {
            $path = $request->file('file')->store('uploads', 'public');

            return back()->with('success', 'File uploaded successfully.')->with('file', $path);
        }

        return back()->with('error', 'There was an error uploading your file.');
    }
}

Cấu Hình Route

Cuối cùng, cấu hình route để xử lý form upload.

Ví Dụ Trong web.php:
use App\Http\Controllers\FileUploadController;

Route::get('/upload', function () {
    return view('upload');
})->name('upload.form');

Route::post('/upload', [FileUploadController::class, 'upload'])->name('upload');
Route Resource and Resourceful Controllers

Route Resource and Resourceful Controllers

01.08.2024
Author: ADMIN

# Resource Controllers

Resource Controllers trong Laravel cung cấp một cách thuận tiện để xử lý các hành động CRUD (Create, Read, Update, Delete) cho các tài nguyên của bạn. Khi bạn tạo một Resource Controller, Laravel sẽ tự động tạo ra các phương thức xử lý các hành động CRUD tiêu chuẩn. Điều này giúp bạn giảm bớt việc phải viết mã thủ công cho các hành động lặp đi lặp lại.

1. Tạo Resource Controller

Để tạo một Resource Controller, bạn sử dụng lệnh Artisan sau:

php artisan make:controller UserController --resource

Lệnh này sẽ tạo ra một controller mới tên là UserController với các phương thức mặc định cho các hành động CRUD. Đây là các phương thức được tạo ra:

  • index(): Hiển thị danh sách tài nguyên.
  • create(): Hiển thị form để tạo tài nguyên mới.
  • store(): Lưu trữ tài nguyên mới vào cơ sở dữ liệu.
  • show($id): Hiển thị chi tiết một tài nguyên cụ thể.
  • edit($id): Hiển thị form để chỉnh sửa một tài nguyên cụ thể.
  • update(Request $request, $id): Cập nhật tài nguyên cụ thể trong cơ sở dữ liệu.
  • destroy($id): Xóa một tài nguyên cụ thể khỏi cơ sở dữ liệu.

2. Route Resource

Để định tuyến đến Resource Controller, bạn có thể sử dụng phương thức Route::resource. Ví dụ:

use Illuminate\Support\Facades\Route;

Route::resource('users', UserController::class);

Lệnh này sẽ tự động tạo ra tất cả các tuyến đường cần thiết cho các hành động CRUD tương ứng với các phương thức trong UserController.

# Actions Handled by Resource Controllers

Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

# Tùy Chỉnh Hành Vi Khi Model Không Tồn Tại với Phương Thức missing

Thường thì, một phản hồi HTTP 404 sẽ được tạo ra nếu một resource model không được tìm thấy. Tuy nhiên, bạn có thể tùy chỉnh hành vi này bằng cách gọi phương thức missing khi xác định resource route của bạn. Phương thức missing chấp nhận một closure sẽ được gọi nếu một Model được ràng buộc một cách ngầm định không thể tìm thấy cho bất kỳ resource's routes nào:

use App\Http\Controllers\UserController;
use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::resource('users', UserController::class)
    ->missing(function (Request $request) {
         return response()->view('errors.custom', [], 404);
});

Trong ví dụ trên, nếu một mô hình User không được tìm thấy khi truy cập bất kỳ tuyến đường tài nguyên nào của users, Laravel sẽ trả về một view tùy chỉnh errors.custom với mã trạng thái 404.

# Soft Deleted Models

Trong Laravel, tính năng Soft Deletes cho phép bạn "xóa" các bản ghi khỏi cơ sở dữ liệu mà không thực sự xóa chúng. Thay vì bị xóa, một bản ghi sẽ được đánh dấu là đã xóa bằng cách thiết lập giá trị của cột deleted_at thành thời điểm hiện tại. Điều này giúp bạn dễ dàng khôi phục các bản ghi đã bị xóa nếu cần thiết.

1. Thiết lập Soft Deletes cho một Model

Để sử dụng Soft Deletes, bạn cần làm theo các bước sau:

Thêm cột deleted_at vào bảng

Bạn có thể sử dụng migration để thêm cột deleted_at vào bảng của bạn:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddDeletedAtToUsersTable extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->softDeletes();
        });
    }

    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropSoftDeletes();
        });
    }
}
Sử dụng trait SoftDeletes trong model

Bạn cần thêm trait SoftDeletes vào model của bạn:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;

    protected $dates = ['deleted_at'];
}

2. Sử dụng Soft Deletes

Xóa mềm một bản ghi

Để xóa mềm một bản ghi, bạn chỉ cần gọi phương thức delete:

$user = User::find(1);
$user->delete();
Khôi phục một bản ghi đã bị xóa mềm

Bạn có thể khôi phục một bản ghi đã bị xóa mềm bằng phương thức restore:

$user = User::withTrashed()->find(1);
$user->restore();
Xóa vĩnh viễn một bản ghi

Để xóa vĩnh viễn một bản ghi, bạn có thể sử dụng phương thức forceDelete:

$user = User::withTrashed()->find(1);
$user->forceDelete();

3. Truy vấn với Soft Deletes

Lấy các bản ghi chưa bị xóa

Mặc định, các truy vấn Eloquent sẽ chỉ lấy các bản ghi chưa bị xóa:

$users = User::all();
Lấy tất cả các bản ghi, bao gồm cả bản ghi đã bị xóa

Bạn có thể sử dụng phương thức withTrashed để lấy tất cả các bản ghi, bao gồm cả những bản ghi đã bị xóa:

$users = User::withTrashed()->get();
Chỉ lấy các bản ghi đã bị xóa

Bạn có thể sử dụng phương thức onlyTrashed để chỉ lấy những bản ghi đã bị xóa mềm:

$users = User::onlyTrashed()->get();

4. Các phương thức bổ sung

Kiểm tra xem một bản ghi đã bị xóa hay chưa

Bạn có thể sử dụng phương thức trashed để kiểm tra xem một bản ghi đã bị xóa mềm hay chưa:

$user = User::withTrashed()->find(1);

if ($user->trashed()) {
    // Bản ghi đã bị xóa mềm
}

# Nested Resources

Nested Resources (tài nguyên lồng nhau) cho phép bạn định nghĩa các tuyến đường tài nguyên lồng nhau để biểu diễn mối quan hệ giữa các mô hình. Điều này thường được sử dụng khi một mô hình có mối quan hệ với một mô hình khác, ví dụ như PostComment.

1. Định Nghĩa Nested Resources

Bạn có thể định nghĩa các nested resources trong tệp định tuyến của mình (routes/web.php). Dưới đây là một ví dụ về cách định nghĩa nested resources cho PostComment:

use App\Http\Controllers\PostController;
use App\Http\Controllers\CommentController;
use Illuminate\Support\Facades\Route;

Route::resource('posts', PostController::class);

Route::resource('posts.comments', CommentController::class);

2. URL và Tên Định Tuyến cho Nested Resources

Khi bạn định nghĩa nested resources, Laravel sẽ tự động tạo ra các tuyến đường với các URL và tên định tuyến tương ứng.

Ví dụ URL và tên định tuyến:
  • GET /posts - posts.index
  • GET /posts/{post} - posts.show
  • GET /posts/{post}/comments - posts.comments.index
  • GET /posts/{post}/comments/{comment} - posts.comments.show

3. Sử Dụng Nested Resources trong Controller

Bạn có thể sử dụng nested resources trong controller của bạn để quản lý các hành động liên quan đến mô hình lồng nhau.

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Comment;
use Illuminate\Http\Request;

class CommentController extends Controller
{
    public function index(Post $post)
    {
        $comments = $post->comments;
        return view('comments.index', compact('comments'));
    }

    public function show(Post $post, Comment $comment)
    {
        return view('comments.show', compact('post', 'comment'));
    }

    public function create(Post $post)
    {
        return view('comments.create', compact('post'));
    }

    public function store(Request $request, Post $post)
    {
        $validatedData = $request->validate([
            'body' => 'required|max:255',
        ]);

        $post->comments()->create($validatedData);

        return redirect()->route('posts.comments.index', $post);
    }

    public function edit(Post $post, Comment $comment)
    {
        return view('comments.edit', compact('post', 'comment'));
    }

    public function update(Request $request, Post $post, Comment $comment)
    {
        $validatedData = $request->validate([
            'body' => 'required|max:255',
        ]);

        $comment->update($validatedData);

        return redirect()->route('posts.comments.index', $post);
    }

    public function destroy(Post $post, Comment $comment)
    {
        $comment->delete();

        return redirect()->route('posts.comments.index', $post);
    }
}

4. Ràng Buộc Ngầm Định và Nested Resources

Laravel tự động ràng buộc các Model cho các nested resources. Khi bạn định nghĩa một nested resource, Laravel sẽ tự động ràng buộc các Model cha cho các tuyến đường con. Ví dụ, trong CommentController, mô hình Post sẽ tự động được ràng buộc trước khi mô hình Comment.

Nested resources cung cấp một cách rõ ràng và dễ dàng để quản lý mối quan hệ giữa các mô hình trong ứng dụng Laravel của bạn. Bằng cách sử dụng nested resources, bạn có thể tạo ra các tuyến đường và controller hành động cho các mô hình lồng nhau một cách trực quan và dễ dàng.

 

Các Mối Quan Hệ Trong Eloquent

Các Mối Quan Hệ Trong Eloquent

01.08.2024
Author: ADMIN

# Các Mối Quan Hệ Trong Eloquent

Eloquent cung cấp một hệ thống mạnh mẽ để quản lý các mối quan hệ giữa các mô hình trong cơ sở dữ liệu. Các mối quan hệ giúp bạn dễ dàng lấy dữ liệu liên quan từ các bảng khác nhau. Dưới đây là các loại mối quan hệ phổ biến trong Eloquent và cách sử dụng chúng:

1. Mối Quan Hệ Một-Một (One-to-One)

Một mối quan hệ một-một liên kết hai mô hình với nhau, với mỗi bản ghi trong bảng đầu tiên liên kết với một bản ghi trong bảng thứ hai.

Ví Dụ:

// Mô hình User
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}

// Mô hình Profile
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Cấu Trúc Bảng:

  • users table: id, name
  • profiles table: id, user_id, bio

2. Mối Quan Hệ Một-Nhiều (One-to-Many)

Một mối quan hệ một-nhiều cho phép một bản ghi trong bảng đầu tiên liên kết với nhiều bản ghi trong bảng thứ hai.

Ví Dụ:

// Mô hình Post
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

// Mô hình Comment
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    public function post()
    {
        return $this->belongsTo(Post::class);
    }
}

Cấu Trúc Bảng:

  • posts table: id, title
  • comments table: id, post_id, content

3. Mối Quan Hệ Nhiều-Nhiều (Many-to-Many)

Mối quan hệ nhiều-nhiều cho phép nhiều bản ghi trong bảng đầu tiên liên kết với nhiều bản ghi trong bảng thứ hai thông qua bảng trung gian.

Ví Dụ:

// Mô hình Student
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    public function courses()
    {
        return $this->belongsToMany(Course::class);
    }
}

// Mô hình Course
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Course extends Model
{
    public function students()
    {
        return $this->belongsToMany(Student::class);
    }
}

Cấu Trúc Bảng:

  • students table: id, name
  • courses table: id, title
  • course_student table: student_id, course_id

4. Mối Quan Hệ Một-Một (Polymorphic)

Mối quan hệ polymorphic cho phép một mô hình liên kết với nhiều mô hình khác theo cách linh hoạt.

Ví Dụ:

// Mô hình Comment
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

// Mô hình Post
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

// Mô hình Video
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Cấu Trúc Bảng:

  • comments table: id, commentable_id, commentable_type, content
  • posts table: id, title
  • videos table: id, title

5. Mối Quan Hệ Một-Nhiều (Polymorphic)

 

Mối quan hệ một-nhiều polymorphic cho phép một mô hình liên kết với nhiều mô hình khác mà không cần phải tạo ra nhiều cột khóa ngoại. Điều này rất hữu ích khi bạn muốn một mô hình có thể liên kết với nhiều loại mô hình khác mà không cần tạo nhiều bảng trung gian.

Ví Dụ Cụ Thể

Giả sử bạn có một hệ thống mà người dùng có thể bình luận trên các bài viết (Post) và video (Video). Bạn có thể sử dụng mối quan hệ polymorphic để xử lý các bình luận mà không cần tạo bảng trung gian riêng cho mỗi loại mô hình.

Bước 1: Tạo Các Mô Hình và Cấu Trúc Bảng

  1. Tạo Model Comment
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Comment extends Model
    {
        /**
         * Thiết lập mối quan hệ polymorphic.
         */
        public function commentable()
        {
            return $this->morphTo();
        }
    }
    
  2. Tạo Model Post
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model
    {
        /**
         * Thiết lập mối quan hệ một-nhiều polymorphic.
         */
        public function comments()
        {
            return $this->morphMany(Comment::class, 'commentable');
        }
    }
    
  3. Tạo Model Video
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Video extends Model
    {
        /**
         * Thiết lập mối quan hệ một-nhiều polymorphic.
         */
        public function comments()
        {
            return $this->morphMany(Comment::class, 'commentable');
        }
    }
    
  4. Tạo Cấu Trúc Bảng
    • Bảng comments

      Schema::create('comments', function (Blueprint $table) {
          $table->id();
          $table->text('content');
          $table->unsignedBigInteger('commentable_id');
          $table->string('commentable_type');
          $table->timestamps();
      });
      

       

      • commentable_id: ID của mô hình mà bình luận thuộc về.
      • commentable_type: Loại mô hình mà bình luận thuộc về (ví dụ: Post hoặc Video).
    • Bảng posts
      Schema::create('posts', function (Blueprint $table) {
          $table->id();
          $table->string('title');
          $table->timestamps();
      });
      
    • Bảng videos
      Schema::create('videos', function (Blueprint $table) {
          $table->id();
          $table->string('title');
          $table->timestamps();
      });
      

Bước 2: Sử Dụng Mối Quan Hệ

1. Thêm Bình Luận

use App\Models\Post;
use App\Models\Video;
use App\Models\Comment;

// Thêm bình luận cho một bài viết
$post = Post::find(1);
$post->comments()->create([
    'content' => 'Great post!',
]);

// Thêm bình luận cho một video
$video = Video::find(1);
$video->comments()->create([
    'content' => 'Amazing video!',
]);

2. Truy Xuất Bình Luận

// Truy xuất bình luận của một bài viết
$post = Post::find(1);
foreach ($post->comments as $comment) {
    echo $comment->content;
}

// Truy xuất bình luận của một video
$video = Video::find(1);
foreach ($video->comments as $comment) {
    echo $comment->content;
}

3. Lấy Mô Hình Từ Bình Luận

// Lấy mô hình mà bình luận thuộc về
$comment = Comment::find(1);
echo $comment->commentable_type; // Ví dụ: App\Models\Post hoặc App\Models\Video

6.Mối Quan Hệ Nhiều-Nhiều (Polymorphic)

Mối quan hệ nhiều-nhiều polymorphic cho phép một mô hình liên kết với nhiều mô hình khác và ngược lại thông qua một bảng trung gian duy nhất. Điều này cho phép mô hình liên kết với nhiều mô hình khác mà không cần phải tạo nhiều bảng trung gian riêng biệt.

Ví Dụ: Tagging trên Bài Viết và Video

Cấu Trúc và Mô Hình
  1. Tạo Mô Hình Tag

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Tag extends Model
    {
        /**
         * Thiết lập mối quan hệ nhiều-nhiều polymorphic.
         */
        public function taggable()
        {
            return $this->morphTo();
        }
    }
    
  2. Tạo Mô Hình Post
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model
    {
        /**
         * Thiết lập mối quan hệ nhiều-nhiều polymorphic.
         */
        public function tags()
        {
            return $this->morphToMany(Tag::class, 'taggable');
        }
    }
    
  3. Tạo Mô Hình Video
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Video extends Model
    {
        /**
         * Thiết lập mối quan hệ nhiều-nhiều polymorphic.
         */
        public function tags()
        {
            return $this->morphToMany(Tag::class, 'taggable');
        }
    }
    
  4. Tạo Cấu Trúc Bảng
    Schema::create('tags', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
    
    Schema::create('taggables', function (Blueprint $table) {
        $table->unsignedBigInteger('tag_id');
        $table->unsignedBigInteger('taggable_id');
        $table->string('taggable_type');
        $table->timestamps();
    });
    
  5. Sử dụng
    // Thêm tag cho một bài viết
    $post = Post::find(1);
    $tag = Tag::find(1);
    $post->tags()->attach($tag);
    
    // Thêm tag cho một video
    $video = Video::find(1);
    $tag = Tag::find(2);
    $video->tags()->attach($tag);
    

Kết Luận

  • Một-Một (One-to-One): Liên kết mỗi bản ghi trong bảng đầu tiên với một bản ghi trong bảng thứ hai.
  • Một-Nhiều (One-to-Many): Liên kết một bản ghi trong bảng đầu tiên với nhiều bản ghi trong bảng thứ hai.
  • Nhiều-Nhiều (Many-to-Many): Liên kết nhiều bản ghi trong bảng đầu tiên với nhiều bản ghi trong bảng thứ hai thông qua bảng trung gian.
  • Polymorphic: Cho phép liên kết linh hoạt với nhiều mô hình khác.

Các mối quan hệ trong Eloquent giúp bạn dễ dàng quản lý và truy xuất dữ liệu liên quan trong ứng dụng của bạn, làm cho việc tương tác với cơ sở dữ liệu trở nên dễ dàng và trực quan hơn.

Auth Basics

Auth Basics

01.08.2024
Author: ADMIN

# Auth Basics

Laravel cung cấp một hệ thống xác thực mạnh mẽ và dễ sử dụng. Dưới đây là những bước cơ bản để thiết lập và sử dụng hệ thống xác thực trong Laravel.

Bước 1: Cài Đặt Laravel UI

Laravel UI là một package cho phép bạn cài đặt các scaffolding (bộ khung) cho xác thực, bao gồm cả giao diện Bootstrap, Vue, và React.

Đầu tiên, cài đặt Laravel UI:

composer require laravel/ui

Sau đó, bạn có thể tạo scaffolding cho xác thực:

php artisan ui bootstrap --auth

Lệnh này sẽ tạo các route, controller, view cần thiết cho hệ thống xác thực và cài đặt Bootstrap. Nếu bạn muốn sử dụng Vue hoặc React, bạn có thể thay bootstrap bằng vue hoặc react.

Tiếp theo, chạy lệnh để cài đặt các package npm và biên dịch các asset:

npm install
npm run dev

Bước 2: Chạy Migrations

Laravel UI sẽ tạo sẵn các migration cho bảng users. Bạn chỉ cần chạy lệnh migrate để tạo bảng trong database:

php artisan migrate

Bước 3: Routes

Laravel UI sẽ tự động tạo các route cần thiết cho hệ thống xác thực trong file routes/web.php:

Auth::routes();

Bạn có thể kiểm tra file này để xem các route mà Laravel đã tạo cho bạn, bao gồm login, register, logout, và password reset.

Bước 4: Middleware

Laravel cung cấp middleware để bảo vệ các route của bạn. Middleware này sẽ đảm bảo rằng chỉ có người dùng đã xác thực mới có thể truy cập các route được bảo vệ.

Ví dụ, bạn có thể bảo vệ một route bằng middleware auth như sau:

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

Bước 5: Views

Laravel UI sẽ tạo sẵn các view cho các trang login, register, và reset password trong thư mục resources/views/auth.

1. Login với $user

Khi bạn cần thiết lập một người dùng hiện tại làm người dùng đã xác thực, bạn có thể truyền instance của người dùng đó vào phương thức login của Facade Auth. Người dùng này phải là một implementation của interface Illuminate\Contracts\Auth\Authenticatable. Mô hình App\Models\User được bao gồm trong Laravel đã triển khai sẵn interface này. Phương pháp này hữu ích khi bạn đã có một instance người dùng hợp lệ, chẳng hạn như ngay sau khi người dùng đăng ký với ứng dụng của bạn.

use Illuminate\Support\Facades\Auth;

$user = User::find(1); // Giả sử bạn đã có instance của người dùng
Auth::login($user);

Ghi Nhớ Đăng Nhập Người Dùng

Auth::login($user, $remember = true);

Sử Dụng Guard

Nếu cần, bạn có thể chỉ định một guard xác thực trước khi gọi phương thức login:

Auth::guard('admin')->login($user);

Ngoài ra, bạn có thể tham khảo thêm về loginUsingId

2. Lấy id user đã đăng nhập

Auth::user()->id;
// or
Auth::id();

3. Extra Password Confirmation

Laravel cung cấp một tính năng gọi là "Extra Password Confirmation" (Xác nhận mật khẩu bổ sung), yêu cầu người dùng nhập lại mật khẩu của họ để xác nhận danh tính trước khi thực hiện các hành động nhạy cảm như thay đổi email, mật khẩu hoặc xóa tài khoản.

Thiết lập Extra Password Confirmation

Laravel đi kèm với các route và controller cần thiết để quản lý việc xác nhận mật khẩu bổ sung. Bạn có thể sử dụng PasswordConfirmationMiddleware để bảo vệ các route cần xác nhận mật khẩu bổ sung.

Sử Dụng Middleware

Đầu tiên, bạn cần bảo vệ các route nhạy cảm của mình bằng middleware password.confirm. Middleware này sẽ kiểm tra xem người dùng đã xác nhận mật khẩu của họ trong một khoảng thời gian nhất định (mặc định là 3 giờ).

Định Nghĩa Route

Trong file routes/web.php, bạn có thể thêm middleware password.confirm cho các route nhạy cảm của mình:

Route::get('/settings', [SettingsController::class, 'index'])->name('settings');

Route::get('/settings/security', [SettingsController::class, 'security'])->middleware(['auth', 'password.confirm'])->name('settings.security');

Trong ví dụ trên, route /settings/security sẽ yêu cầu người dùng xác nhận mật khẩu của họ trước khi truy cập.

Tạo Controller cho Xác Nhận Mật Khẩu

Laravel đã cung cấp sẵn controller và route cho việc xác nhận mật khẩu. Bạn có thể kiểm tra hoặc tùy chỉnh theo nhu cầu.

File: app/Http/Controllers/Auth/ConfirmPasswordController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ConfirmPasswordController extends Controller
{
    /**
     * Hiển thị form xác nhận mật khẩu.
     *
     * @return \Illuminate\View\View
     */
    public function showConfirmForm()
    {
        return view('auth.passwords.confirm');
    }

    /**
     * Xác nhận mật khẩu của người dùng.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function confirm(Request $request)
    {
        $request->validate([
            'password' => 'required|password',
        ]);

        $request->session()->put('auth.password_confirmed_at', time());

        return redirect()->intended();
    }
}

View cho Form Xác Nhận Mật Khẩu

Tạo một file view để hiển thị form xác nhận mật khẩu. Laravel có sẵn file confirm.blade.php cho form xác nhận mật khẩu trong thư mục resources/views/auth/passwords.

File: resources/views/auth/passwords/confirm.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Confirm Password') }}</div>

                <div class="card-body">
                    {{ __('Please confirm your password before continuing.') }}

                    <form method="POST" action="{{ route('password.confirm') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Confirm Password') }}
                                </button>

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Route Cho Xác Nhận Mật Khẩu

Laravel đã định nghĩa sẵn route cho xác nhận mật khẩu. Bạn có thể tìm thấy route này trong file routes/web.php:

Route::get('password/confirm', [ConfirmPasswordController::class, 'showConfirmForm'])->name('password.confirm');
Route::post('password/confirm', [ConfirmPasswordController::class, 'confirm']);

4. Fortify Password Rules

Laravel Fortify cung cấp một cách dễ dàng để tùy chỉnh quy tắc mật khẩu cho ứng dụng của bạn. Bạn có thể định nghĩa các quy tắc mật khẩu tùy chỉnh thông qua lớp Password.

Thiết Lập Các Quy Tắc Mật Khẩu

Laravel Fortify cung cấp lớp Password để bạn có thể định nghĩa các quy tắc mật khẩu một cách linh hoạt. Bạn có thể tùy chỉnh các quy tắc này trong phương thức boot của FortifyServiceProvider.

Cấu Hình Mặc Định

Trong FortifyServiceProvider, bạn có thể định nghĩa các quy tắc mật khẩu mặc định như sau:

File: app/Providers/FortifyServiceProvider.php

<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
use Illuminate\Validation\Rules\Password;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        // Cấu hình các quy tắc mật khẩu
        Password::defaults(function () {
            return Password::min(8)
                            ->mixedCase()
                            ->letters()
                            ->numbers()
                            ->symbols()
                            ->uncompromised();
        });
    }
}

Trong đoạn mã trên, các quy tắc mật khẩu được thiết lập như sau:

  • min(8): Mật khẩu phải có ít nhất 8 ký tự.
  • mixedCase(): Mật khẩu phải có cả chữ hoa và chữ thường.
  • letters(): Mật khẩu phải có ít nhất một chữ cái.
  • numbers(): Mật khẩu phải có ít nhất một chữ số.
  • symbols(): Mật khẩu phải có ít nhất một ký tự đặc biệt.
  • uncompromised(): Mật khẩu không được nằm trong danh sách các mật khẩu đã bị lộ.

 

 

Blade Components

Blade Components

01.08.2024
Author: ADMIN

# Blade Components

Laravel Blade Components cung cấp một cách tiện lợi để xây dựng các phần tử HTML tái sử dụng, giúp bạn tổ chức mã nguồn một cách rõ ràng và hiệu quả hơn. Blade Components cho phép bạn tách biệt logic và giao diện, giúp việc phát triển và bảo trì ứng dụng trở nên dễ dàng hơn.

1. Tạo Blade Components

Tạo Component Bằng Lệnh Artisan

Bạn có thể sử dụng lệnh Artisan để tạo một component:

php artisan make:component Alert

Lệnh này sẽ tạo hai file:

  • Một class component tại app/View/Components/Alert.php
  • Một view Blade tại resources/views/components/alert.blade.php

File Class Component

File: app/View/Components/Alert.php

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public $type;

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($type)
    {
        $this->type = $type;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|\Closure|string
     */
    public function render()
    {
        return view('components.alert');
    }
}

File View Component

File: resources/views/components/alert.blade.php

<div class="alert alert-{{ $type }}">
    {{ $slot }}
</div>

2. Sử Dụng Blade Components

Nhúng Component Trong View

Bạn có thể nhúng component trong view Blade bằng cú pháp <x-component-name>:

File: resources/views/welcome.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
</head>
<body>
    <x-alert type="success">
        This is a success alert.
    </x-alert>

    <x-alert type="danger">
        This is a danger alert.
    </x-alert>
</body>
</html>

3. Truyền Dữ Liệu Cho Component

Bạn có thể truyền dữ liệu cho component thông qua các thuộc tính:

File: app/View/Components/Alert.php

public $type;

public function __construct($type)
{
    $this->type = $type;
}

File: resources/views/components/alert.blade.php

<div class="alert alert-{{ $type }}">
    {{ $slot }}
</div>

File: resources/views/welcome.blade.php

<x-alert type="success">
    This is a success alert.
</x-alert>

<x-alert type="danger">
    This is a danger alert.
</x-alert>

4. Slots

Slots cho phép bạn xác định các phần nội dung động trong component. Mặc định, tất cả nội dung được truyền vào component sẽ nằm trong biến $slot.

Slots Mặc Định

File: resources/views/components/alert.blade.php

<div class="alert alert-{{ $type }}">
    {{ $slot }}
</div>

File: resources/views/welcome.blade.php

<x-alert type="success">
    This is a success alert.
</x-alert>

Named Slots

Bạn có thể tạo nhiều slots với tên khác nhau.

File: resources/views/components/alert.blade.php

<div class="alert alert-{{ $type }}">
    <div class="alert-title">{{ $title }}</div>
    {{ $slot }}
</div>

File: resources/views/welcome.blade.php

<x-alert type="success">
    <x-slot name="title">
        Success
    </x-slot>
    This is a success alert.
</x-alert>

5. Inline Components

Nếu component của bạn đơn giản và không yêu cầu logic phức tạp, bạn có thể sử dụng Inline Components mà không cần tạo file class riêng.

File: resources/views/components/button.blade.php

<button {{ $attributes->merge(['class' => 'btn btn-primary']) }}>
    {{ $slot }}
</button>

File: resources/views/welcome.blade.php

<x-button>
    Click Me
</x-button>

Tóm Tắt

  • Tạo Component: Sử dụng lệnh Artisan để tạo component.
  • Nhúng Component: Sử dụng cú pháp <x-component-name> để nhúng component trong view.
  • Truyền Dữ Liệu: Truyền dữ liệu cho component thông qua các thuộc tính.
  • Slots: Sử dụng slots để xác định nội dung động trong component.
  • Inline Components: Sử dụng Inline Components cho các component đơn giản.

Blade Components giúp mã nguồn của bạn trở nên sạch sẽ, dễ đọc và dễ bảo trì hơn. Việc tách biệt giao diện và logic giúp bạn tập trung vào từng khía cạnh riêng biệt của ứng dụng, làm cho quá trình phát triển trở nên hiệu quả hơn.

Layout: @include, @extends, @section, @yield

Layout: @include, @extends, @section, @yield

01.08.2024
Author: ADMIN

# @include, @extends, @section, và @yield

Laravel Blade cung cấp các từ khóa @include, @extends, @section, và @yield để giúp bạn tái sử dụng và tổ chức mã HTML một cách hiệu quả. Dưới đây là cách sử dụng từng từ khóa này với các ví dụ cụ thể.

@include

@include cho phép bạn nhúng một view Blade khác vào trong view hiện tại. Đây là cách tuyệt vời để tái sử dụng các phần tử HTML như header, footer, hoặc sidebar.

Ví Dụ

Giả sử bạn có một view header.blade.php:

<!-- resources/views/header.blade.php -->
<header>
    <h1>My Website Header</h1>
</header>

Bạn có thể nhúng view này vào view chính của bạn như sau:

<!-- resources/views/welcome.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
</head>
<body>
    @include('header')
    <div class="content">
        <p>Welcome to the homepage!</p>
    </div>
</body>
</html>

@extends

@extends được sử dụng để chỉ định layout mà view hiện tại sẽ kế thừa. Layout này thường chứa các cấu trúc HTML cơ bản mà các view khác có thể sử dụng lại.

Ví Dụ

Giả sử bạn có một layout app.blade.php:

<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    @include('header')
    <div class="content">
        @yield('content')
    </div>
    @include('footer')
</body>
</html>

Trong view cụ thể của bạn, bạn có thể kế thừa layout này như sau:

<!-- resources/views/home.blade.php -->
@extends('layouts.app')

@section('title', 'Home Page')

@section('content')
    <h2>Welcome to the Home Page</h2>
    <p>This is the home page content.</p>
@endsection

@section và @yield

@section được sử dụng để xác định nội dung mà view con sẽ cung cấp cho các vùng nội dung được định nghĩa trong layout bằng @yield.

Ví Dụ

Trong layout app.blade.php, bạn có thể có các vùng nội dung:

<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    @include('header')
    <div class="content">
        @yield('content')
    </div>
    @include('footer')
</body>
</html>

Trong view con home.blade.php, bạn có thể định nghĩa các phần nội dung cho các vùng đó:

<!-- resources/views/home.blade.php -->
@extends('layouts.app')

@section('title', 'Home Page')

@section('content')
    <h2>Welcome to the Home Page</h2>
    <p>This is the home page content.</p>
@endsection

Tóm Tắt

  • @include: Nhúng một view Blade khác vào view hiện tại.
  • @extends: Kế thừa layout từ một view khác.
  • @section: Định nghĩa một phần nội dung trong view con.
  • @yield: Đánh dấu vị trí mà nội dung của view con sẽ được chèn vào trong layout.

Việc sử dụng @include, @extends, @section, và @yield giúp bạn tổ chức mã nguồn của mình một cách rõ ràng và tái sử dụng được các phần tử giao diện, làm cho việc phát triển và bảo trì ứng dụng trở nên dễ dàng hơn.

Laravel Breeze

Laravel Breeze

01.08.2024
Author: ADMIN

# Laravel Breeze

Laravel Breeze là một hệ thống xác thực đơn giản và gọn nhẹ dành cho các ứng dụng Laravel. Nó cung cấp các tính năng cơ bản như đăng ký, đăng nhập, đặt lại mật khẩu và xác nhận email. Breeze được xây dựng để giúp các nhà phát triển khởi đầu nhanh chóng với các tính năng xác thực mà không phải cấu hình quá nhiều.

Cài Đặt Laravel Breeze

Để cài đặt Laravel Breeze, bạn cần làm theo các bước sau:

  1. Cài đặt Laravel

    Đầu tiên, bạn cần tạo một ứng dụng Laravel mới hoặc sử dụng một ứng dụng Laravel hiện có.

    composer create-project laravel/laravel my-app
    
  2. Cài đặt Laravel Breeze

    Sử dụng Composer để cài đặt gói Laravel Breeze.

    composer require laravel/breeze --dev
    
  3. Cài đặt Breeze

    Chạy lệnh cài đặt Breeze để thiết lập các file scaffolding cho hệ thống xác thực.

    php artisan breeze:install
    
  4. Chạy migration

    Chạy các lệnh migration để tạo các bảng cần thiết trong cơ sở dữ liệu.

    php artisan migrate
    
  5. Cài đặt các gói npm và build assets

    Breeze sử dụng các file frontend được xây dựng bằng Tailwind CSS và Laravel Mix. Chạy các lệnh dưới đây để cài đặt các gói npm và build assets.

    npm install && npm run dev
    
  6. Khởi động server

    Chạy server Laravel để kiểm tra hệ thống xác thực.

    php artisan serve
    

Các Tính Năng Chính

Sau khi cài đặt thành công, Breeze sẽ cung cấp các tính năng xác thực cơ bản sau:

  1. Đăng Ký Người Dùng

    Bạn có thể truy cập vào URL /register để hiển thị form đăng ký người dùng. Breeze sẽ tạo ra tất cả các controller và view cần thiết cho việc đăng ký người dùng.

    <!-- resources/views/auth/register.blade.php -->
    <form method="POST" action="{{ route('register') }}">
        @csrf
        <!-- Các trường nhập thông tin -->
        <button type="submit">Register</button>
    </form>
    
  2. Đăng Nhập

    Người dùng có thể đăng nhập vào ứng dụng qua URL /login.

    <!-- resources/views/auth/login.blade.php -->
    <form method="POST" action="{{ route('login') }}">
        @csrf
        <!-- Các trường nhập thông tin -->
        <button type="submit">Login</button>
    </form>
    
  3. Đặt Lại Mật Khẩu

    Breeze cung cấp các view và logic để đặt lại mật khẩu. Người dùng có thể truy cập URL /forgot-password để gửi yêu cầu đặt lại mật khẩu.

    <!-- resources/views/auth/forgot-password.blade.php -->
    <form method="POST" action="{{ route('password.email') }}">
        @csrf
        <!-- Trường nhập email -->
        <button type="submit">Send Password Reset Link</button>
    </form>
    
  4. Xác Nhận Email

    Breeze cũng hỗ trợ tính năng xác nhận email, cho phép bạn gửi email xác nhận đến người dùng sau khi họ đăng ký.

    <!-- resources/views/auth/verify-email.blade.php -->
    <p>{{ __('Before proceeding, please check your email for a verification link.') }}</p>
    

Tùy Chỉnh Laravel Breeze

Nếu bạn muốn tùy chỉnh các view hoặc logic của Breeze, bạn có thể chỉnh sửa các file view trong thư mục resources/views/auth và các file controller trong thư mục app/Http/Controllers/Auth.

Tóm Tắt

Laravel Breeze là một giải pháp tuyệt vời cho việc khởi đầu nhanh chóng với các tính năng xác thực cơ bản trong Laravel. Nó cung cấp một bộ công cụ đầy đủ để quản lý đăng ký, đăng nhập, đặt lại mật khẩu và xác nhận email mà không cần cấu hình quá nhiều. Nếu bạn cần một hệ thống xác thực mạnh mẽ và tùy biến hơn, bạn có thể cân nhắc sử dụng Laravel Fortify hoặc Jetstream.