เนื้อหาตอนต่อไปนี้เราจะมาดูเกี่ยวกับ 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 ก็จะประมาณนี้ เป็นแนวทางนำปรับไปใช้งานต่อๆ ไป
เนื้อหาตอนหน้าจะเป็นอะไรรอติดตาม