Lập trình · 22/09/2026

Học Laravel 13 – Bài 04: Cấu hình môi trường và logging trong Laravel 13

Bài 4 của khóa Laravel 13: tách cấu hình TaskFlow khỏi code xử lý request và thêm một log có chủ đích. Tiếp nối bài 3 về vòng đời request, chúng ta vẫn dùng trang /taskflow, chưa thêm database nghiệp vụ. Mục tiêu là thay đổi tên hiển thị theo môi trường và bật/tắt log mà không sửa route mỗi lần.

Cấu hình môi trường và logging trong Laravel 13

Bài 4 của khóa Laravel 13: tách cấu hình TaskFlow khỏi code xử lý request và thêm một log có chủ đích. Tiếp nối bài 3 về vòng đời request, chúng ta vẫn dùng trang /taskflow, chưa thêm database nghiệp vụ. Mục tiêu là thay đổi tên hiển thị theo môi trường và bật/tắt log mà không sửa route mỗi lần.

1. Phân biệt ba lớp cấu hình

Biến môi trường cung cấp đầu vào; các file trong config chuyển đầu vào thành cấu hình ứng dụng; route, controller và service đọc cấu hình qua config(). Trong TaskFlow, đường đi sẽ là TASKFLOW_NAME → taskflow.name → projectName trong view. Việc tách này cho phép test thay cấu hình mà không sửa file .env thật.

Dùng env() trong file config, không rải trong code nghiệp vụ. Khi config được cache, Laravel không nạp .env như lúc chưa cache; env() ngoài config có thể không nhận giá trị bạn mong đợi, dù biến cấp hệ điều hành vẫn có thể tồn tại. Xem tài liệu cấu hình Laravel 13.

2. Thêm cấu hình riêng của TaskFlow

Tạo config/taskflow.php và thêm hai dòng không bí mật vào .env.example. Nếu muốn ghi đè giá trị local, thêm chúng vào .env của máy học; không sao chép đè toàn bộ file đang có:

<?php
// config/taskflow.php
return [
    'name' => env('TASKFLOW_NAME', 'TaskFlow'),
    'overview_logging' => env('TASKFLOW_OVERVIEW_LOGGING', false),
];
# .env.example (and your local .env when needed)
TASKFLOW_NAME=TaskFlow
TASKFLOW_OVERVIEW_LOGGING=false

Tên có khoảng trắng cần đặt trong dấu ngoặc kép, ví dụ TASKFLOW_NAME="TaskFlow Local". Dùng literal false như ví dụ cho cờ tắt. Không dùng chuỗi tùy ý như "off" rồi giả định PHP sẽ xem là false; đó là chuỗi không rỗng. Nếu một cấu hình đến từ nguồn không kiểm soát, cần validation rõ ràng thay vì ép kiểu đoán ý nghĩa.

3. Thay route của bài trước

Trong routes/web.php, thay route /taskflow cũ bằng đoạn sau, không thêm route trùng. Giữ route welcome; mỗi import chỉ xuất hiện một lần:

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;

Route::get('/taskflow', function () {
    if (config('taskflow.overview_logging')) {
        Log::info('taskflow.overview.viewed', ['route' => 'taskflow.overview']);
    }

    return view('taskflow.overview', [
        'projectName' => config('taskflow.name'),
        'milestone' => 'Request lifecycle',
    ]);
})->name('taskflow.overview');

Giữ nguyên view ở bài 3. Khi cờ false, route không ghi log info này; khi true, một sự kiện có tên ổn định được ghi với context chỉ gồm tên route. Đây là ví dụ phục vụ học tập, không phải yêu cầu log mọi lượt xem trên website thật. Với traffic lớn, các sự kiện ít giá trị dễ làm tăng chi phí và che mất lỗi quan trọng.

4. Chọn channel và mức log có chủ đích

Kiểm tra config/logging.php của chính project để biết LOG_CHANNEL trỏ tới đâu. Với local, có thể chọn LOG_CHANNEL=single và LOG_LEVEL=debug để dễ quan sát storage/logs/laravel.log. Đừng giả định mọi triển khai đều ghi file này: container có thể dùng stderr và chuyển log sang hệ thống thu thập tập trung.

info mô tả sự kiện bình thường đáng ghi nhận; warning báo tình huống bất thường có thể phục hồi; error ghi thất bại cần điều tra. Ngưỡng channel lọc bỏ mức thấp hơn: nếu đặt error thì không thấy log info của ví dụ là đúng. Các channel và context được mô tả trong tài liệu logging.

Không log toàn bộ request, Authorization, cookie, mật khẩu, token hoặc .env. Ví dụ chỉ chọn field được phép thay vì cố xóa secret khỏi một payload tùy ý. Dòng log cũng không phải bằng chứng giao dịch database đã commit; khi học transaction và queue, chúng ta sẽ chọn thời điểm ghi nhận phù hợp.

5. Kiểm thử cấu hình và nội dung log

Tạo tests/Feature/TaskFlowConfigurationTest.php:

<?php
namespace Tests\Feature;

use Illuminate\Support\Facades\Log;
use Tests\TestCase;

class TaskFlowConfigurationTest extends TestCase
{
    public function test_overview_uses_configuration_and_logs_only_allowlisted_context(): void
    {
        config(['taskflow.name' => 'Course Workspace', 'taskflow.overview_logging' => true]);
        Log::spy();

        $this->get('/taskflow?token=must-not-be-logged')
            ->assertOk()
            ->assertViewHas('projectName', 'Course Workspace');

        Log::shouldHaveReceived('info')->once()->with(
            'taskflow.overview.viewed',
            ['route' => 'taskflow.overview'],
        );
    }

    public function test_overview_logging_can_be_disabled(): void
    {
        config(['taskflow.overview_logging' => false]);
        Log::spy();

        $this->get('/taskflow')->assertOk();

        Log::shouldNotHaveReceived('info');
    }
}
php artisan test --filter=TaskFlowConfigurationTest
php artisan test

Log spy kiểm tra lời gọi và context chính xác mà không ghi một file thật. Chuỗi token trong URL là dữ liệu giả cho test; không dùng secret thật để thử. Test chứng minh đoạn route này chỉ truyền context cho phép, không chứng minh toàn bộ ứng dụng, proxy hay access log đều loại bỏ mọi dữ liệu nhạy cảm. Không đưa token thật vào URL dù route không log nó.

6. Tự làm thí nghiệm config cache

Chỉ thực hành trên TaskFlow local: đặt TASKFLOW_NAME="TaskFlow Local", chạy config:clear và xem /taskflow. Sau đó cache cấu hình:

php artisan config:cache
php artisan config:show taskflow

Sửa tên trong .env thành "TaskFlow Changed" rồi xem lại config:show taskflow. Khi cache vẫn tồn tại, giá trị còn là bản đã cache. Chạy config:clear, kiểm tra lại và cuối cùng trả tên về TaskFlow để test của bài 3 vẫn dùng baseline. Không chạy config:show database để chia sẻ kết quả chẩn đoán vì output có thể chứa thông tin kết nối.

Ở local, không cần giữ config cache trong lúc liên tục chỉnh cấu hình. Khi deploy, tạo cache sau khi môi trường đích đã có đúng biến cấu hình; không đóng gói cache từ máy cá nhân kèm secret. Worker chạy dài cần restart theo quy trình deploy để đọc cấu hình mới. Đừng coi việc sửa .env là bằng chứng mọi process đã nhận giá trị mới.

7. Lỗi thường gặp và tiêu chuẩn hoàn thành

  • Đổi .env nhưng không đổi giao diện: kiểm tra cache, biến môi trường cấp hệ thống và đúng project đang phục vụ.
  • Không thấy log: kiểm tra cờ bật, channel, level, quyền ghi và hệ thống thu thập log.
  • Test tên TaskFlow thất bại: xem bạn có giữ tên thử nghiệm trong .env hay không; test cấu hình mới tự đặt giá trị riêng.
  • Production lộ exception: APP_DEBUG phải false; vẫn cần log nội bộ có kiểm soát, không tắt mọi quan sát.

Hoàn thành khi bạn giải thích được vì sao config() dùng được sau cache, bật/tắt sự kiện mà không sửa route, và chỉ ra giới hạn của log spy. Bản thực hành đã pass 7 test với 13 assertions; config:cache, config:show taskflow và config:clear đều chạy thành công. Chưa có kiểm chứng một triển khai production của TaskFlow ở bài này.

Điều hướng: Bài 3 · Lộ trình. Bài tiếp theo đưa routing, controller và middleware vào cùng một luồng.

Điều hướng khóa học Laravel 13

Bài trước (03) · Bài sau (05) · Mục lục trọn bộ 37 bài

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.