---
# System prepended metadata

title: 'PHP - TL19+TL20: Laravel MVC'

---

# I. Route và Controller
## I.1 Route
Laravel Route là một phần quan trọng của bất kỳ ứng dụng Laravel nào, nó đóng vai trò như là bản đồ chỉ dẫn, quy định cách mà các HTTP request được xử lý. Các route định nghĩa URL, phương thức HTTP (như GET, POST, PUT, DELETE), và hành động cụ thể sẽ được thực hiện khi request đến một URL cụ thể.

### Các Đặc Điểm Cơ Bản:

1. **File Route**: Trong Laravel, các route thường được định nghĩa trong thư mục `routes`. Các file chính là `web.php` (dành cho trang web), `api.php` (dành cho API), `console.php` (dành cho các lệnh Artisan), và `channels.php` (dành cho WebSockets).

2. **Cú Pháp Định Nghĩa Route Cơ Bản**:
   ```php
   Route::get('/example', function () {
       return 'Hello World';
   });
   ```
   Trong đó `get` là phương thức HTTP, `/example` là URI, và `function` là hành động cần thực hiện.

3. **Controller Routes**:
   ```php
   Route::get('/user', 'UserController@index');
   ```
   Ở đây, thay vì định nghĩa hành động trực tiếp trong file route, bạn có thể gọi một method (`index`) trong một Controller (`UserController`).

4. **Route Parameters**:
   - Tham số bắt buộc:
     ```php
     Route::get('/user/{id}', function ($id) {
         return 'User ' . $id;
     });
     ```
   - Tham số tùy chọn:
     ```php
     Route::get('/user/{name?}', function ($name = 'John') {
         return 'User ' . $name;
     });
     ```

5. **Named Routes**: Cho phép gán tên cho route, thuận tiện cho việc tạo URL hoặc redirect.
   ```php
   Route::get('/user/profile', function () {
       //
   })->name('profile');
   ```

6. **Middleware**: Được sử dụng để lọc và kiểm soát request trước khi chúng đến controller.
   ```php
   Route::get('/admin', function () {
       //
   })->middleware('admin');
   ```

7. **Route Groups**: Được sử dụng để nhóm nhiều route có các thuộc tính chung, như middleware, namespaces, hoặc prefix.
   ```php
   Route::group(function () {
        Route::get('/provinces', 'ProvinceController@index')->name('province');
        Route::get('/districts', 'DistrictController@index')->name('district');
        Route::get('/users/create', 'UserController@create')->name('create');
        Route::post('/users', 'UserController@store')->name('store');
   })->middleware(['auth'])->prefix('admin');
   ```

8. **Sub-Domain Routing**: Laravel hỗ trợ route cho các sub-domain.
   ```php
   Route::domain('{account}.myapp.com')->group(function () {
       Route::get('user/{id}', function ($account, $id) {
           //
       });
   });
   ```

9. **Rate Limiting**: Đối với các route API, Laravel cung cấp tính năng giới hạn số lượng request trong một khoảng thời gian nhất định.

    ```php
    Route::middleware('throttle:60,1')->group(function () {
        Route::get('/user/profile', function () {
            // Mã của bạn
        });
    });
    ```

10. **Fallback Routes**: Được sử dụng để xử lý các trường hợp URL không khớp với bất kỳ route nào khác.
    ```php
    Route::fallback(function () {
        // Xử lý 404
    });
    ```

## I.2 Controller
Trong Laravel, Controller đóng vai trò trung tâm trong việc xử lý logic ứng dụng. Controllers xử lý các yêu cầu HTTP đến, thực hiện các thao tác cần thiết như truy xuất dữ liệu, xử lý form, và sau đó trả về phản hồi HTTP, thường là dưới dạng một view.

### Tạo Controller

Để tạo một controller mới, bạn sử dụng Artisan command line tool của Laravel. Ví dụ:

```bash
php artisan make:controller UserController
```

Lệnh này sẽ tạo một controller mới tên là `UserController` trong thư mục `app/Http/Controllers`.

### Cấu Trúc Controller

Một controller cơ bản trong Laravel thường có dạng như sau:

```php
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index()
    {
        $users = User::all();
        return view('users.index', compact('users'));
    }

    // Thêm các phương thức khác...
}
```

Ở đây, `index` là một phương thức của `UserController` và truy xuất tất cả người dùng từ database, sau đó trả về một view.

### Định Nghĩa Route cho Controller

Bạn định nghĩa route trong các file route (thường là `web.php` hoặc `api.php` trong thư mục `routes`) để chỉ định các yêu cầu HTTP nào sẽ được xử lý bởi controller của bạn.

```php
use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
```

### Resource Controller

Laravel cung cấp một cách thuận tiện để tạo một controller với các phương thức chuẩn cho CRUD (create, read, update, delete) thông qua khái niệm Resource Controller.

```bash
php artisan make:controller UserController --resource
```

Controller này sẽ bao gồm các phương thức như `index`, `create`, `store`, `show`, `edit`, `update`, và `destroy`.

### Dependency Injection

Laravel hỗ trợ dependency injection vào controller. Điều này có nghĩa là bạn có thể yêu cầu các service cần thiết trong hàm khởi tạo của controller.

```php
public function __construct(UserRepository $users)
{
    $this->users = $users;
}
```

### Middleware

Bạn có thể gán middleware cho controller để thực hiện việc kiểm tra hoặc xử lý trước khi controller xử lý yêu cầu.

```php
public function __construct()
{
    $this->middleware('auth');
}
```

## Kết Luận

* Route trong Laravel cung cấp một hệ thống linh hoạt và mạnh mẽ cho việc xử lý request và định nghĩa hành động tương ứng trong ứng dụng của bạn. Việc hiểu rõ về cách sử dụng route giúp bạn tổ chức cấu trúc ứng dụng một cách rõ ràng và hiệu quả.
* Controllers trong Laravel giúp bạn tách biệt logic xử lý yêu cầu khỏi routing và view, làm cho mã nguồn dễ đọc, dễ bảo trì, và tăng tính tái sử dụng. Sử dụng controllers một cách hiệu quả sẽ giúp cấu trúc ứng dụng của bạn trở nên rõ ràng và chặt chẽ hơn.

---
# II. Model và Relationship

## II.1 Model
Trong Laravel, Model là một phần quan trọng của mô hình MVC (Model-View-Controller), đại diện cho lớp liên quan đến dữ liệu và logic xử lý dữ liệu. Model trong Laravel chủ yếu tương tác với database thông qua Eloquent ORM, một ORM (Object-Relational Mapping) cung cấp một cách trực quan và linh hoạt để truy vấn và làm việc với dữ liệu.

### Cách Tạo Model

Để tạo một model mới trong Laravel, bạn thường sử dụng Artisan CLI. Ví dụ, để tạo một model `User`, bạn sẽ sử dụng lệnh sau:

```bash
php artisan make:model User
```

Lệnh này sẽ tạo một file model mới trong thư mục `app/Models` (trong Laravel 8 trở đi) hoặc `app` (trong các phiên bản trước Laravel 8).

### Cấu Trúc Cơ Bản của Model

Một model cơ bản trong Laravel thường trông như sau:

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // Định nghĩa model ở đây
}
```

### Tương Tác với Database

Model sử dụng Eloquent ORM để tương tác với database. Eloquent cung cấp một giao diện để tạo, đọc, cập nhật, và xóa bản ghi database một cách dễ dàng.

#### Ví dụ:

```php
// Tạo một bản ghi mới
$user = new User();
$user->name = 'John Doe';
$user->email = 'john@example.com';
$user->save();

// Truy vấn dữ liệu
$users = User::all();

// Cập nhật bản ghi
$user = User::find(1);
$user->name = 'Jane Doe';
$user->save();

// Xóa bản ghi
$user = User::find(1);
$user->delete();
```

### Mass Assignment

Laravel cung cấp khả năng tự động gán dữ liệu cho các thuộc tính của model thông qua mass assignment. Để sử dụng tính năng này, bạn cần định nghĩa thuộc tính `fillable` hoặc `guarded` trong model.

```php
class User extends Model
{
    protected $fillable = ['name', 'email', 'password'];
    // Hoặc sử dụng $guarded
    // protected $guarded = [];
}
```

## II.2 Relationships

Eloquent cũng hỗ trợ định nghĩa các mối quan hệ giữa các model, như `hasOne`, `hasMany`, `belongsTo`, `belongsToMany`, `morphMany`, và `morphToMany`.

### Các loại Relationship:

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

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}
```

#### 1. One-to-One

Mối quan hệ một-một cho phép một model liên kết trực tiếp với một model khác. Ví dụ, mỗi `User` có thể có một `Profile`.

##### Định nghĩa:

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

#### 2. One-to-Many

Mối quan hệ một-nhiều cho phép một model liên kết với nhiều model khác. Ví dụ, một `Post` có thể có nhiều `Comment`.

##### Định nghĩa:

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

#### 3. Many-to-One

Ngược lại với one-to-many, trong many-to-one, nhiều bản ghi trong một bảng liên kết với một bản ghi trong bảng khác. Ví dụ, nhiều `Comment` có thể thuộc về một `Post`.

##### Định nghĩa:

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

#### 4. Many-to-Many

Mối quan hệ nhiều-nhiều liên kết nhiều bản ghi trong một bảng với nhiều bản ghi trong bảng khác. Thường được quản lý thông qua một bảng trung gian. Ví dụ, `Student` và `Course` có thể có mối quan hệ nhiều-nhiều.

##### Định nghĩa:

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

#### 5. Has Many Through

Mối quan hệ này được sử dụng để truy vấn qua một mối quan hệ trung gian. Ví dụ, một `Country` có thể có nhiều `Post` thông qua một mối quan hệ trung gian `User`.

##### Định nghĩa:

```php
class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}
```

#### 6. Polymorphic Relations

Trong mối quan hệ đa hình, một model có thể thuộc về nhiều loại model khác. Ví dụ, cả `Post` và `Video` có thể có nhiều `Comment`.

##### Định nghĩa:
```yml
posts
    id - integer
    name - string
    user_id - integer
 
users
    id - integer
    name - string
 
images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string
```

```php
class Image extends Model
{
    public function imageable()
    {
        return $this->morphTo('imageable');
    }
}

class Post extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

class User extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

```

### Làm Việc với Relationship

#### 1. Lấy dữ liệu từ Relationship

Khi đã định nghĩa các mối quan hệ, bạn có thể dễ dàng truy vấn dữ liệu liên quan:

```php
$comments = Post::find(1)->comments; // Lấy tất cả các comment của post có id là 1

$profile = User::find(1)->profile; // Lấy profile của user có id là 1
```

#### 2. Cập nhật dữ liệu vào relationship

Trong Laravel, khi làm việc với các mối quan hệ (relationships) giữa các model, có một số phương thức quan trọng giúp bạn quản lý các mối quan hệ này một cách hiệu quả. Cụ thể, các phương thức `associate`, `dissociate`, `attach`, `detach`, và `sync` là những công cụ mạnh mẽ để quản lý các mối quan hệ như belongsTo, belongsToMany, và many-to-many.

##### 1. Associate và Dissociate

`associate` và `dissociate` được sử dụng chủ yếu trong mối quan hệ `belongsTo`.

- **associate:** Dùng để liên kết một model với model khác trong mối quan hệ `belongsTo`. Ví dụ: liên kết một comment với một post.

  ```php
  $comment = new Comment;
  $post = Post::find(1);

  $comment->post()->associate($post);
  $comment->save();
  ```

- **dissociate:** Dùng để hủy liên kết.

  ```php
  $comment->post()->dissociate();
  $comment->save();
  ```

##### 2. Attach và Detach

`attach` và `detach` được sử dụng trong mối quan hệ many-to-many.

- **attach:** Dùng để thêm một hoặc nhiều model vào mối quan hệ. Nếu liên kết đã tồn tại, `attach` không kiểm tra trùng lặp.

  ```php
  $user = User::find(1);
  $roleId = 2;

  $user->roles()->attach($roleId);
  ```

  Bạn cũng có thể chuyển một mảng của ID để attach nhiều role cùng một lúc.

- **detach:** Dùng để xóa một hoặc nhiều model khỏi mối quan hệ. Nếu không truyền ID nào, tất cả các liên kết sẽ bị xóa.

  ```php
  // Xóa một role cụ thể
  $user->roles()->detach($roleId);

  // Xóa tất cả các role
  $user->roles()->detach();
  ```

##### 3. Sync

`sync` cũng được sử dụng trong mối quan hệ many-to-many. Phương thức này hữu ích để cập nhật mối quan hệ, nó sẽ xóa các liên kết cũ không có trong mảng được truyền vào và thêm những liên kết mới.

- **sync:** Nếu bạn có một mảng các ID, `sync` sẽ giữ chỉ những liên kết có trong mảng đó và xóa bỏ những cái khác.

  ```php
  $user = User::find(1);
  $roles = [1, 2, 3];

  $user->roles()->sync($roles);
  ```

##### 4. SyncWithoutDetaching

Đôi khi bạn muốn thêm các liên kết mới mà không xóa các liên kết cũ. Đó là lúc `syncWithoutDetaching` trở nên hữu ích.

- **syncWithoutDetaching:** Giữ các liên kết hiện tại và chỉ thêm những liên kết mới không tồn tại.

  ```php
  $user->roles()->syncWithoutDetaching([1, 2]);
  ```

## Kết Luận

* Model trong Laravel là một công cụ mạnh mẽ, cung cấp cơ chế linh hoạt và trực quan để tương tác với dữ liệu trong ứng dụng của bạn. Sử dụng Eloquent ORM giúp việc làm việc với database trở nên đơn giản và hiệu quả, giảm thiểu đáng kể lượng mã cần viết và bảo trì.
* Eloquent ORM cũng cung cấp các cách thức để định nghĩa và làm việc với các mối quan hệ giữa các model. Các mối quan hệ (relations) này phản ánh các liên kết giữa các bảng trong cơ sở dữ liệu và cho phép bạn truy vấn dữ liệu liên quan một cách trực quan và hiệu quả.

---
# III. View và Blade template
Trong Laravel, "View" là một phần quan trọng của mô hình MVC (Model-View-Controller). View chịu trách nhiệm cho phần hiển thị giao diện người dùng, tức là nó đảm nhiệm việc render dữ liệu ra trình duyệt dưới dạng HTML hoặc định dạng khác như JSON, XML cho các ứng dụng API. Dưới đây là một số thông tin cơ bản và cách sử dụng View trong Laravel:

## III.1 Cơ bản về View và Blade

### Tạo View
View trong Laravel thường được lưu trong thư mục `resources/views`. Bạn có thể tạo file view dưới dạng `.blade.php` để sử dụng Blade, một engine template mạnh mẽ của Laravel, hoặc chỉ đơn giản là file `.php`.

Ví dụ: Tạo file view `welcome.blade.php` trong `resources/views`.

### Truyền Dữ Liệu vào View
Có thể truyền dữ liệu từ controller sang view để hiển thị thông tin động:

```php
public function show($id)
{
    $user = User::findOrFail($id);
    return view('user.profile', ['user' => $user]);
}
```

Trong ví dụ trên, dữ liệu `user` được truyền vào view `user.profile`.

### Sử dụng Blade

Blade là một engine template mạnh mẽ giúp việc viết mã HTML trở nên dễ dàng và gọn gàng hơn với việc hỗ trợ các cấu trúc điều khiển như vòng lặp, điều kiện, template kế thừa, v.v.

```blade
<!-- resources/views/greetings.blade.php -->
<html>
<head>
    <title>Greetings</title>
</head>
<body>
    <h1>Hello, {{ $name }}!</h1>
</body>
</html>
```

Ở đây, `{{ $name }}` sẽ được thay thế bằng giá trị của biến `$name` khi view được render.

### Kế Thừa Template

Blade hỗ trợ kế thừa layout giúp tái sử dụng mã nguồn và tổ chức code tốt hơn:

```blade
<!-- resources/views/layouts/app.blade.php -->
<html>
<head>
    <title>App Name - @yield('title')</title>
</head>
<body>
    @section('sidebar')
        This is the master sidebar.
    @show

    <div class="container">
        @yield('content')
    </div>
</body>
</html>
```

Bạn có thể "kế thừa" view này trong các view khác:

```blade
@extends('layouts.app')

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

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection
```
## III.2 Các cú pháp phổ biến trong Blade
### 1. Hiển Thị Dữ Liệu

- `{{ $variable }}`: Hiển thị nội dung của biến. Dữ liệu sẽ được tự động thoát (escape) để tránh XSS.
- `{!! $variable !!}`: Hiển thị nội dung mà không thoát dữ liệu. Sử dụng khi bạn tin tưởng nguồn dữ liệu.

### 2. Cấu Trúc Điều Khiển

- `@if`, `@elseif`, `@else`, `@endif`: Cấu trúc điều kiện.
  ```blade
  @if ($condition)
      // Nội dung nếu điều kiện đúng
  @elseif ($anotherCondition)
      // Nội dung nếu điều kiện khác đúng
  @else
      // Nội dung nếu không điều kiện nào đúng
  @endif
  ```
- `@unless`: Điều kiện ngược, tức là `@if (! $condition)`.
  ```blade
  @unless ($condition)
      // Nội dung nếu điều kiện sai
  @endunless
  ```
- `@isset`, `@endisset`: Kiểm tra nếu một biến được đặt.
  ```blade
  @isset($variable)
      // Nội dung nếu biến tồn tại
  @endisset
  ```
- `@empty`, `@endempty`: Kiểm tra nếu một biến trống.
  ```blade
  @empty($variable)
      // Nội dung nếu biến trống
  @endempty
  ```

### 3. Vòng Lặp

- `@for`, `@endfor`: Vòng lặp for.
- `@foreach`, `@endforeach`: Vòng lặp foreach.
- `@while`, `@endwhile`: Vòng lặp while.
- `@break`, `@continue`: Điều khiển vòng lặp.

### 4. Template Kế Thừa

- `@extends('layout')`: Kế thừa một layout.
- `@section('content')`, `@endsection`: Định nghĩa một section.
- `@yield('content')`: Hiển thị nội dung của một section.
- `@parent`: Thêm nội dung vào section từ layout cha.

### 5. Bao Gồm Các View Khác

- `@include('view.name', ['some' => 'data'])`: Bao gồm một view khác và truyền dữ liệu vào nó.

### 6. Các Cú Pháp Khác

- `@csrf`: Sinh ra một trường token CSRF trong form.
- `@method('PUT')`: Tạo một trường ẩn cho việc spoofing method trong form.
- `@error('field')`: Hiển thị lỗi cho một trường cụ thể.

### 7. Cú Pháp Raw PHP

- `@php`: Cho phép bạn sử dụng raw PHP.

## III.3. Tạo Form với Blade
Tạo form trong Laravel sử dụng Blade template engine là một quá trình đơn giản và linh hoạt. Laravel Blade cung cấp một số cú pháp rõ ràng và dễ đọc để tạo và quản lý form. Dưới đây là một ví dụ về cách tạo một form cơ bản trong Laravel sử dụng Blade:

### Bước 1: Tạo Route

Đầu tiên, bạn cần tạo một route trong `routes/web.php` để xử lý việc hiển thị và gửi form:

```php
Route::get('/form', 'FormController@showForm')->name('form.show');
Route::post('/form', 'FormController@submitForm')->name('form.submit');
```

### Bước 2: Tạo Controller

Tạo một controller mới, ví dụ `FormController`, để xử lý logic của form:

```php
php artisan make:controller FormController
```

Trong `FormController`, bạn viết các hàm để xử lý việc hiển thị và gửi form:

```php
use Illuminate\Http\Request;

public function showForm() {
    return view('form');
}

public function submitForm(Request $request) {
    $validatedData = $request->validate([
        'name' => 'required|max:255',
        'email' => 'required|email',
        'field2' => [
            'required',
            function ($attribute, $value, $fail) {
                if ($value !== 'giá trị mong muốn') {
                    $fail($attribute.' không đúng với giá trị mong muốn.');
                }
            },
        ],
        // Thêm các quy tắc xác thực khác tại đây
    ]);

    // Xử lý dữ liệu sau khi đã xác thực
}
```

### Bước 3: Tạo View

Tạo một file view mới, ví dụ `resources/views/form.blade.php`, để tạo giao diện form:

```blade
<form action="{{ route('form.submit') }}" method="POST">
    @csrf  <!-- CSRF Token là bắt buộc trong Laravel -->

    <label for="name">Name:</label>
    <input type="text" name="name" id="name" required>

    <label for="email">Email:</label>
    <input type="email" name="email" id="email" required>

    <button type="submit">Submit</button>
</form>
```

Trong ví dụ này, `@csrf` là directive của Blade để sinh ra một CSRF token, giúp bảo mật form.

### Bước 4: Hiển Thị Lỗi và Dữ Liệu Cũ

Bạn cũng có thể hiển thị lỗi validation và giữ dữ liệu cũ trong các trường của form:

```blade
<form action="{{ route('form.submit') }}" method="POST">
    @csrf

    <label for="name">Name:</label>
    <input type="text" name="name" id="name" value="{{ old('name') }}" required>
    @error('name')
        <div>{{ $message }}</div>
    @enderror

    <label for="email">Email:</label>
    <input type="email" name="email" id="email" value="{{ old('email') }}" required>
    @error('email')
        <div>{{ $message }}</div>
    @enderror

    <button type="submit">Submit</button>
</form>
```

Trong đoạn code này, `old('name')` và `old('email')` giúp giữ lại dữ liệu đã nhập trước đó nếu form bị lỗi và cần được gửi lại. `@error` directive hiển thị lỗi validation liên quan đến mỗi trường.

## Kết Luận

* View trong Laravel là một phần không thể thiếu trong việc xây dựng giao diện người dùng. View gắn liền với việc sử dụng Blade, hệ thống template mạnh mẽ của Laravel, cung cấp nhiều cú pháp đơn giản để viết code PHP một cách gọn gàng và dễ đọc.
*  Với việc sử dụng Blade, việc phát triển trở nên dễ dàng và linh hoạt hơn, giúp các nhà phát triển có thể tạo ra các ứng dụng web phức tạp một cách nhanh chóng và hiệu quả.
*  Sử dụng Blade để tạo form trong Laravel giúp quá trình này trở nên dễ dàng và linh hoạt hơn, đồng thời hỗ trợ tốt cho việc xác thực và hiển thị lỗi. Bạn có thể mở rộng và tùy chỉnh form tùy theo nhu cầu cụ thể của ứng dụng.