NTM Solutions

Bài đăng nổi bật

🚀 Laravel 12 (2026) — Từ PHP Core đến Full Stack📘

Nếu cập nhật theo Laravel 12 LTS (2026) thì mình sẽ chia thành các phần như sau để người học đi từ PHP Core → Laravel → Triển khai dự án th...

Thứ Sáu, 25 tháng 9, 2026

🚀LARAVEL 13 — BÀI 49 — PRODUCTION TIPS

Ở các bài trước, chúng ta đã lần lượt xây dựng và triển khai Blog CMS:

Bài 45 → Shared Hosting
Bài 46 → VPS
Bài 47 → Nginx
Bài 48 → Queue Worker & Scheduler

Đến đây ứng dụng đã có thể chạy trên production.

Nhưng:

Chạy được chưa có nghĩa là đã được cấu hình tốt cho production.

Một Laravel application thực tế cần quan tâm thêm:

  • Performance

  • Cache

  • Environment

  • Debug

  • Security

  • Database

  • Queue

  • Storage

  • Logs

  • Deployment

  • Configuration

Laravel 13 cung cấp sẵn nhiều công cụ để tối ưu những vấn đề này. Trong tài liệu deployment chính thức, Laravel đặc biệt khuyến nghị cache configuration, events, routes và views khi triển khai production.


1. Development và Production khác nhau

Trong quá trình học, chúng ta thường chạy:

php artisan serve

với:

APP_ENV=local
APP_DEBUG=true

Điều này phù hợp cho development.

Production nên sử dụng:

APP_ENV=production
APP_DEBUG=false

Mô hình:

Development

APP_ENV=local
APP_DEBUG=true
        │
        ▼
Debug nhiều
Hot reload
Test
Development

Production:

Production

APP_ENV=production
APP_DEBUG=false
        │
        ▼
Security
Performance
Caching
Monitoring

2. File .env

Laravel sử dụng .env để chứa các giá trị phụ thuộc môi trường.

Ví dụ:

APP_NAME="Blog CMS"

APP_ENV=production

APP_KEY=base64:...

APP_DEBUG=false

APP_URL=https://example.com

Database:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=blog_user
DB_PASSWORD=********

Mail:

MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...
MAIL_ENCRYPTION=tls

Queue:

QUEUE_CONNECTION=database

Cache:

CACHE_STORE=database

Các giá trị này có thể thay đổi giữa:

Local
Staging
Production

Laravel cũng khuyến cáo không commit .env vào source control vì file này có thể chứa credentials và thông tin nhạy cảm.


3. .env không phải file để đưa lên Git

Không nên:

git add .env

Thay vào đó:

.env

nên được ignore.

Thông thường project có:

.env
.env.example

Trong đó:

.env

Chứa cấu hình thực tế:

DB_PASSWORD=secret-password

.env.example

Chỉ chứa cấu trúc mẫu:

DB_PASSWORD=

Nhờ vậy người khác có thể biết application cần những biến môi trường nào mà không biết password production.


4. APP_ENV

Ví dụ:

APP_ENV=production

Laravel có thể kiểm tra environment:

use Illuminate\Support\Facades\App;

if (App::environment('production')) {
    // Production
}

Hoặc:

if (App::environment(['local', 'staging'])) {
    // Local hoặc staging
}

Trong production Blog CMS:

APP_ENV=production

là lựa chọn phù hợp.


5. APP_DEBUG

Đây là một trong những biến quan trọng nhất:

APP_DEBUG=false

Development:

APP_DEBUG=true

Production:

APP_DEBUG=false

Laravel documentation cảnh báo APP_DEBUG=true trên production có thể làm lộ thông tin nhạy cảm cho người dùng.


6. Điều gì xảy ra khi APP_DEBUG=true?

Giả sử code có lỗi:

$post->category->name;

nhưng:

$post->category

là null.

Development có thể hiển thị rất nhiều thông tin:

Exception
File
Line
Stack Trace
Environment
Configuration
SQL
Request

Điều này cực kỳ hữu ích khi debug.

Nhưng production:

APP_DEBUG=true

có thể biến thông tin debug thành dữ liệu mà attacker có thể khai thác.

Do đó:

APP_DEBUG=false

7. Production Error Page

Production nên hiển thị một thông báo thân thiện:

Something went wrong.
Please try again later.

thay vì:

SQLSTATE...
/var/www/blog/vendor/...
DB_PASSWORD...
Stack trace...

Nguyên tắc:

Development
    ↓
Developer cần thông tin

Production
    ↓
User cần thông báo an toàn

8. APP_KEY

Laravel application cần:

APP_KEY=base64:...

Không được tùy tiện thay đổi APP_KEY trên production đang chạy.

Nếu thay đổi key, những dữ liệu được mã hóa bằng key cũ có thể không còn giải mã được.

Ví dụ:

php artisan key:generate

Chỉ nên thực hiện khi tạo application hoặc khi bạn hiểu rõ tác động.

Không nên mỗi lần deploy lại chạy:

php artisan key:generate

9. APP_URL

Production nên đặt URL thật:

APP_URL=https://example.com

Không nên để:

APP_URL=http://127.0.0.1:8000

nếu application đang chạy trên Internet.

APP_URL có thể được sử dụng trong nhiều tình huống tạo URL, command và các thành phần khác của application.


10. Cache là gì?

Cache là kỹ thuật lưu lại dữ liệu hoặc kết quả đã được xử lý để lần sau lấy nhanh hơn.

Ví dụ:

Không Cache

Request
   ↓
Database
   ↓
Query
   ↓
Process
   ↓
Response

Có Cache:

Request
   ↓
Cache
   │
   ├── Có → Response nhanh
   │
   └── Không
        ↓
      Database
        ↓
      Cache
        ↓
      Response

11. Laravel Cache

Laravel cung cấp API thống nhất cho nhiều cache backend.

Ví dụ:

use Illuminate\Support\Facades\Cache;

Lưu:

Cache::put('site_name', 'Blog CMS', 3600);

Lấy:

$name = Cache::get('site_name');

Hoặc:

$name = Cache::get('site_name', 'Default');

Xóa:

Cache::forget('site_name');

12. Cache::remember()

Đây là một pattern rất hữu ích.

Ví dụ:

$categories = Cache::remember(
    'blog.categories',
    3600,
    function () {
        return Category::active()
            ->withCount('posts')
            ->orderBy('name')
            ->get();
    }
);

Luồng:

Request
   │
   ▼
Cache?
   │
   ├── Có
   │    ↓
   │  Return
   │
   └── Không
        ↓
     Database
        ↓
      Cache
        ↓
      Return

Thay vì query database liên tục, dữ liệu có thể được sử dụng từ cache trong thời gian đã cấu hình.


13. Cache cho Blog CMS

Trong Blog CMS, chúng ta có:

Categories
Tags
Settings
Statistics
Popular Posts
Homepage Data

Một số dữ liệu không thay đổi liên tục có thể phù hợp với cache.

Ví dụ:

$categories = Cache::remember(
    'categories.active',
    3600,
    fn () => Category::active()
        ->withCount('posts')
        ->orderBy('name')
        ->get()
);

14. Không nên cache mọi thứ

Cache không phải:

Càng nhiều càng tốt.

Ví dụ:

User profile
Admin permissions
Realtime stock price
Current order status

có thể cần dữ liệu mới.

Nếu cache quá lâu:

Database
    ↓
Data mới

Cache
    ↓
Data cũ

Người dùng có thể nhìn thấy dữ liệu stale.

Do đó cần cân nhắc:

Data thay đổi thường xuyên
→ Cache ngắn hoặc không cache

Data ít thay đổi
→ Cache lâu hơn

15. Clear Cache

Trong development hoặc khi troubleshooting:

php artisan optimize:clear

Laravel 13 cung cấp optimize:clear để xóa các cache được tạo bởi optimize và các key trong default cache store.

Có thể sử dụng riêng:

php artisan config:clear

hoặc:

php artisan route:clear

hoặc:

php artisan view:clear

Tùy trường hợp.


16. Production Optimization

Laravel 13 có command:

php artisan optimize

Đây là command rất quan trọng khi deploy production.

Laravel sẽ cache các thành phần quan trọng như:

Configuration
Events
Routes
Views

Laravel documentation khuyến nghị chạy php artisan optimize trong deployment process.


17. config:cache

Chạy:

php artisan config:cache

Laravel gom configuration vào cache.

Điều này giúp giảm việc phải đọc nhiều file configuration khi application boot.


18. Lưu ý cực kỳ quan trọng về env()

Sau khi:

php artisan config:cache

không nên viết:

$name = env('APP_NAME');

trực tiếp trong application code.

Không nên:

class BlogController
{
    public function index()
    {
        $debug = env('APP_DEBUG');
    }
}

Thay vào đó:

$debug = config('app.debug');

Tư duy đúng:

.env
 ↓
config/*.php
 ↓
config(...)

Ví dụ trong:

config/app.php

có:

'debug' => (bool) env('APP_DEBUG', false),

Application sử dụng:

config('app.debug');

Laravel documentation lưu ý rằng sau khi config:cache, .env không còn được load trong request và env() bên ngoài configuration files có thể trả về null.


19. Cache Routes

Laravel có:

php artisan route:cache

Command này tạo route cache.

Đặc biệt có lợi với application có nhiều routes.

Blog CMS của chúng ta có thể có:

Web Routes
Admin Routes
Blog Routes
API Routes
Auth Routes

Khi số lượng route tăng lên, route caching giúp giảm thời gian đăng ký routes khi application boot.


20. Cache Views

Chạy:

php artisan view:cache

Laravel sẽ precompile Blade views.

Ví dụ:

resources/views/
       ↓
Blade
       ↓
Compiled Views

Nhờ vậy production không phải compile từng Blade view lần đầu khi request.

Laravel khuyến nghị cache views trong deployment process.


21. Cache Events

Laravel cũng hỗ trợ:

php artisan event:cache

Command này cache event → listener mappings.

Ví dụ Blog CMS:

Registered
    ↓
SendWelcomeEmail

PostPublished
    ↓
SendNotification

PostUpdated
    ↓
ClearPostCache

Khi application lớn, caching event discovery có thể giúp quá trình boot hiệu quả hơn.


22. Production Optimize đầy đủ

Có thể chạy:

php artisan optimize

Thay vì phải chạy riêng:

php artisan config:cache
php artisan event:cache
php artisan route:cache
php artisan view:cache

Laravel 13 cung cấp optimize như command tổng hợp cho deployment.


23. Autoloader Optimization

Khi deploy production:

composer install \
    --no-dev \
    --optimize-autoloader

Trong một dòng:

composer install --no-dev --optimize-autoloader

Ý nghĩa:

--no-dev

Không cài các package development không cần thiết.

Ví dụ:

PHPUnit
Debugbar
Development tools

--optimize-autoloader giúp Composer tối ưu class autoloading.


24. Không chạy npm run dev trên production

Development:

npm run dev

Production:

npm run build

Ví dụ:

npm install
npm run build

Sau đó:

public/build

chứa production assets.


25. Laravel Vite

Nếu Blog CMS sử dụng Vite:

resources/css
resources/js

thì production nên build:

npm run build

Thay vì để development server chạy trên production.

Mô hình:

Development
    ↓
npm run dev

Production
    ↓
npm run build

26. Database Optimization

Một trong những bottleneck lớn nhất của web application thường là database.

Ví dụ:

Post::all();

có thể lấy quá nhiều dữ liệu.

Không nên:

$posts = Post::all();

nếu database có:

1,000,000 posts

Thay vào đó:

$posts = Post::paginate(10);

27. Pagination

Blog CMS của chúng ta đã sử dụng:

->paginate(10)

Ví dụ:

$posts = Post::published()
    ->latest('published_at')
    ->paginate(10);

Thay vì lấy toàn bộ:

Post::all();

Database chỉ phải xử lý lượng dữ liệu phù hợp với page hiện tại.


28. Eager Loading

Một lỗi rất phổ biến:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->user->name;
    echo $post->category->name;
}

Có thể tạo ra vấn đề N+1 Query.

Thay vào đó:

$posts = Post::with([
    'user',
    'category'
])->get();

Laravel sẽ eager load relationship.


29. Blog CMS và N+1

Controller của chúng ta đã sử dụng:

Post::published()
    ->with(['user', 'category'])
    ->latest('published_at')
    ->paginate(10);

Đây là cách tốt hơn:

Posts
 │
 ├── User
 └── Category

thay vì để từng Post tự query User và Category.


30. Chỉ lấy những cột cần thiết

Không phải lúc nào cũng cần:

Post::all();

với toàn bộ column.

Ví dụ:

Post::query()
    ->select([
        'id',
        'title',
        'slug',
        'excerpt'
    ])
    ->latest()
    ->paginate(10);

Nếu page chỉ hiển thị:

Title
Excerpt

thì không nhất thiết phải lấy toàn bộ content lớn.


31. Database Index

Các column thường được:

WHERE
ORDER BY
JOIN

có thể cần index phù hợp.

Ví dụ:

posts.slug
posts.user_id
posts.category_id
posts.status
posts.published_at

Migration:

$table->index('status');
$table->index('published_at');

Foreign key thường đã có index phù hợp tùy schema và cách khai báo, nhưng cần hiểu execution plan và workload thực tế thay vì index mọi column.


32. Không index mọi column

Sai lầm:

Index tất cả

Index giúp query:

Nhanh hơn

nhưng cũng có cost:

INSERT
UPDATE
DELETE

phải duy trì index.

Do đó:

Query thường xuyên
      ↓
Phân tích
      ↓
Index phù hợp

Không phải:

Column nào cũng index

33. Cache Database Query

Không nên cache mọi query.

Ví dụ categories:

$categories = Cache::remember(
    'categories.active',
    3600,
    fn () => Category::active()
        ->withCount('posts')
        ->orderBy('name')
        ->get()
);

Khi category thay đổi:

Cache::forget('categories.active');

Như vậy cache có thể được invalidated đúng thời điểm.


34. Cache Invalidation

Một trong những vấn đề khó của cache là:

Cache cũ

Ví dụ:

10:00
Category = Laravel

cache:

Laravel

11:00 admin đổi:

Laravel → Laravel 13

nhưng cache vẫn:

Laravel

Nếu không clear/invalidate:

Database = Laravel 13
Cache    = Laravel

Vì vậy khi update dữ liệu quan trọng:

Cache::forget('categories.active');

hoặc sử dụng strategy phù hợp.


35. Storage

Production cần kiểm tra:

php artisan storage:link

Laravel sử dụng:

storage/app/public

cho public files và symbolic link:

public/storage

để browser có thể truy cập.

Blog CMS:

Post Image
   ↓
storage/app/public/posts
   ↓
public/storage
   ↓
Browser

36. Permissions

Laravel cần quyền ghi cho:

storage/
bootstrap/cache/

Ví dụ trên Ubuntu + Nginx/PHP-FPM:

sudo chown -R www-data:www-data /var/www/blog/storage
sudo chown -R www-data:www-data /var/www/blog/bootstrap/cache

Tùy server setup, user chạy PHP-FPM có thể khác www-data.

Không nên dùng:

chmod -R 777

chỉ để “cho chạy được”.


37. Vì sao chmod 777 nguy hiểm?

chmod -R 777 /var/www/blog

nghĩa là:

Owner     → read/write/execute
Group     → read/write/execute
Others    → read/write/execute

Đây là quyền quá rộng.

Thay vào đó:

Owner
Group
Web Server

nên được cấu hình đúng.

Nguyên tắc:

Cấp quyền tối thiểu cần thiết.


38. Security — .env

Không bao giờ public:

.env

Nginx phải trỏ:

root /var/www/blog/public;

chứ không:

root /var/www/blog;

Laravel deployment documentation nhấn mạnh rằng web server phải hướng request tới public/index.php, không phải project root, để tránh expose sensitive files.


39. Security — APP_DEBUG

Production:

APP_DEBUG=false

Không:

APP_DEBUG=true

Đây là một trong những cấu hình bảo mật cơ bản nhất của Laravel production.


40. Security — APP_ENV

Production:

APP_ENV=production

Giúp application biết mình đang chạy trong environment nào.


41. Security — Secret Keys

Các thông tin như:

APP_KEY
DB_PASSWORD
MAIL_PASSWORD
AWS_SECRET
API_KEY

không nên hard-code vào source:

$password = '123456';

Không nên:

Git
   ↓
Source
   ↓
Secret

Mà:

Environment
   ↓
.env
   ↓
config
   ↓
Application

42. Security — Password

Laravel không nên lưu password dạng plain text.

Không:

password = 123456

Laravel sử dụng hashing.

Ví dụ:

use Illuminate\Support\Facades\Hash;

$hash = Hash::make($password);

Kiểm tra:

Hash::check($password, $hash);

43. Security — Validation

Không tin dữ liệu từ browser.

Ví dụ:

$request->validate([
    'title' => ['required', 'string', 'max:255'],
    'content' => ['required', 'string'],
]);

Client-side validation:

JavaScript

chỉ giúp UX.

Server-side validation:

Laravel

mới là lớp bảo vệ thực sự.


44. Security — Mass Assignment

Model:

protected $fillable = [
    'name',
    'slug',
    'description',
    'is_active',
];

Không nên cho phép user tùy tiện gửi:

role=admin

nếu role không thuộc dữ liệu họ được phép thay đổi.

Ví dụ:

User::create($request->validated());

cần kết hợp:

Validation
+
Fillable
+
Authorization

45. Security — Authorization

Authentication:

Bạn là ai?

Authorization:

Bạn được phép làm gì?

Ví dụ:

User
 └── Xem bài viết

Admin
 ├── Tạo category
 ├── Sửa category
 ├── Xóa category
 └── Quản lý user

Không nên chỉ dựa vào:

ẩn button

mà phải bảo vệ ở server bằng:

Middleware
Policy
Gate
Authorization

46. Security — CSRF

Các form web thay đổi dữ liệu cần CSRF protection.

Ví dụ Blade:

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

    ...
</form>

Laravel có cơ chế CSRF protection cho web requests.

Không nên bỏ:

@csrf

chỉ vì form vẫn submit được trong một số trường hợp.


47. Security — SQL Injection

Không nên nối chuỗi SQL trực tiếp:

DB::select(
    "SELECT * FROM posts WHERE title = '$title'"
);

Thay vào đó sử dụng Query Builder/Eloquent:

Post::where('title', $title)->get();

Laravel sẽ sử dụng parameter binding phù hợp.


48. Security — XSS

Nếu nội dung user nhập:

<script>...</script>

không nên tùy tiện render raw HTML.

Blade mặc định:

{{ $post->title }}

sẽ escape output.

Cẩn thận với:

{!! $post->content !!}

Nếu content cho phép HTML, cần có chiến lược sanitization phù hợp.


49. Security — File Upload

Blog CMS của chúng ta có upload image.

Không nên chỉ kiểm tra:

filename.jpg

Mà phải validation:

'image' => [
    'nullable',
    'image',
    'max:2048',
]

Có thể giới hạn MIME/types theo yêu cầu application.

Ngoài server validation, frontend có thể báo:

File > 2MB

để cải thiện UX.

Nhưng validation Laravel vẫn bắt buộc.


50. Security — Storage

Không nên lưu file upload tùy tiện vào:

project root

Nên sử dụng Laravel filesystem:

$image->store('posts', 'public');

Sau đó:

php artisan storage:link

Laravel filesystem cung cấp abstraction cho local, public và các storage backend khác.


51. Security — HTTPS

Production nên sử dụng:

HTTPS

Không nên:

HTTP

để đăng nhập.

Mô hình:

Browser
   │
 HTTPS
   ▼
Nginx
   ▼
Laravel

HTTPS bảo vệ dữ liệu trên đường truyền.


52. Security — HTTP Headers

Có thể cấu hình một số security headers tại Nginx.

Ví dụ:

add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";

Laravel 13 deployment configuration mẫu cũng sử dụng các header này.

Không nên copy một danh sách security headers một cách máy móc.

Mỗi header cần hiểu rõ tác dụng và khả năng ảnh hưởng tới application.


53. Rate Limiting

Các endpoint nhạy cảm như:

Login
Register
Password Reset
API

nên có rate limiting phù hợp.

Ví dụ:

User
 ↓
Login attempts
 ↓
Rate Limit
 ↓
Too many requests
 ↓
Block / Throttle

Điều này giúp giảm abuse và brute-force attempts.


54. Logs

Production không nên bật debug để “xem lỗi”.

Hãy sử dụng logs.

Ví dụ:

Log::error('Payment failed', [
    'order_id' => $order->id,
]);

Log thường nằm trong:

storage/logs/

Có thể kiểm tra:

tail -f storage/logs/laravel.log

hoặc:

tail -f storage/logs/*.log

55. Health Check

Laravel 13 có health route:

/up

Mặc định route này trả:

200

nếu application boot thành công.

Nếu application gặp lỗi boot:

500

Laravel cung cấp route này để uptime monitor, load balancer hoặc hệ thống orchestration sử dụng.

Ví dụ:

https://example.com/up

56. Health Check trong Blog CMS

Có thể dùng:

Monitoring
    │
    ▼
https://example.com/up
    │
    ├── 200 → OK
    │
    └── 500 → Problem

Đây là một cách đơn giản để kiểm tra application còn hoạt động hay không.


57. Production Deployment Flow

Từ Bài 45 đến Bài 49, quy trình deployment của chúng ta có thể là:

Developer
    │
    ▼
Git
    │
    ▼
VPS
    │
    ▼
composer install --no-dev --optimize-autoloader
    │
    ▼
npm run build
    │
    ▼
php artisan migrate --force
    │
    ▼
php artisan optimize
    │
    ▼
php artisan reload
    │
    ▼
Nginx
    │
    ▼
Laravel 13

Laravel 13 deployment documentation cũng khuyến nghị tối ưu application và reload các long-running services sau deployment để chúng sử dụng code mới.


58. Một deployment script đơn giản

Có thể hình dung quy trình:

git pull origin main

composer install --no-dev --optimize-autoloader

npm install
npm run build

php artisan migrate --force

php artisan storage:link

php artisan optimize

php artisan reload

Tùy kiến trúc Queue/Worker, có thể cần đảm bảo process monitor như Supervisor khởi động lại worker sau khi reload.


59. Không chạy migration production tùy tiện

Development:

php artisan migrate

Production:

php artisan migrate --force

Flag:

--force

cho phép migration chạy trong production mà không yêu cầu interactive confirmation.

Nhưng:

Trước khi migration production, phải hiểu migration sẽ thay đổi database như thế nào.

Đặc biệt với database lớn:

ALTER TABLE
DROP COLUMN
Index
Data migration

có thể ảnh hưởng production.


60. Backup Database

Một production application phải nghĩ đến:

Nếu database hỏng thì sao?

Không nên chỉ có:

Database

mà cần:

Database
   │
   ▼
Backup
   │
   ├── Daily
   ├── Weekly
   └── Retention

Ví dụ MySQL có thể backup bằng:

mysqldump

Điều quan trọng không chỉ là:

Backup

mà còn:

Restore được hay không?

Một backup chưa từng thử restore chưa thể xem là chiến lược backup hoàn chỉnh.


61. Storage Backup

Database không phải dữ liệu duy nhất.

Blog CMS còn có:

Post Images
User Avatars
Uploaded Files

Nếu các file này nằm trong:

storage/app/public

thì cũng cần có chiến lược backup.

Production backup:

Database
+
Uploaded Files
+
Environment/Secrets strategy

62. Không backup vendor và node_modules như dữ liệu chính

Thông thường source repository có:

composer.json
composer.lock
package.json
package-lock.json

Có thể cài lại:

composer install
npm install

Do đó production backup nên tập trung vào:

Database
Uploaded Files
Application Source
Configuration/Secrets

và chiến lược khôi phục phù hợp.


63. Performance Checklist

Một Laravel production cơ bản:

[✓] PHP production configuration
[✓] OPcache
[✓] Composer optimized autoload
[✓] Config cache
[✓] Route cache
[✓] Event cache
[✓] View cache
[✓] Database indexes
[✓] Pagination
[✓] Eager loading
[✓] Appropriate cache
[✓] Queue
[✓] Scheduler
[✓] Nginx
[✓] PHP-FPM

Không phải tất cả đều phải tối ưu cực đại ngay từ đầu.

Nguyên tắc:

Đo → tìm bottleneck → tối ưu.


64. Đừng tối ưu mù quáng

Ví dụ application chậm.

Không nên ngay lập tức:

Redis
Horizon
Octane
Multiple servers
Load Balancer
Microservices

trong khi vấn đề thực sự là:

N+1 Query

hoặc:

SELECT *

hoặc:

Không có index

Quy trình tốt hơn:

Problem
   ↓
Measure
   ↓
Identify bottleneck
   ↓
Optimize
   ↓
Measure again

65. Production Stack của Blog CMS

Sau 49 bài, Blog CMS đã đi từ:

PHP

đến:

Laravel 13

và cuối cùng:

                         INTERNET
                             │
                             ▼
                          HTTPS
                             │
                             ▼
                          Nginx
                             │
                 ┌───────────┴───────────┐
                 │                       │
              PHP-FPM                Static Files
                 │
                 ▼
            Laravel 13
                 │
       ┌─────────┼─────────┐
       │         │         │
       ▼         ▼         ▼
     MySQL     Cache     Storage
       │
       │
       ▼
    Database
       
Queue:
Laravel → Queue → Worker → Supervisor

Scheduler:
Cron → schedule:run → Laravel Scheduler

Đây không còn là một project PHP đơn giản.

Đây đã là một Laravel application có kiến trúc production cơ bản.


66. Production .env mẫu

Ví dụ:

APP_NAME="Blog CMS"

APP_ENV=production

APP_KEY=base64:YOUR_REAL_APP_KEY

APP_DEBUG=false

APP_URL=https://example.com

LOG_CHANNEL=stack
LOG_LEVEL=error

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=blog_user
DB_PASSWORD=YOUR_DATABASE_PASSWORD

QUEUE_CONNECTION=database

CACHE_STORE=database

Không copy nguyên mẫu này vào production.

Các giá trị:

APP_KEY
DB_PASSWORD
MAIL_PASSWORD
API_KEY

phải sử dụng secret thật của server.


67. Production Command Checklist

Sau khi deploy code:

composer install --no-dev --optimize-autoloader

Build frontend:

npm run build

Migration:

php artisan migrate --force

Storage:

php artisan storage:link

Optimization:

php artisan optimize

Reload:

php artisan reload

Nếu sử dụng Supervisor cho queue worker, kiểm tra:

sudo supervisorctl status

Kiểm tra Nginx:

sudo nginx -t

Kiểm tra application:

https://example.com/up

68. Khi nào dùng optimize:clear?

Nếu production có vấn đề liên quan đến cache configuration:

php artisan optimize:clear

Sau đó kiểm tra lại .env và configuration.

Sau khi sửa xong, có thể chạy:

php artisan optimize

Tư duy:

Clear
 ↓
Fix
 ↓
Optimize

Không nên chạy optimize:clear liên tục trên production mà không hiểu lý do.


69. Những lỗi production người mới thường gặp

Lỗi 1

APP_DEBUG=true

Production.

→ Có nguy cơ lộ thông tin.


Lỗi 2

Nginx:

root /var/www/blog;

→ Sai.

Đúng:

root /var/www/blog/public;

Lỗi 3

Không chạy:

php artisan optimize

→ Có thể bỏ qua các optimization cache production.


Lỗi 4

Deploy code mới nhưng Worker vẫn chạy code cũ.

→ Reload/restart long-running services.


Lỗi 5

Không có backup database.

→ Khi database hỏng, mất dữ liệu.


Lỗi 6

Upload file nhưng không:

php artisan storage:link

→ Image không truy cập được.


Lỗi 7

Dùng:

chmod -R 777

→ Cấp quyền quá rộng.


Lỗi 8

Query:

Model::all();

trên bảng cực lớn.

→ Có thể gây tốn RAM và chậm.


70. Production Security Checklist

[ ] APP_DEBUG=false

[ ] APP_ENV=production

[ ] HTTPS

[ ] .env không commit Git

[ ] APP_KEY được bảo vệ

[ ] Database password được bảo vệ

[ ] Không expose project root

[ ] Nginx root → public/

[ ] Validation server-side

[ ] Authorization

[ ] CSRF

[ ] Password hashing

[ ] File upload validation

[ ] Rate limiting

[ ] Security headers phù hợp

[ ] Logs

[ ] Database backup

[ ] Uploaded files backup

[ ] Queue Worker monitoring

71. Production Performance Checklist

[ ] Composer optimized autoload

[ ] Config cache

[ ] Event cache

[ ] Route cache

[ ] View cache

[ ] Database indexes

[ ] Pagination

[ ] Eager loading

[ ] Query optimization

[ ] Cache dữ liệu phù hợp

[ ] Vite production build

[ ] Queue cho tác vụ nặng

[ ] Scheduler cho tác vụ định kỳ

72. Bài tập thực hành

Bài tập 1 — Production Environment

Đổi:

APP_ENV=production
APP_DEBUG=false

Sau đó kiểm tra:

App::environment();

Bài tập 2 — Optimize

Chạy:

php artisan optimize

Sau đó kiểm tra website.


Bài tập 3 — Clear Cache

Chạy:

php artisan optimize:clear

Sau đó:

php artisan optimize

Quan sát sự khác nhau.


Bài tập 4 — Route Cache

Chạy:

php artisan route:cache

Sau đó:

php artisan route:list

Bài tập 5 — View Cache

Chạy:

php artisan view:cache

Kiểm tra Blog CMS.


Bài tập 6 — Cache Category

Viết:

Cache::remember(...)

để cache danh sách category.

Sau đó khi category thay đổi:

Cache::forget(...)

Bài tập 7 — Health Check

Mở:

/up

và kiểm tra HTTP status.


Bài tập 8 — Security

Kiểm tra production:

APP_DEBUG=false

và thử truy cập:

/.env

Kết quả phải là:

Không được phép truy cập

73. Tổng kết

Sau bài này, chúng ta đã hoàn thành phần quan trọng nhất của deployment Laravel 13.

Các nguyên tắc cần nhớ:

ENV
 ↓
Configuration
 ↓
Cache
 ↓
Optimization
 ↓
Security
 ↓
Monitoring

Production không đơn giản chỉ là:

Upload source code

Mà là:

Application
+
Web Server
+
PHP-FPM
+
Database
+
Cache
+
Queue
+
Scheduler
+
Security
+
Monitoring
+
Backup

📌 74. Những command cần nhớ

Optimize

php artisan optimize

Clear optimization cache

php artisan optimize:clear

Configuration

php artisan config:cache

Routes

php artisan route:cache

Views

php artisan view:cache

Events

php artisan event:cache

Storage

php artisan storage:link

Migration production

php artisan migrate --force

Reload long-running services

php artisan reload

Laravel 13 documentation xác nhận reload được dùng để terminate các long-running services như queue workers, Reverb hoặc Octane sau deployment để process monitor có thể khởi động lại chúng với code mới.


🎯 75. Tư duy Production

Một developer Laravel không chỉ cần biết:

Controller
Model
Migration
Blade
Route

mà khi đưa application ra Internet còn phải hiểu:

Code
 ↓
Security
 ↓
Performance
 ↓
Deployment
 ↓
Monitoring
 ↓
Backup

Đó chính là sự khác biệt giữa:

"Làm được một Laravel project"

và:

"Biết triển khai một Laravel application"

🏁 KẾT THÚC PHẦN TRIỂN KHAI

Sau:

Bài 45 — Deploy Shared Hosting
Bài 46 — Deploy VPS
Bài 47 — Nginx
Bài 48 — Queue Worker & Scheduler
Bài 49 — Production Tips

chúng ta đã hoàn thành toàn bộ phần:

TRIỂN KHAI LARAVEL 13

Kiến trúc cuối cùng:

                         INTERNET
                             │
                          HTTPS
                             │
                             ▼
                          NGINX
                             │
                             ▼
                         PHP-FPM
                             │
                             ▼
                      ┌─────────────┐
                      │ Laravel 13  │
                      └──────┬──────┘
                             │
          ┌──────────────────┼──────────────────┐
          │                  │                  │
          ▼                  ▼                  ▼
       MySQL              Cache             Storage
          │
          │
          ▼
       Database

          Laravel
             │
             ▼
          Queue
             │
             ▼
          Worker
             │
             ▼
        Supervisor

          Cron
             │
             ▼
     Laravel Scheduler

Và chỉ còn một bài cuối cùng:

🎓 BÀI 50 — TỔNG KẾT DỰ ÁN BLOG CMS

Chúng ta sẽ tổng hợp toàn bộ những gì đã học:

PHP
 ↓
Laravel 13
 ↓
MVC
 ↓
Database
 ↓
Eloquent
 ↓
Relationship
 ↓
Authentication
 ↓
Authorization
 ↓
CRUD
 ↓
Upload
 ↓
Search
 ↓
Pagination
 ↓
Soft Delete
 ↓
Events
 ↓
Queue
 ↓
Mail
 ↓
Notification
 ↓
Cache
 ↓
Storage
 ↓
Logging
 ↓
REST API
 ↓
Sanctum
 ↓
Nginx
 ↓
VPS
 ↓
Production

và ráp lại thành Blog CMS hoàn chỉnh.

x1

quay về MỤC LỤC

Không có nhận xét nào:

Đăng nhận xét

Facebook Youtube RSS