🐯
I'm a Guesser
  • 💋ยินดีต้อนรับท่านผู้อ่านที่หลงเข้ามาทุกท่าน
  • 💖Laravel ลูกรัก
    • 🌞Service Provider คืออะไร ?
      • 🙋‍♀️EventServiceProvider
    • วิธีการเก็บ Log Request และ Response ใน Laravel ผ่าน Middleware และ Events
      • เก็บ Log ทุกๆ requests ผ่าน Middleware - ตอนที่ 1
      • Log http ทุกๆ requests ผ่าน Middleware - ตอนที่ 2
    • Service Container
    • Livewire
  • 🐘php
    • PSR คือ มาตรฐานการเขียนโค้ดที่ควรทราบ
      • PSR-0 มาตรฐานการโหลด File อัตโนมัติ
      • PSR-1 มาตรฐานของโค้ต
      • PSR-4 มาตรฐานการโหลดไฟล์อัตโนมัติ
  • 🌧️Cloud
    • 🦉ส่ง Project Golang ขึ้น Lambda
  • Amazon Web Services (AWS)
    • 🐓AWS คืออะไร
    • 😅AWS Lambda
  • Other
    • Privacy Policy
Powered by GitBook
On this page
  • 1. Middleware
  • 2. ออกแบบตัวเขียน Log
  • 3. เขียน Log ลง Database
  1. Laravel ลูกรัก
  2. วิธีการเก็บ Log Request และ Response ใน Laravel ผ่าน Middleware และ Events

เก็บ Log ทุกๆ requests ผ่าน Middleware - ตอนที่ 1

เริ่มต้นวิธีการเขียน Log http requests ผ่านตัว Middleware

Previousวิธีการเก็บ Log Request และ Response ใน Laravel ผ่าน Middleware และ EventsNextLog http ทุกๆ requests ผ่าน Middleware - ตอนที่ 2

Last updated 1 year ago

เอาจริงๆแล้วมันเป็นวิธีที่ง่าย และ simple ที่สุดแล้วครับ เพราะเราสามารถจัดการได้ที่เดียวเลย และแก้ไขได้ง่าย

มาดูขั้นตอนการสร้างกันครับ

1. Middleware

คือระบบที่เราสามารถใช้เพื่อจัดการ request และ response ใน Laravel ซึ่งเราสามารถใช้เพื่อเก็บ log ได้

สร้าง middleware ใหม่ด้วยคำสั่ง:

php artisan make:middleware LogRequestMiddleware

เราก็จะได้ไฟล์ app/Http/Middleware/LogRequestMiddleware.php มีหน้าตาอย่างงี้

app/Http/Middleware/LogRequestMiddleware.php
<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;

class LogRequestMiddleware
{
    /**
     * Handle incoming request
     */
    public function handle(Request $request, \Closure $next)
    {
        //

        return $next($request);
    }
}

แล้วเอา Middleware ตัวนี้ไปลงทะเบียนลำดับการทำงานที่ app/Http/Kernel.php

เช่นตัวอย่างนี้

app/Http/Kernel.php
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
       // .....
       \App\Http\Middleware\LogRequestMiddleware::class,
    ];
    
    // ......
}

มาอธิบาย middleware กันหน่อย

ดูจากตัวแปลที่รับเข้ามาใน method handler มันจะมีแค่ $request และ $next

ซึ่งคำสั่ง $next นั้น เอาไว้กระทำกับ middleware ตัวถัดไป จนกว่าจะเสร็จทุกขั้นตอน

(ดูได้ที่ app/Http/Kernel.php)

เรามาปรับรูปแบบใหม่เพื่อเตรียมทำ log เราก็จะได้หน้าตาแบบนี้

/**
 * Handle incoming request
 */
public function handle(Request $request, \Closure $next)
{
   /** @var \Illuminate\Http\Request $response */
   $response = $next($request);
   
   // Do something...
   
   return $response;
}

ถ้าเราเขียน log จากตรงนี้มันก็ทำได้แหละครับ, แต่มันจะมีปัญหาตามมาคือ "บางที method handle ตรงนี้อาจจะมาไม่ถึงหากมี request พังก่อนหน้า"

ดังนั้นเรามาดูตรงนี้กันครับ

เพิ่ม method terminate เข้ามา ซึ่ง method นี้จะทำงานก็ต่อเมื่อ request นั้นสิ้นสุดลง

พอเพิ่มแล้วเราก็จะได้หน้าตาแบบนี้ครับ

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use App\Contracts\HttpLogger;

class LogRequestMiddleware
{
    /**
     * Handle incoming request
     */
    public function handle(Request $request, \Closure $next)
    {
        return $next($request);
    }
    
    /**
     * Handle response
     */
    public function terminate($request, $response)
    {
        //
    }
}

มันก็จะดักได้ง่ายขึ้น เพราะเราไม่ต้องกังวลตัว middleware ที่อยู่ก่อนหน้าตัวนี้

ทีนี้ เรามาออกแบบตัวเขียน log กันครับ

2. ออกแบบตัวเขียน Log

ประเด็นเลยคือ พอเราจะเขียน log แต่ละทีหนิ, เราชอบนึกเรื่องที่มันดูซับซ้อนก่อนเลยคือ "เขียนลง DB ไหนดีหล่ะ ถึงจะเร็ว"

ผมจะบอกว่า "เลิกคิดเถอะครับ" เพราะสุดท้าย คุณต้องหาสิ่งที่ดีกว่าที่สุดอยู่เรื่อยๆ

ดังนั้น, ใช้ Strategy Pattern ละกัน

โจทย์คือ

  • ต้องเก็บทุก request, method, url, header, user agent, ip address, payload

  • เก็บทุก response, status code, response header, response body

เริ่ม

สร้างไฟล์ app/Contracts/HttpLogger.php

app/Contracts/HttpLogger.php
<?php

namespace App\Contracts;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

interface HttpLogger
{
    /**
     * Write log
     * 
     * @param \Illuminate\Http\Request $request
     * @param \Illuminate\Http\Response $response
     */
    public function write(Request $request, $response);
}

แล้วทำไปใช้งานที่ middleware ได้เลย ก็จะได้หน้าตาแบบนี้

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use App\Contracts\HttpLogger;

class LogRequestMiddleware
{
    public function __construct(
        private HttpLogger $logger,
    )
    {
        //
    }
    
    /**
     * Handle incoming request
     */
    public function handle(Request $request, \Closure $next)
    {
        return $next($request);
    }
    
    /**
     * Handle response
     */
    public function terminate($request, $response)
    {
        $this->logger->write($request, $response);
    }
}

"อย่าเพิ่งไป Run นะ, พังนะ"

3. เขียน Log ลง Database

"คิดอะไรไม่ออก ก็เขียน log ลง db ตัวเองแบบง่ายๆนี่แหละ"

สร้างไฟล์ app/Features/HttpLogger/DatabaseLogger.php

app/Features/HttpLogger/DatabaseLogger.php
<?php

namespace App\Features\HttpLogger;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Contracts\HttpLogger as HttpLoggerContract;

class DatabaseLogger implements HttpLoggerContract
{
    /**
     * Write log
     */
    public function write(Request $request, $response)
    {
        DB::table('http_log_requests')->insert([
            // Do someting...
        ]);
    }
}

พอเราได้ทุกอย่างที่ต้องการแล้ว, เราก็เอาไปลงทะเบียนที่ Provider กันครับ

ในที่นี่ ผมเอาไว้ที่ app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use App\Contracts;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(
             Contracts\HttpLogger::class, 
             \App\Features\HttpLogger\DatabaseLogger::class,
        );
    }
}

เป็นอันจบครับ สำหรับการเขียน log ผ่าน middleware

💖
จากบทความก่อนหน้า