การจัดการ Request ใน Slim framework 4

บทความใหม่ สัปดาห์ที่แล้ว โดย Ninenik Narkdee
slim framework request object php

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ slim framework request object php



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


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง











เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ