เนื้อหาตอนต่อไปนี้เราจะมาดูเกี่ยวกับ Container
ส่วนจัดการเสริมเพิ่มเติมสำหรับ นำเอาโปรแกรมการทำงาน
จากภายนอก มาใช้ร่วมกับ slim หรืออาจจะเรียกว่าเป็น
dependency injection ก็ได้ ใน Slim จะรองรับ container ใน
รูปแบบ PSR-11 เช่น PHP-DI
แต่ในที่นี้เราจะใช้เป็นตัว League Container
ติดตั้ง League Container
ให้ทำการติดตั้ง League Container ผ่าน composer ดังนี้
composer require league/container
เวลาเรียกใช้จะรวมอยู่ใน autoload แล้วสามารถนำไปใช้งานได้เลย
การใช้งาน League Container
ทำการสร้าง instance สำหรับ Container และกำหนดการใช้งานร่วมกับ app จะกำหนดไว้ก่อนคำสั่ง
create() ตามตัวอย่างด้านล่าง
// สร้าง Container โดยใช้ League Container $container = new League\Container\Container(); // กำหนดการใช้ Container สำหรับร่วมกับการสร้าง app Slim\Factory\AppFactory::setContainer($container); $app = AppFactory::create();
ต่อไปกำหนด service ที่ต้องการใช้งานเข้าไปใน container ในที่จะใช้เป็นส่วนของการทำงานร่วมกับฐาน
ข้อมูล MySQL โดยการกำหนด service จะใช้คำสั่ง add() ดังนี้
// กำหนด service ให้กับ container $container->add('db', function () { $mysqli = new mysqli("localhost", "root","","test"); if ($mysqli->connect_errno) exit(); if (!$mysqli->set_charset("utf8")) exit(); return $mysqli; });
เราสามารถเรียกใช้งานใน route หรือ middleware ได้ด้วยคำสั่ง $this->get() ดังนี้
$app->get('/home', function (Request $request, Response $response, $args) { $db = $this->get('db'); $response->getBody()->write('Welcome'); return $response; });
หรือกรณีต้องการตรวจสอบค่าก่อนว่ามีหรือไม่ ก็สามารถใช้คำสั่ง has() ดังนี้
$app->get('/home', function (Request $request, Response $response, $args) { if ($this->has('db')) { $db = $this->get('db'); } $response->getBody()->write('Welcome'); return $response; });
ตัวอย่างประยุกต์การใช้งาน Container
เราจะทำการสร้าง REST API อย่างง่ายเป็นข้อมูลจังหวัดในประเทศไทย ใช้ตัวอย่างข้อมูล
จากฐานข้อมูลตามลิ้งค์นี้ http://niik.in/que_2398_6277
ไฟล์ index.php
<?php use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; use Psr\Http\Message\ServerRequestInterface; use Psr\Log\LoggerInterface; require __DIR__ . '/./vendor/autoload.php'; // สร้าง Container โดยใช้ League Container $container = new League\Container\Container(); // กำหนดการใช้ Container สำหรับร่วมกับการสร้าง app Slim\Factory\AppFactory::setContainer($container); $app = AppFactory::create(); $app->setBasePath('/demo/api'); // กำหนด service ให้กับ container $container->add('db', function () { $mysqli = new mysqli("localhost", "root","","test"); if ($mysqli->connect_errno) exit(); if (!$mysqli->set_charset("utf8")) exit(); return $mysqli; }); // กำหนดรุปแบบ Error Handler เอง $customErrorHandler = function ( ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails, ?LoggerInterface $logger = null ) use ($app) { $payload = ['error' => $exception->getMessage()]; $response = $app->getResponseFactory()->createResponse(); $response->getBody()->write( json_encode($payload, JSON_UNESCAPED_UNICODE) ); return $response ->withHeader('Content-Type', 'application/json'); }; // Error Middleware $errorMiddleware = $app->addErrorMiddleware(false, true, true); $errorMiddleware->setDefaultErrorHandler($customErrorHandler); // เรียกใช้งานรูปแบบที่กำหนด // Routing $app->get('/province[/{id:[[:digit:]]+}]', function (Request $request, Response $response, $args) { $data = []; if ($this->has('db')) { $db = $this->get('db'); $sql = " SELECT * FROM tbl_provinces WHERE 1 "; if(isset($args['id'])){ // ถ้าระบุ id จังหวัด $sql.= " AND province_id='".(int)$args['id']."' "; } $result = $db->query($sql); if( $result && $result->num_rows > 0 ){ $data = $result->fetch_all(MYSQLI_ASSOC); } } $payload = json_encode($data); $response->getBody()->write($payload); return $response ->withHeader('Content-Type', 'application/json'); }); $app->run();
ในตัวอย่างเราใช้งาน container สำหรับสร้าง service ที่เชื่อมต่อกับฐานข้อมูล จากนั้นเรียกใช้งานใน route
ทำการดึงข้อมูลจากฐานข้อมูล แล้วส่งออกเป็นข้อมูล JSON String data
เรามีการกำหนดการสร้างรูปแบบ error middleware แบบกำหนดเอง เพื่อให้แสดงข้อมูลกรณี error ในรูปแบบ
ข้อมูล JSON String data ดูตัวอย่างผลลัพธ์การทำงาน ดังนี้
ผลลัพธ์ที่ได้
แสดงข้อมูลทั้งหมด 77 จังหวัด เมื่อเรียกไปยัง /province
แสดงข้อมูลเฉพาะจังหวัด id เท่ากับ 1 /province/1
แสดงข้อมูลเฉพาะจังหวัด id เท่ากับ 77 /province/77
แสดงข้อมูลว่าง ไม่มีจังหวัด id เท่ากับ 78 /province/78
แสดง error ไม่มีหน้าที่ตรงตามที่ระบุ /province/data
เนื้อหาเกี่ยวกับ Container ที่ใช้งานร่วมกับ slim ก็จะประมาณนี้ เป็นแนวทางนำปรับไปใช้งานต่อๆ ไป
เนื้อหาตอนหน้าจะเป็นอะไรรอติดตาม