ใน Slim framework จะมีการใช้งาน request object
ทั้งใน middleware และ route โดยฝั่ง web server
จะรับค่านี้มาจาก client สำหรับ request เราทราบไปแล้ว
ว่าเป็นข้อมูลที่ไม่สามารถแก้ไขได้ ดังนั้นการจัดการต่างๆ
จึงเป็นไปในลักษณะการ clone แล้วปรับแก้ไขจากค่าเดิม แล้วส่ง
ต่อไปใช้งานอีกที ได้อธิบายไปแล้วในตอนที่ผ่านๆ มา
การรับค่า Request Object
ตัวอย่างด้านล่าง เป็นการรับค่า request object เข้าไปใน middleware และ route ตามลำดับ
โดยจะเป็นค่า argument แรกของทั้งส่งฟังก์ชั่น
// App middleware รับค่า request object ผ่านตัวแปร $request $app->add(function (Request $request, RequestHandler $handler) { $myData = ['Hello','World']; $request = $request->withAttribute('data', $myData); // ส่งข้อมูลไปด้วย return $handler->handle($request); // ส่งต่อ request }); // Routing รับค่า request object ผ่านตัวแปร $request $app->get('/', function (Request $request, Response $response, $args) { $data = $request->getAttribute('data'); // รับค่าข้อมูล $response->getBody()->write(join(' ',$data)); return $response; });
สังเกตว่า middleware แรกไม่มีการใช้งาน reponse object ดึงนั้นเวลาทำงานในส่วนของ response
ก็จะข้าม middleware นี้ไป
ข้อมูล Request Method
เราสามารถดูค่าข้อมูลของ request method ที่ถูกส่งเข้ามาได้ด้วยคำสั่ง
$method = $request->getMethod();
ค่าที่ได้จะเป็นตัวพิมพ์ใหญ่ มีค่าต่างๆ ดังนี้
- GET
- POST
- PUT
- DELETE
- HEAD
- PATCH
- OPTIONS
เราสามารถใช้เป็นเงื่อนไขสำหรับกำหนดการทำงานใน middleware ได้ เช่น
$app->add(function (Request $request, RequestHandler $handler) { $method = $request->getMethod(); if($method == 'POST'){ // กรณีส่งแบบ POST $myData = ['Hello','World']; $request = $request->withAttribute('data', $myData); // ส่งข้อมูลไปด้วย }else{ // กรณีเป็นค่าอื่นๆ $myData = ['Welcome']; $request = $request->withAttribute('data', $myData); // ส่งข้อมูลไปด้วย } return $handler->handle($request); // ส่งต่อ request });
ข้อมูล Request URI
เราสามารถดูข้อมูล url ที่ request เข้ามาด้วยคำสั่ง ดังนี้ ดูตัวอย่างประกอบ
$app->add(function (Request $request, RequestHandler $handler) { $uri = $request->getUri(); echo $uri; // https://localhost/demo/api/home return $handler->handle($request); // ส่งต่อ request }); // Routing $app->get('/home', function (Request $request, Response $response, $args) { $response->getBody()->write('Welcome'); return $response; });
เมื่อเราเรียกไปยัง url เป็น https://localhost/demo/api/home จะได้ค่าจากคำสั่ง
$uri = $request->getUri(); // https://localhost/demo/api/home
ตาม url ที่เรียกใช้งาน นอกจากนั้น เรายังสามารถดูรายละเอียดแต่ละส่วนของ url ตามคำสั่งต่างๆ
ดังนี้ สมมติเราเรียกไปที่ https://localhost/demo/api/home?ref=mobile
$app->add(function (Request $request, RequestHandler $handler) { $uri = $request->getUri(); echo $uri."<br>"; // https://localhost/demo/api/home?ref=mobile echo $uri->getScheme()."<br>"; // https echo $uri->getAuthority()."<br>"; // localhost echo $uri->getUserInfo()."<br>"; // ถ้าไม่มีข้อมูลผูเ้ใช้ จะคืนเป็นค่าว่าง echo $uri->getHost()."<br>"; // localhost echo $uri->getPort()."<br>"; // ถ้าเป็น port มาตรฐาน เช่น 80 443 จะคืนเป็นค่าว่าง echo $uri->getPath()."<br>"; // /demo/api/home echo $uri->getQuery()."<br>"; // ref=mobile echo $uri->getFragment()."<br>"; // ค่าที่อยู่หลัง # ใน url ใน request url เราจะไม่สามารถดึงค่านี้ได้ $param = $request->getQueryParams(); // กรณีต้องการค่าแบบ array print_r($param); // Array ( [ref] => mobile ) return $handler->handle($request); // ส่งต่อ request });
ข้อมูล Request Headers
ในทุกๆ HTTP Request จะมี headers เป็นข้อมูลที่ไม่แสดงใน request body เราสามารถดูข้อมูล
ในส่วนของ header ได้ดังนี้
กรณีดึงข้อมูล headers ทั้งหมดมาแสดง ใช้คำสั่งดังนี้
$app->add(function (Request $request, RequestHandler $handler) { $headers = $request->getHeaders(); // ดึงรายการ header ทั้งหมด foreach ($headers as $name => $values) { echo $name . ": " . implode(", ", $values)."<br>"; } return $handler->handle($request); // ส่งต่อ request });
กรณีดึงเฉพาะชื่อ headers ที่ต้องการ ใช้คำสั่งดังนี้
$app->add(function (Request $request, RequestHandler $handler) { $headerValueArray = $request->getHeader('Accept-Language'); print_r($headerValueArray); // Array ( [0] => th-TH,th;q=0.9,en-US;q=0.8,en;q=0.7,my;q=0.6 ) $headerValueString = $request->getHeaderLine('Accept-Language'); echo $headerValueString; // th-TH,th;q=0.9,en-US;q=0.8,en;q=0.7,my;q=0.6 return $handler->handle($request); // ส่งต่อ request });
สังเกตว่าคำสั่ง getHeader() จะให้ข้อมูลเป็น array ในขณะที่คำสั่ง getHeaderLine() จะให้ข้อมูล
เป็น string
เราสามารถตรวจสอบว่า ชื่อ header ที่เราต้องการใช้งานมีอยู่ใน request หรือไม่ สามารถทำได้ดังนี้
$app->add(function (Request $request, RequestHandler $handler) { if ($request->hasHeader('Accept-Language')) { // เช็คว่ามี header นี้หรือไม่ $headerValueString = $request->getHeaderLine('Accept-Language'); echo $headerValueString; // th-TH,th;q=0.9,en-US;q=0.8,en;q=0.7,my;q=0.6 } return $handler->handle($request); // ส่งต่อ request });
ข้อมูล Request Body
ในทุกๆ HTTP Request จะมีข้อมูลส่วนของ request body แต่การเรียกดูข้อมูลแบบ GET ส่วนใหญ่จะไม่
ค่อยมีการส่งข้อมูลมาด้วย เพราะ GET มักใช้สำหรับดึงข้มมูลมาแสดงมากกว่า เราจะจำลองการใช้งานร่วม
กับ POST เป็นตัวอย่าง ดังนี้
// Routing $app->get('/home', function (Request $request, Response $response, $args) { $form = <<<HTML <form action="/demo/api/send" method="post"> <input type="text" name="data"> <button type="submit">Send</button> </form> HTML; $response->getBody()->write($form); return $response; }); $app->post('/send', function (Request $request, Response $response, $args) { $body = $request->getBody(); // ได้ข้อมูล stream มาไว้ในตัวแปร $body echo $body->getSize()."<br>"; // ขนาดข้อมูล byte ถ้าไม่รู้จักจะเป็น null // null echo $body->tell()."<br>"; // 0 ตำแหน่งข้อมูลปัจจุบัน // 0 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 ทั้งหมดมาแสดง // data=hello echo $body->eof()."<br>"; // 1 หรือ true เพราะแสดงข้อมูลทั้งหมดจบแล้ว // 1 $body->rewind(); // ไปเริ่มข้อมูลที่ตำแหน่ง เริ่มต้น echo $body->read(3)."<br>"; // อ่านข้อมูลมา 3 ตัวแรก // dat echo $body->tell()."<br>"; // 3 ตำแหน่งข้อมูลปัจจุบัน // 3 $body->seek(2);// เลื่อนข้อมูลไปอีก 2 ตำแหน่ง echo $body->tell()."<br>"; // 2 ตำแหน่งข้อมูลปัจจุบัน // 2 echo $body->read(3)."<br>"; // ดึงข้อมูล 3 ตัวเริ่มจากตำแหน่งที่ 2 // ta= echo $body->tell()."<br>"; // 5 ตำแหน่งปัจจุบัน // 5 print_r($body->getMetadata())."<br>"; // array ข้อมูลอื่นๆ // Array ( [timed_out] => [blocked] => 1 [eof] => [wrapper_type] => PHP // [stream_type] => Input [mode] => rb [unread_bytes] => 5 [seekable] => 1 // [uri] => php://input ) $response->getBody()->write('Process data'); return $response; });
เราจำลองสร้างฟอร์มสำหรับส่งข้อมูลเมื่อไปหน้า /home แล้วส่งข้อมูลแบบ POST ไปยังหน้า
/send ข้อมูลที่ได้จะสามารถเรียกใช้งานได้ทั้งใน middelware และ route ที่เข้าเงื่อนไขที่กำหนด
เมื่อพิมพ์คำว่า hello แล้วส่งค่าไป ข้อมูล body ของ stream จะเท่ากับ data=hello ตัวอย่างโค้ด
ด้านบนใช้คำสั่งต่างๆ จำลองการทำงานกับส่วน request body
การอัพโหลดไฟล์
กรณีมีการอัพโหลดไฟล์ จะใช้คำสั่ง getUploadedFiles() ในการจัดการดังนี้ เราจะจำลองฟอร์มสำหรับ
อัพโหลดไฟล์ และวิธีการทำงานร่วมกับไฟล์อัพโหลด ด้วยคำสั่งต่างๆ
// Routing $app->get('/home', function (Request $request, Response $response, $args) { $form = <<<HTML <form action="/demo/api/send" method="post" enctype="multipart/form-data"> <input type="file" name="fileToUpload" id="fileToUpload"> <button type="submit">Send</button> </form> HTML; $response->getBody()->write($form); return $response; }); $app->post('/send', function (Request $request, Response $response, $args) { $files = $request->getUploadedFiles(); // echo $files['fileToUpload']->getStream(); // แสดงข้อมูลของไฟล์ที่อัพโหลด // $files['fileToUpload']->moveTo('new.jpg'); // สำหรับอัพไหลดไปเก็บที่ path ที่กำหนด echo $files['fileToUpload']->getSize()."<br>"; // 569377 echo $files['fileToUpload']->getError()."<br>"; // 0 echo $files['fileToUpload']->getClientFilename()."<br>"; // IMG_5118.jpg echo $files['fileToUpload']->getClientMediaType()."<br>"; // image/jpeg $response->getBody()->write('Process data'); return $response; });
เครื่องมือจัดการข้อมูล Request เพิ่มเติม
ตรวจสอบว่าเป็นการส่งข้อมูลมาแบบ ajax หรือ XHR requests หรือไม่
if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') { // ทำคำสั่ง }
ตรวจสอบชนิดข้อมูลที่ส่งมา Content Type
$contentType = $request->getHeaderLine('Content-Type');
ตรวจสอบขนาดของข้อมูล Content Length
$length = $request->getHeaderLine('Content-Length');
ดูรายละเอียดข้อมูลเกี่ยวกับ Server Parameter ($_SERVER)
$params = $request->getServerParams(); $servername = $params['SERVER_NAME'] ?? null; $authorization = $params['HTTP_AUTHORIZATION'] ?? null;
ดูรายละเอียดข้อมูลที่ส่งแบบ POST มาจากฟอร์ม ทั้งแบบชนิดข้อมูลฟอร์มในรูปแบบ
application/x-www-form-urlencoded หรือ multipart/form-data
// array ข้อมูล POST ทั้งหมด $params = (array)$request->getParsedBody(); // เลือกเฉพาะที่ต้องการ POST $data = $params['data'];
ข้อมูล Route Object
กรณี้เราต้องการอ้างอิงการใช้งาน route ใน middleware สามารถทำได้ดังนี้
เรียกใช้งาน RouteContext class
use Slim\Routing\RouteContext;
จากนั้นกำหนดการทำงานใน route middleware ประมาณนี้
// Routing $app->get('/home', function (Request $request, Response $response, $args) { $response->getBody()->write('Welcome'); return $response; })->add(function (Request $request, RequestHandler $handler) { $routeContext = RouteContext::fromRequest($request); // คืนค่า routeContext $route = $routeContext->getRoute(); // คืนค่า route object // ตัวอย่าง เรียกใช้งาน route object $routeArg = $route->getArguments(); print_r($routeArg); return $handler->handle($request); // ส่งต่อ request });
เนื่องจากเป็นการอ้างอิง route ดังนั้นเวลาใช้งานจะต้องใช้แบบ route middleware เพราะจะต้องมี route
ก่อนถึงจะอ้างอิงการใช้งานได้
การดูค่า BasePath จาก route
$basePath = $routeContext->getBasePath(); echo $basePath; // /demo/api
การส่งต่อข้อมูลผ่าน request object
เกี่ยวกับการส่งข้อมูลได้อธิบายไปบ้างแล้วในบทความก่อนหน้า ดูตัวอย่างเล็กน้อยเพิ่มเติม เช่น กรณีต้องการ
ส่งข้อมูลค่า session ก็จะใช้เป็นประมาณนี้
// App middleware $app->add(function (Request $request, RequestHandler $handler) { $_SESSION['name'] = 'John Doe'; $request = $request->withAttribute('session', $_SESSION); return $handler->handle($request); // ส่งต่อ request }); // Routing $app->get('/home', function (Request $request, Response $response, $args) { $session = $request->getAttribute('session'); $response->getBody()->write('Welcome Yay, ' . $session['name']); return $response; });
เนื้อหาเกี่ยวกับการใช้งาน Request object ใน Slim framework 4 ก็มีแนวทางเบื้องต้นประมาณนี้
หลายๆ เนื้อหาก็อาจจะคุ้นเคยมาบ้างแล้ว หากใช้งานเกี่ยวกับ HTTP Request บ่อยๆ ถือเป็นการทบทวน
ไปในตัว เนื้อหาตอนหน้าจะเป็นอะไร รอติดตาม