จากตอนที่แล้วเราดูเกี่ยวกับ request object ใน
slim framework ไปแล้ว เนื้อหานี้มาดูต่อในส่วนของ
response object เป็นการคืนค่า HTTP reponse กลับไปแสดง
ยังฝั่ง client เรามาดูการจัดการส่วนต่างๆ ของ response
เช่น status headers และ body ก่อนที่ส่งค่ากลับไปแสดง
การรับค่า Response Object
ตัวอย่างด้านล่างเป็นการรับค่า response object เข้ามาใช้งานใน route เป็น argument ตัว
ที่สองที่เรียกใช้งานในฟังก์ชั่น ที่กำหนดไว้ใน route
// Routing รับค่า response object ผ่านตัวแปร $response $app->get('/home', function (Request $request, Response $response) { $response->getBody()->write('Welcome'); return $response; });
สำหรับการใช้งานใน middleware จะใช้งานผ่าน RequestHandler ในรูปแบบดังนี้
$app->add(function (Request $request, RequestHandler $handler) { $response = $handler->handle($request); return $response; });
กรณีเราต้องการสร้าง response object ใหม่ขึ้นมาใช้งานสามารถกำการทำงานเป็นดังนี้ได้
$app->add(function (Request $request, RequestHandler $handler) use ($app) { // ตัว response เดิมที่ส่งต่อๆ กันมา $response = $handler->handle($request); // ตัว response ใหม่ $response = $app->getResponseFactory()->createResponse(); return $response; });
หรือจะเรียกใช้งาน Response class
use Slim\Psr7\Response;
แล้วกำหนดในลักษณะด้านล่างนี้ก็ได้เหมือนกัน
$app->add(function (Request $request, RequestHandler $handler) { // ตัว response เดิมที่ส่งต่อๆ กันมา $response = $handler->handle($request); // ตัว response ใหม่ $response = new Response(); return $response; });
ข้อมูล Response Status
ทุกๆ HTTP response จะมีสถานะ หรือ status code เป็นตัวเลข ที่กำหนดรูปแบบของ response
ที่ส่งกลับไปยัง client สถานะ 200 เป็นค่าเริ่มต้นของ response status ที่ส่งกลับ
สามารถดูข้อมูลของ status code ด้วยคำสั่งดังนี้
$status = $response->getStatusCode(); // 200
กรณีที่ต้องการกำหนด status code ใหม่ ก็ทำได้ดังนี้
$newResponse = $response->withStatus(302);
ข้อมูล Response Headers
ทุกๆ HTTP response มี headers แต่ใน slim framework เราจะสามารถอ่านค่าข้อมูล header ของ
response object เฉพาะค่าที่เรากำหนดเพิ่มเข้าไปเท่านั้น หากต้องการเป็น header ค่าอื่นๆ ต้องใช้ผ่าน
request object แทน ดูตัวอย่าง สองส่วนด้านล่างประกอบคำอธิบาย
// App middleware $app->add(function (Request $request, RequestHandler $handler) use ($app) { // ตัว response เดิมที่ส่งต่อๆ กันมา $response = $handler->handle($request); $headers = $response->getHeaders(); /* Array ( [Content-Type] => Array ( [0] => application/json ) ) */ /* foreach ($headers as $name => $values) { echo $name . ": " . implode(", ", $values); } */ return $response; }); // Routing $app->get('/home', function (Request $request, Response $response, $args) { $payload = json_encode(['hello' => 'world'], JSON_PRETTY_PRINT); $response->getBody()->write($payload); $response = $response->withHeader('Content-Type', 'application/json'); return $response; });
ในส่วนของ routing เรามีการกำหนด response ขึ้นมาใหม่ ด้วยการใช้คำสั่ง withHeader() แล้วกำหนด
ส่วนของ Content-Type เข้าไป เมื่อลองแสดงข้อมูล header ใน middleware ก็จะได้โครงสร้างข้อมูลเป็น
array ตามตัวอย่างในโค้ด ซึ่งมีแค่ค่าเดียวที่สามารถอ่านได้ผ่าน response object แต่จริงๆ แล้วมีค่าอื่นๆ
ด้วย แต่ต้องเรียกผ่าน request object จึงจะเห็นค่าอื่นๆ หรือสามารถ inspect ผ่าน dev console ของ
บราวเซอร์ก็จะเห็นค่าอื่นๆ ได้เช่นกัน
หากเราไม่กำหนด บรรทัดนี้
// $response = $response->withHeader('Content-Type', 'application/json');
นั่นแสดงว่าคำสั่งเรียกใช้งาน header ผ่าน response object ก็จะเป็น ค่าว่าง array เป็น 0 หรือก็คือไม่มี
ข้อมูล response header ที่สามารถแสดงได้
การแสดง header ทั้งหมด ใช้คำสั่งดังนี้
$headers = $response->getHeaders(); // print_r($headers); foreach ($headers as $name => $values) { echo $name . ": " . implode(", ", $values); }
การแสดงเฉพาะ header ที่ต้องการ ใช้คำสั่งดังนี้
$headerValueArray = $response->getHeader('Content-Type');
จะเห็นข้อมูลของแต่ละ header มีได้หลายค่า คั่นด้วย , (comma) จึงคืนค่าเป็น array หาก
เราต้องการให้แสดงเป็นข้อความเดียวก็ใช้เป็นคำสั่ง
$headerValueString = $response->getHeaderLine('Content-Type');
การตรวจสอบค่า header ว่ามีหรือไม่ใช้คำสั่ง
if ($response->hasHeader('Content-Type')) { // ทำคำสั่ง }
การกำหนดค่า header ใหม่ ใช้คำสั่ง
$newResponse = $oldResponse->withHeader('Content-type', 'application/json');
กำหนดชื่อ และค่าข้อมูลใหม่ ตามต้องการ
การเพิ่มค่า header ต่อเข้าไปจากค่าเดิม ใช้คำสั่ง
$newResponse = $oldResponse->withAddedHeader('Allow', 'PUT');
ดูตัวอย่าง
$response = $response ->withHeader('Content-Type', 'application/json') ->withAddedHeader('Content-Type','text/html') ->withAddedHeader('Allow', 'PUT') ->withAddedHeader('Allow', 'POST'); /* Array ( [Content-Type] => Array ( [0] => application/json [1] => text/html ) [Allow] => Array ( [0] => PUT [1] => POST ) ) */
withAddedHeader() จะเป็นการเพิ่มค่าใหม่ต่อเข้าไปในชื่อ header เดิมที่มีอยู่แล้ว ต่างจาก
withHeader() ที่เป็นการกำหนดค่าใหม่ให้กับชื่อ header
การลบ header สามารถใช้คำสั่งดังนี้
$newResponse = $oldResponse->withoutHeader('Allow');
จะลบได้เฉพาะข้อมูล header ของ response object ที่เรากำหนดขึ้นมาใหม่เท่านั้น และจะไปใช้ค่า
เดิมที่มีแทน
ข้อมูล Response Body
เหมือนกับรูปแบบการใช้งานในส่วนของ request body เพียงแต่ส่วนนี้จะเป็นส่วนของข้อมูลที่กำลังส่ง
ออกไปหรือข้อมูลฝั่ง response ดูตัวอย่าง
// Routing $app->get('/home', function (Request $request, Response $response, $args) { $response->getBody()->write('Welcome'); $body = $response->getBody(); // ได้ข้อมูล stream มาไว้ในตัวแปร $body echo $body->getSize()."<br>"; // ขนาดข้อมูล byte ถ้าไม่รู้จักจะเป็น null // 7 echo $body->tell()."<br>"; // 0 ตำแหน่งข้อมูลปัจจุบัน // 7 echo $body->eof()."<br>"; // false ยังไม่สิ้นสุดข้อมูล stream // false echo $body->isSeekable()."<br>"; // 1 หรือ true ถ้าสามารถไปยังตำแหน่งข้อมูลได้ // 1 // echo $body->seek(2); // ไปเาิ่มข้อมูลที่ตำแหน่งที่ 2 $body->rewind(); // ไปเริ่มข้อมูลที่ตำแหน่ง เริ่มต้น // echo $body->write(); echo $body->isReadable()."<br>"; // 1 หรือ true ถ้าสามารถอ่านได้ // 1 echo $body->getContents()."<br>"; // ดึงข้อมูล stream ทั้งหมดมาแสดง // Welcome echo $body->eof()."<br>"; // 1 หรือ true เพราะแสดงข้อมูลทั้งหมดจบแล้ว // 1 $body->rewind(); // ไปเริ่มข้อมูลที่ตำแหน่ง เริ่มต้น echo $body->read(3)."<br>"; // อ่านข้อมูลมา 3 ตัวแรก // Wel echo $body->tell()."<br>"; // 3 ตำแหน่งข้อมูลปัจจุบัน // 3 $body->seek(2);// เลื่อนข้อมูลไปอีก 2 ตำแหน่ง echo $body->tell()."<br>"; // 2 ตำแหน่งข้อมูลปัจจุบัน // 2 echo $body->read(3)."<br>"; // ดึงข้อมูล 3 ตัวเริ่มจากตำแหน่งที่ 2 // lco echo $body->tell()."<br>"; // 5 ตำแหน่งปัจจุบัน // 5 print_r($body->getMetadata())."<br>"; // array ข้อมูลอื่นๆ // Array ( [wrapper_type] => PHP [stream_type] => TEMP [mode] => w+b // [unread_bytes] => 0 [seekable] => 1 [uri] => php://temp ) return $response; });
ข้อมูลที่เราจะส่งออกไปทาง response เป็นข้อความคำว่า 'Welcome' ขนาด 7 ตัวอักษร รูปแบบการทำงาน
ของคำสั่งต่างๆ แสดงในโค้ด สังเกตว่า ข้อมูลนี้เป้นข้อมูล stream แบบ temp หรือข้อมูลชั่วคราวก่อน
ที่จะถูกส่งออกไปแสดง ต่างจาก request ที่จะเป็นข้อมูล stream Input
เราสามารถเรียกใช้งานข้อมูล stream อื่น เพื่อส่งออกไปแสดงได้ เช่น จากไฟล์ในระบบ โดยจะใช้งาน
กับคำสั่ง withBody() ดูตัวอย่าง การเปิดไฟล์ข้อมูล แล้วส่งออกไปกับ response
ใช้งาน StreamFactory class
use Slim\Psr7\Factory\StreamFactory;
ตัวอย่างการใช้งานเปิดอ่านไฟล์ composer.json
// Routing $app->get('/home', function (Request $request, Response $response, $args) { // $response->getBody()->write('Welcome'); $streamFactory = new StreamFactory(); $newStream = $streamFactory->createStreamFromFile("composer.json",'r'); $response = $response ->withBody($newStream) ->withHeader('Content-type', 'application/json'); return $response; });
การแสดงข้อมูล JSON
เราสามารถกำหนด response ข้อมูลไปแสดงเป็น JSON String data ได้ดังนี้
$data = array('name' => 'Rob', 'age' => 40); $payload = json_encode($data); $response->getBody()->write($payload); return $response ->withHeader('Content-Type', 'application/json') ->withStatus(201);
ในตัวอย่างเราเพิ่มการกำหนด status code เข้าไปด้วย
แนวทางการใช้งาน ข้อมูล JSON นี้จะเป็นแนวทางที่เราจะประยุกต์เพื่อใช้กับรุปแบบ API ในลำดับต่อๆ ไป
การ Redirect
ในกรณีที่เราต้องการเปลี่ยน url หรือลิ้งค์ไปยังหน้าใหม่ เว็บไซต์ใหม่ หรือเพจใหม่ สามารถใช้คำสั่งได้ดังนี้
return $response ->withHeader('Location', 'https://www.ninenik.com') ->withStatus(302);
เนื้อหาเกี่ยวกับการใช้งาน Response object ใน Slim framework 4 ก็มีแนวทางเบื้องต้นประมาณนี้
หลายๆ เนื้อหาก็อาจจะคุ้นเคยมาบ้างแล้ว บางรูปแบบก็คล้ายกับการใช้งานกับ request object
เนื้อหาตอนหน้าจะเป็นอะไร รอติดตาม