Kotchasan Framework Documentation

Kotchasan Framework Documentation

Controller Classes - คลาสควบคุม

TH 05 Feb 2026 06:23

Controller Classes - คลาสควบคุม

ภาพรวม

Controller Classes ใน Kotchasan Framework เป็นส่วนประกอบหลักของ MVC pattern ที่ทำหน้าที่เป็นตัวกลางระหว่าง Model และ View โดยจัดการ HTTP requests, business logic, และการส่งผ่านข้อมูลไปยัง View

คุณสมบัติหลัก

  • MVC Pattern: ใช้งานตาม Model-View-Controller pattern
  • Request Handling: จัดการ HTTP requests ทุกประเภท
  • API Support: รองรับการสร้าง REST API
  • Authentication: ระบบยืนยันตัวตนและการอนุญาต
  • Validation: ตรวจสอบความถูกต้องของข้อมูล
  • Error Handling: จัดการข้อผิดพลาดอย่างสม่ำเสมอ
  • Response Formatting: จัดรูปแบบการตอบกลับ

สารบัญ

  1. Controller Base Class
  2. ApiController - REST API Controller
  3. HTTP Request และ Response Handling
  4. Authentication และ Security
  5. Error Handling และ Validation
  6. Best Practices - แนวทางปฏิบัติที่ดี

Controller Base Class

Controller base class เป็นคลาสพื้นฐานสำหรับการสร้าง controllers ทั้งหมด

การใช้งาน Controller พื้นฐาน

use Kotchasan\Database;

use Kotchasan\Controller;
use Kotchasan\Http\Request;

class UserController extends Controller
{
    /
      แสดงรายการผู้ใช้
     /
    public function index(Request $request)
    {
        // ดึงข้อมูลผู้ใช้
        $users = Kotchasan\Database::create()
            ->select(['id', 'name', 'email', 'status'])
            ->from('users')
            ->where(['status', 'active'])
            ->orderBy('name')
            ->fetchAll();

        // ส่งข้อมูลไปยัง View
        return View::create()
            ->assign('users', $users)
            ->render('user/index');
    }

    /
      แสดงฟอร์มสร้างผู้ใช้ใหม่
     /
    public function create(Request $request)
    {
        return View::create()->render('user/create');
    }

    /
      บันทึกผู้ใช้ใหม่
     /
    public function store(Request $request)
    {
        $input = $request->getParsedBody();

        // Validation
        $errors = $this->validateUserInput($input);
        if (!empty($errors)) {
            return View::create()
                ->assign('errors', $errors)
                ->assign('input', $input)
                ->render('user/create');
        }

        // บันทึกข้อมูล
        $userId = Kotchasan\Database::create()
            ->insert('users')
            ->values([
                'name' => $input['name'],
                'email' => $input['email'],
                'password' => password_hash($input['password'], PASSWORD_DEFAULT),
                'created_at' => date('Y-m-d H:i:s')
            ])
            ->execute();

        // Redirect หลังจากบันทึกสำเร็จ
        return Response::create()
            ->withStatus(302)
            ->withHeader('Location', '/users/' . $userId);
    }

    /
      แสดงข้อมูลผู้ใช้
     /
    public function show(Request $request)
    {
        $userId = $request->getAttribute('id');

        $user = Kotchasan\Database::create()
            ->select(['id', 'name', 'email', 'created_at'])
            ->from('users')
            ->where(['id', $userId])
            ->first();

        if (!$user) {
            return Response::create()
                ->withStatus(404)
                ->getBody()->write('User not found');
        }

        return View::create()
            ->assign('user', $user)
            ->render('user/show');
    }

    /
      Validation สำหรับข้อมูลผู้ใช้
     /
    private function validateUserInput($input)
    {
        $errors = [];

        if (empty($input['name'])) {
            $errors['name'] = 'ชื่อเป็นข้อมูลที่จำเป็น';
        }

        if (empty($input['email'])) {
            $errors['email'] = 'อีเมลเป็นข้อมูลที่จำเป็น';
        } elseif (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'รูปแบบอีเมลไม่ถูกต้อง';
        }

        if (empty($input['password'])) {
            $errors['password'] = 'รหัสผ่านเป็นข้อมูลที่จำเป็น';
        } elseif (strlen($input['password']) < 6) {
            $errors['password'] = 'รหัสผ่านต้องมีอย่างน้อย 6 ตัวอักษร';
        }

        return $errors;
    }
}

Factory Pattern

// การสร้าง Controller instance
$controller = Controller::create();

// การใช้งานใน routing
$userController = UserController::create();
$response = $userController->index($request);

ApiController - REST API Controller

ApiController เป็นคลาสพิเศษสำหรับการสร้าง REST API endpoints

คุณสมบัติของ ApiController

  • REST API Support: รองรับ REST API patterns
  • JSON Response: ส่งผลลัพธ์เป็น JSON
  • Authentication: ระบบยืนยันตัวตนด้วย Token
  • CORS Support: รองรับ Cross-Origin Resource Sharing
  • Rate Limiting: จำกัดอัตราการเรียกใช้ API
  • Error Standardization: มาตรฐานการส่งข้อผิดพลาด

การใช้งาน ApiController

use Kotchasan\Database;

use Kotchasan\ApiController;
use Kotchasan\Http\Request;
use Kotchasan\Http\Response;

class UserApiController extends ApiController
{
    /
      ดึงรายการผู้ใช้ - GET /api/users
     /
    public function index(Request $request): Response
    {
        try {
            // ตรวจสอบ authentication
            $this->requireAuthentication($request);

            // ดึงพารามิเตอร์จาก query string
            $page = (int) $request->getQueryParam('page', 1);
            $limit = (int) $request->getQueryParam('limit', 20);
            $search = $request->getQueryParam('search', '');

            // สร้าง query
            $query = Kotchasan\Database::create()
                ->select(['id', 'name', 'email', 'status', 'created_at'])
                ->from('users');

            // เพิ่มเงื่อนไขการค้นหา
            if (!empty($search)) {
                $query->where(function($q) use ($search) {
                    $q->where(['name', 'LIKE', "%{$search}%"])
                      ->orWhere(['email', 'LIKE', "%{$search}%"]);
                });
            }

            // นับจำนวนทั้งหมด
            $total = $query->count();

            // ดึงข้อมูลพร้อม pagination
            $users = $query
                ->orderBy('created_at', 'DESC')
                ->limit($limit, ($page - 1)  $limit)
                ->fetchAll();

            // ส่งผลลัพธ์แบบ paginated
            return $this->paginatedResponse($users, $total, $page, $limit);

        } catch (Exception $e) {
            return $this->errorResponse(
                'เกิดข้อผิดพลาดในการดึงข้อมูลผู้ใช้',
                500,
                ['error' => $e->getMessage()]
            );
        }
    }

    /
      ดึงข้อมูลผู้ใช้เฉพาะ - GET /api/users/{id}
     /
    public function show(Request $request): Response
    {
        try {
            $this->requireAuthentication($request);

            $userId = $request->getAttribute('id');

            $user = Kotchasan\Database::create()
                ->select(['id', 'name', 'email', 'status', 'created_at', 'updated_at'])
                ->from('users')
                ->where(['id', $userId])
                ->first();

            if (!$user) {
                return $this->errorResponse('ไม่พบข้อมูลผู้ใช้', 404);
            }

            return $this->successResponse($user, 'ดึงข้อมูลผู้ใช้สำเร็จ');

        } catch (Exception $e) {
            return $this->errorResponse(
                'เกิดข้อผิดพลาดในการดึงข้อมูลผู้ใช้',
                500,
                ['error' => $e->getMessage()]
            );
        }
    }

    /
      สร้างผู้ใช้ใหม่ - POST /api/users
     /
    public function store(Request $request): Response
    {
        try {
            $this->requireAuthentication($request);

            $input = $request->getParsedBody();

            // Validation
            $validationErrors = $this->validateInput([
                'name' => 'required|string|min:2|max:100',
                'email' => 'required|email|unique:users,email',
                'password' => 'required|string|min:6'
            ], $input);

            if (!empty($validationErrors)) {
                return $this->errorResponse(
                    'ข้อมูลไม่ถูกต้อง',
                    422,
                    $validationErrors
                );
            }

            // สร้างผู้ใช้ใหม่
            $userId = Kotchasan\Database::create()
                ->insert('users')
                ->values([
                    'name' => $input['name'],
                    'email' => $input['email'],
                    'password' => password_hash($input['password'], PASSWORD_DEFAULT),
                    'status' => 'active',
                    'created_at' => date('Y-m-d H:i:s'),
                    'updated_at' => date('Y-m-d H:i:s')
                ])
                ->execute();

            // ดึงข้อมูลผู้ใช้ที่สร้างใหม่
            $newUser = Kotchasan\Database::create()
                ->select(['id', 'name', 'email', 'status', 'created_at'])
                ->from('users')
                ->where(['id', $userId])
                ->first();

            return $this->successResponse(
                $newUser,
                'สร้างผู้ใช้ใหม่สำเร็จ',
                201
            );

        } catch (Exception $e) {
            return $this->errorResponse(
                'เกิดข้อผิดพลาดในการสร้างผู้ใช้',
                500,
                ['error' => $e->getMessage()]
            );
        }
    }

    /
      อัปเดตข้อมูลผู้ใช้ - PUT/PATCH /api/users/{id}
     /
    public function update(Request $request): Response
    {
        try {
            $this->requireAuthentication($request);

            $userId = $request->getAttribute('id');
            $input = $request->getParsedBody();

            // ตรวจสอบว่าผู้ใช้มีอยู่จริง
            $existingUser = Kotchasan\Database::create()
                ->select(['id'])
                ->from('users')
                ->where(['id', $userId])
                ->first();

            if (!$existingUser) {
                return $this->errorResponse('ไม่พบข้อมูลผู้ใช้', 404);
            }

            // Validation
            $validationErrors = $this->validateInput([
                'name' => 'string|min:2|max:100',
                'email' => "email|unique:users,email,{$userId}",
                'password' => 'string|min:6'
            ], $input);

            if (!empty($validationErrors)) {
                return $this->errorResponse(
                    'ข้อมูลไม่ถูกต้อง',
                    422,
                    $validationErrors
                );
            }

            // เตรียมข้อมูลสำหรับอัปเดต
            $updateData = ['updated_at' => date('Y-m-d H:i:s')];

            if (isset($input['name'])) {
                $updateData['name'] = $input['name'];
            }

            if (isset($input['email'])) {
                $updateData['email'] = $input['email'];
            }

            if (isset($input['password'])) {
                $updateData['password'] = password_hash($input['password'], PASSWORD_DEFAULT);
            }

            // อัปเดตข้อมูล
            Kotchasan\Database::create()
                ->update('users')
                ->set($updateData)
                ->where(['id', $userId])
                ->execute();

            // ดึงข้อมูลที่อัปเดตแล้ว
            $updatedUser = Kotchasan\Database::create()
                ->select(['id', 'name', 'email', 'status', 'updated_at'])
                ->from('users')
                ->where(['id', $userId])
                ->first();

            return $this->successResponse(
                $updatedUser,
                'อัปเดตข้อมูลผู้ใช้สำเร็จ'
            );

        } catch (Exception $e) {
            return $this->errorResponse(
                'เกิดข้อผิดพลาดในการอัปเดตข้อมูลผู้ใช้',
                500,
                ['error' => $e->getMessage()]
            );
        }
    }

    /
      ลบผู้ใช้ - DELETE /api/users/{id}
     */
    public function destroy(Request $request): Response
    {
        try {
            $this->requireAuthentication($request);

            $userId = $request->getAttribute('id');

            // ตรวจสอบว่าผู้ใช้มีอยู่จริง
            $existingUser = Kotchasan\Database::create()
                ->select(['id', 'name'])
                ->from('users')
                ->where(['id', $userId])
                ->first();

            if (!$existingUser) {
                return $this->errorResponse('ไม่พบข้อมูลผู้ใช้', 404);
            }

            // ลบข้อมูลผู้ใช้
            Kotchasan\Database::create()
                ->delete('users')
                ->where(['id', $userId])
                ->execute();

            return $this->successResponse(
                ['deleted_user' => $existingUser],
                'ลบผู้ใช้สำเร็จ'
            );

        } catch (Exception $e) {
            return $this->errorResponse(
                'เกิดข้อผิดพลาดในการลบผู้ใช้',
                500,
                ['error' => $e->getMessage()]
            );
        }
    }
}

HTTP Request และ Response Handling

Request Handling

use Kotchasan\Database;

class ProductController extends Controller
{
    public function search(Request $request)
    {
        // ดึงข้อมูลจาก Query Parameters
        $query = $request->getQueryParam('q', '');
        $category = $request->getQueryParam('category', '');
        $minPrice = (float) $request->getQueryParam('min_price', 0);
        $maxPrice = (float) $request->getQueryParam('max_price', 0);
        $page = (int) $request->getQueryParam('page', 1);
        $limit = (int) $request->getQueryParam('limit', 20);

        // ดึงข้อมูลจาก Request Body (POST/PUT)
        $postData = $request->getParsedBody();

        // ดึงข้อมูลจาก Headers
        $authToken = $request->getHeaderLine('Authorization');
        $contentType = $request->getHeaderLine('Content-Type');

        // ดึงข้อมูลจาก Cookies
        $sessionId = $request->getCookieParam('session_id');

        // ดึงข้อมูลจาก Route Parameters
        $productId = $request->getAttribute('id');

        // ดึงข้อมูลไฟล์ที่อัปโหลด
        $uploadedFiles = $request->getUploadedFiles();

        // สร้าง query สำหรับค้นหา
        $searchQuery = Kotchasan\Database::create()
            ->select(['id', 'name', 'price', 'category', 'image'])
            ->from('products');

        // เพิ่มเงื่อนไขการค้นหา
        if (!empty($query)) {
            $searchQuery->where(['name', 'LIKE', "%{$query}%"]);
        }

        if (!empty($category)) {
            $searchQuery->where(['category', $category]);
        }

        if ($minPrice > 0) {
            $searchQuery->where(['price', '>=', $minPrice]);
        }

        if ($maxPrice > 0) {
            $searchQuery->where(['price', '<=', $maxPrice]);
        }

        // นับจำนวนผลลัพธ์
        $total = $searchQuery->count();

        // ดึงข้อมูลพร้อม pagination
        $products = $searchQuery
            ->orderBy('name')
            ->limit($limit, ($page - 1) * $limit)
            ->fetchAll();

        return View::create()
            ->assign('products', $products)
            ->assign('total', $total)
            ->assign('currentPage', $page)
            ->assign('totalPages', ceil($total / $limit))
            ->render('product/search');
    }
}

Response Handling

class ResponseController extends Controller
{
    /
      ส่ง JSON Response
     /
    public function jsonResponse()
    {
        $data = [
            'status' => 'success',
            'message' => 'ดึงข้อมูลสำเร็จ',
            'data' => [
                'users' => [
                    ['id' => 1, 'name' => 'John'],
                    ['id' => 2, 'name' => 'Jane']
                ]
            ],
            'timestamp' => time()
        ];

        return Response::create()
            ->withHeader('Content-Type', 'application/json')
            ->withStatus(200)
            ->getBody()->write(json_encode($data));
    }

    /
      ส่ง HTML Response
     /
    public function htmlResponse()
    {
        $content = View::create()
            ->assign('title', 'หน้าแรก')
            ->assign('message', 'ยินดีต้อนรับ')
            ->render('home/index');

        return Response::create()
            ->withHeader('Content-Type', 'text/html; charset=utf-8')
            ->withStatus(200)
            ->getBody()->write($content);
    }

    /
      Redirect Response
     /
    public function redirectResponse()
    {
        return Response::create()
            ->withStatus(302)
            ->withHeader('Location', '/dashboard');
    }

    /
      File Download Response
     /
    public function downloadFile(Request $request)
    {
        $filename = $request->getAttribute('filename');
        $filePath = '/path/to/files/' . $filename;

        if (!file_exists($filePath)) {
            return Response::create()
                ->withStatus(404)
                ->getBody()->write('File not found');
        }

        $fileContent = file_get_contents($filePath);

        return Response::create()
            ->withHeader('Content-Type', 'application/octet-stream')
            ->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
            ->withHeader('Content-Length', strlen($fileContent))
            ->withStatus(200)
            ->getBody()->write($fileContent);
    }

    /
      Image Response
     /
    public function serveImage(Request $request)
    {
        $imageId = $request->getAttribute('id');
        $imagePath = '/path/to/images/' . $imageId . '.jpg';

        if (!file_exists($imagePath)) {
            return Response::create()->withStatus(404);
        }

        $imageContent = file_get_contents($imagePath);

        return Response::create()
            ->withHeader('Content-Type', 'image/jpeg')
            ->withHeader('Cache-Control', 'public, max-age=86400')
            ->withStatus(200)
            ->getBody()->write($imageContent);
    }
}

Authentication และ Security

Token-based Authentication

use Kotchasan\Database;

class AuthController extends Controller
{
    /
      Login และสร้าง Token
     /
    public function login(Request $request): Response
    {
        $input = $request->getParsedBody();

        // Validation
        if (empty($input['email']) || empty($input['password'])) {
            return $this->errorResponse('กรุณากรอกอีเมลและรหัสผ่าน', 400);
        }

        // ตรวจสอบผู้ใช้
        $user = Kotchasan\Database::create()
            ->select(['id', 'name', 'email', 'password', 'status'])
            ->from('users')
            ->where(['email', $input['email']])
            ->first();

        if (!$user || !password_verify($input['password'], $user['password'])) {
            return $this->errorResponse('อีเมลหรือรหัสผ่านไม่ถูกต้อง', 401);
        }

        if ($user['status'] !== 'active') {
            return $this->errorResponse('บัญชีผู้ใช้ถูกปิดใช้งาน', 403);
        }

        // สร้าง JWT Token
        $payload = [
            'user_id' => $user['id'],
            'email' => $user['email'],
            'iat' => time(),
            'exp' => time() + (24  60  60) // 24 ชั่วโมง
        ];

        $token = $this->generateJWTToken($payload);

        // อัปเดต last login
        Kotchasan\Database::create()
            ->update('users')
            ->set(['last_login' => date('Y-m-d H:i:s')])
            ->where(['id', $user['id']])
            ->execute();

        return $this->successResponse([
            'user' => [
                'id' => $user['id'],
                'name' => $user['name'],
                'email' => $user['email']
            ],
            'token' => $token,
            'expires_in' => 86400
        ], 'เข้าสู่ระบบสำเร็จ');
    }

    /
      ตรวจสอบ Token
     /
    protected function requireAuthentication(Request $request)
    {
        $authHeader = $request->getHeaderLine('Authorization');

        if (empty($authHeader)) {
            throw new AuthenticationException('Missing Authorization header', 401);
        }

        // ดึง Token จาก Authorization header
        if (!preg_match('/Bearer\s+(.)$/i', $authHeader, $matches)) {
            throw new AuthenticationException('Invalid Authorization header format', 401);
        }

        $token = $matches[1];

        // ตรวจสอบ JWT Token
        try {
            $payload = $this->verifyJWTToken($token);

            // ตรวจสอบว่า token ยังไม่หมดอายุ
            if ($payload['exp'] < time()) {
                throw new AuthenticationException('Token expired', 401);
            }

            // ดึงข้อมูลผู้ใช้
            $user = Kotchasan\Database::create()
                ->select(['id', 'name', 'email', 'status'])
                ->from('users')
                ->where(['id', $payload['user_id']])
                ->first();

            if (!$user || $user['status'] !== 'active') {
                throw new AuthenticationException('Invalid user', 401);
            }

            // เก็บข้อมูลผู้ใช้ใน request attribute
            $request = $request->withAttribute('user', $user);

            return $user;

        } catch (Exception $e) {
            throw new AuthenticationException('Invalid token: ' . $e->getMessage(), 401);
        }
    }

    /
      Logout
     /
    public function logout(Request $request): Response
    {
        // ใน JWT token-based auth, logout ทำได้โดยการลบ token ที่ client
        // หรือเก็บ blacklist ของ token ที่ logout แล้ว

        return $this->successResponse(
            ['message' => 'Logged out successfully'],
            'ออกจากระบบสำเร็จ'
        );
    }

    /
      ดึงข้อมูล profile ของผู้ใช้ปัจจุบัน
     */
    public function profile(Request $request): Response
    {
        $user = $this->requireAuthentication($request);

        return $this->successResponse($user, 'ดึงข้อมูล profile สำเร็จ');
    }
}

Error Handling และ Validation

Centralized Error Handling

class ErrorController extends Controller
{
    /
      จัดการ 404 Error
     /
    public function notFound(Request $request): Response
    {
        $isApiRequest = strpos($request->getHeaderLine('Content-Type'), 'application/json') !== false
                       || strpos($request->getUri()->getPath(), '/api/') === 0;

        if ($isApiRequest) {
            return $this->errorResponse('Endpoint not found', 404);
        }

        return View::create()
            ->assign('title', 'ไม่พบหน้าที่ต้องการ')
            ->assign('message', 'ขออภัย ไม่พบหน้าที่คุณต้องการ')
            ->render('errors/404')
            ->withStatus(404);
    }

    /
      จัดการ 500 Error
     /
    public function serverError(Request $request, Exception $exception): Response
    {
        // Log error
        error_log("Server Error: " . $exception->getMessage() . "\n" . $exception->getTraceAsString());

        $isApiRequest = strpos($request->getHeaderLine('Content-Type'), 'application/json') !== false
                       || strpos($request->getUri()->getPath(), '/api/') === 0;

        if ($isApiRequest) {
            $errorData = [
                'error' => 'Internal server error'
            ];

            // แสดงรายละเอียด error ใน development mode
            if (self::$cfg->debug) {
                $errorData['debug'] = [
                    'message' => $exception->getMessage(),
                    'file' => $exception->getFile(),
                    'line' => $exception->getLine(),
                    'trace' => $exception->getTrace()
                ];
            }

            return $this->errorResponse(
                'เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์',
                500,
                $errorData
            );
        }

        return View::create()
            ->assign('title', 'เกิดข้อผิดพลาด')
            ->assign('message', 'เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์')
            ->assign('debug', self::$cfg->debug ? $exception : null)
            ->render('errors/500')
            ->withStatus(500);
    }
}

Input Validation

use Kotchasan\Database;

class ValidationController extends Controller
{
    /
      Validation Rules
     /
    protected function getValidationRules()
    {
        return [
            'user_create' => [
                'name' => 'required|string|min:2|max:100',
                'email' => 'required|email|unique:users,email',
                'password' => 'required|string|min:6|confirmed',
                'phone' => 'nullable|string|regex:/^[0-9\-\+\s\(\)]+$/',
                'age' => 'nullable|integer|min:18|max:100'
            ],
            'user_update' => [
                'name' => 'string|min:2|max:100',
                'email' => 'email|unique:users,email,{id}',
                'password' => 'string|min:6|confirmed',
                'phone' => 'nullable|string|regex:/^[0-9\-\+\s\(\)]+$/',
                'age' => 'nullable|integer|min:18|max:100'
            ],
            'product_create' => [
                'name' => 'required|string|min:2|max:200',
                'price' => 'required|numeric|min:0',
                'category_id' => 'required|integer|exists:categories,id',
                'description' => 'nullable|string|max:1000',
                'image' => 'nullable|file|mimes:jpg,jpeg,png|max:2048'
            ]
        ];
    }

    /
      ตรวจสอบ Input ตาม Rules
     /
    protected function validateInput(string $ruleSet, array $input, array $context = []): array
    {
        $rules = $this->getValidationRules()[$ruleSet] ?? [];
        $errors = [];

        foreach ($rules as $field => $rule) {
            $ruleList = explode('|', $rule);
            $value = $input[$field] ?? null;

            foreach ($ruleList as $singleRule) {
                $error = $this->validateField($field, $value, $singleRule, $input, $context);
                if ($error) {
                    $errors[$field] = $error;
                    break; // หยุดตรวจสอบ rule อื่นสำหรับ field นี้
                }
            }
        }

        return $errors;
    }

    /
      ตรวจสอบ Field เดียว
     /
    private function validateField(string $field, $value, string $rule, array $input, array $context): ?string
    {
        $ruleParts = explode(':', $rule, 2);
        $ruleName = $ruleParts[0];
        $ruleParam = $ruleParts[1] ?? null;

        switch ($ruleName) {
            case 'required':
                if (empty($value)) {
                    return "ฟิลด์ {$field} เป็นข้อมูลที่จำเป็น";
                }
                break;

            case 'string':
                if (!is_string($value)) {
                    return "ฟิลด์ {$field} ต้องเป็นข้อความ";
                }
                break;

            case 'integer':
                if (!is_numeric($value) || !is_int((int)$value)) {
                    return "ฟิลด์ {$field} ต้องเป็นจำนวนเต็ม";
                }
                break;

            case 'numeric':
                if (!is_numeric($value)) {
                    return "ฟิลด์ {$field} ต้องเป็นตัวเลข";
                }
                break;

            case 'email':
                if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    return "ฟิลด์ {$field} ต้องเป็นอีเมลที่ถูกต้อง";
                }
                break;

            case 'min':
                $min = (int)$ruleParam;
                if (strlen($value) < $min) {
                    return "ฟิลด์ {$field} ต้องมีอย่างน้อย {$min} ตัวอักษร";
                }
                break;

            case 'max':
                $max = (int)$ruleParam;
                if (strlen($value) > $max) {
                    return "ฟิลด์ {$field} ต้องมีไม่เกิน {$max} ตัวอักษร";
                }
                break;

            case 'unique':
                list($table, $column, $except) = explode(',', $ruleParam . ',,');
                $except = str_replace('{id}', $context['id'] ?? '', $except);

                $query = Kotchasan\Database::create()
                    ->select(['id'])
                    ->from($table)
                    ->where([$column, $value]);

                if (!empty($except)) {
                    $query->where(['id', '!=', $except]);
                }

                if ($query->first()) {
                    return "ฟิลด์ {$field} มีการใช้งานแล้ว";
                }
                break;

            case 'exists':
                list($table, $column) = explode(',', $ruleParam);
                $exists = Kotchasan\Database::create()
                    ->select(['id'])
                    ->from($table)
                    ->where([$column, $value])
                    ->first();

                if (!$exists) {
                    return "ฟิลด์ {$field} ไม่พบข้อมูลที่เกี่ยวข้อง";
                }
                break;

            case 'confirmed':
                $confirmField = $field . '_confirmation';
                if ($value !== ($input[$confirmField] ?? null)) {
                    return "ฟิลด์ {$field} ไม่ตรงกับการยืนยัน";
                }
                break;
        }

        return null;
    }
}

Best Practices - แนวทางปฏิบัติที่ดี

1. Controller Organization

// จัดระเบียบ Controllers ตาม feature
// app/Controllers/User/UserController.php
// app/Controllers/Product/ProductController.php
// app/Controllers/Order/OrderController.php

namespace App\Controllers\User;

class UserController extends Controller
{
    // เก็บ logic ที่เกี่ยวข้องกับ User เท่านั้น
    public function index() { / ... / }
    public function show() { / ... / }
    public function create() { / ... / }
    public function update() { / ... / }
    public function delete() { / ... / }
}

2. Dependency Injection

class UserController extends Controller
{
    private $userService;
    private $notificationService;

    public function __construct(
        UserService $userService,
        NotificationService $notificationService
    ) {
        $this->userService = $userService;
        $this->notificationService = $notificationService;
    }

    public function create(Request $request): Response
    {
        $input = $request->getParsedBody();

        try {
            $user = $this->userService->createUser($input);
            $this->notificationService->sendWelcomeEmail($user);

            return $this->successResponse($user, 'สร้างผู้ใช้สำเร็จ');

        } catch (ValidationException $e) {
            return $this->errorResponse('ข้อมูลไม่ถูกต้อง', 422, $e->getErrors());
        }
    }
}

3. Response Consistency

trait ApiResponseTrait
{
$code = 20; // 0): Response
    {
        return Response::create()
            ->withHeader('Content-Type', 'application/json')
            ->withStatus($code)
            ->getBody()->write(json_encode([
                'success' => true,
                'message' => $message,
                'data' => $data,
                'timestamp' => time()
            ]));
    }

$code = 40; // 0, $errors = null): Response
    {
        $response = [
            'success' => false,
            'message' => $message,
            'timestamp' => time()
        ];

        if ($errors !== null) {
            $response['errors'] = $errors;
        }

        return Response::create()
            ->withHeader('Content-Type', 'application/json')
            ->withStatus($code)
            ->getBody()->write(json_encode($response));
    }

    protected function paginatedResponse(array $data, int $total, int $page, int $limit): Response
    {
        return $this->successResponse([
            'items' => $data,
            'pagination' => [
                'current_page' => $page,
                'per_page' => $limit,
                'total' => $total,
                'total_pages' => ceil($total / $limit),
                'has_next' => $page < ceil($total / $limit),
                'has_prev' => $page > 1
            ]
        ]);
    }
}

4. Error Handling

class BaseController extends Controller
{
    protected function handleException(Exception $e, Request $request): Response
    {
        // Log error
        error_log("Controller Error: " . $e->getMessage());

        // ตรวจสอบประเภท exception
        if ($e instanceof ValidationException) {
            return $this->errorResponse('ข้อมูลไม่ถูกต้อง', 422, $e->getErrors());
        }

        if ($e instanceof AuthenticationException) {
            return $this->errorResponse('ไม่ได้รับอนุญาต', 401);
        }

        if ($e instanceof NotFoundException) {
            return $this->errorResponse('ไม่พบข้อมูล', 404);
        }

        // Error ทั่วไป
        $message = self::$cfg->debug ? $e->getMessage() : 'เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์';
        return $this->errorResponse($message, 500);
    }
}

5. Performance Optimization

use Kotchasan\Database;

class OptimizedController extends Controller
{
    /
      ใช้ Cache สำหรับข้อมูลที่ไม่เปลี่ยนแปลงบ่อย
     /
    public function getCategories(Request $request): Response
    {
        $cache = CacheFactory::create('file');
        $cacheKey = 'categories_list';

        $categories = $cache->get($cacheKey);
        if ($categories === null) {
            $categories = Kotchasan\Database::create()
                ->select(['id', 'name', 'slug'])
                ->from('categories')
                ->where(['status', 'active'])
                ->orderBy('name')
                ->fetchAll();

            $cache->set($cacheKey, $categories, 3600); // Cache 1 ชั่วโมง
        }

        return $this->successResponse($categories);
    }

    /
      ใช้ Eager Loading เพื่อลด N+1 queries
     /
    public function getUsersWithProfiles(Request $request): Response
    {
        // แทนที่จะ query แยกสำหรับแต่ละ user
        $users = Kotchasan\Database::create()
            ->select([
                'U.id', 'U.name', 'U.email',
                'P.phone', 'P.address', 'P.avatar'
            ])
            ->from('users U')
            ->leftJoin('user_profiles P', 'U.id = P.user_id')
            ->where(['U.status', 'active'])
            ->fetchAll();

        return $this->successResponse($users);
    }
}

Controller Classes ใน Kotchasan Framework ให้ความยืดหยุ่นในการจัดการ HTTP requests และสร้าง API endpoints ที่มีประสิทธิภาพ การใช้งานที่ถูกต้องจะช่วยให้โค้ดมีความเป็นระเบียบและง่ายต่อการบำรุงรักษา