การจัดการอาร์กิวเมนต์ PUT / DELETE ใน PHP


84

ฉันกำลังทำงานกับไลบรารีไคลเอนต์ RESTของฉันสำหรับ CodeIgniterและฉันกำลังดิ้นรนหาวิธีส่งอาร์กิวเมนต์ PUT และ DELETE ใน PHP

ในไม่กี่แห่งฉันเคยเห็นผู้คนใช้ตัวเลือก:

$this->option(CURLOPT_PUT, TRUE);
$this->option(CURLOPT_POSTFIELDS, $params);

น่ารำคาญดูเหมือนว่าจะไม่ทำอะไรเลย นี่เป็นวิธีที่ถูกต้องในการตั้งค่าพารามิเตอร์ PUT หรือไม่

ถ้าเป็นเช่นนั้นฉันจะตั้งค่าพารามิเตอร์ DELETE ได้อย่างไร

$ this-> option () เป็นส่วนหนึ่งของไลบรารีของฉันมันเพียงแค่สร้างอาร์เรย์ของค่าคงที่ CURLOPT_XX และส่งไปยัง curl_setopt_array () เมื่อมีการเรียกใช้คำขอ cURL ที่สร้างขึ้น

ฉันพยายามอ่านพารามิเตอร์ PUT และ DELETE โดยใช้รหัสต่อไปนี้:

        case 'put':
            // Set up out PUT variables
            parse_str(file_get_contents('php://input'), $this->_put_args);
        break;

        case 'delete':
            // Set up out PUT variables
            parse_str(file_get_contents('php://input'), $this->_delete_args);
        break;

มีสองตัวเลือกที่นี่ฉันเข้าใกล้สิ่งนี้ผิดวิธีหรือมีข้อผิดพลาดในห้องสมุดของฉัน หากคุณสามารถแจ้งให้เราทราบได้ว่าสิ่งนี้ควรได้ผลหรือไม่ฉันก็สามารถใช้การดีบักจนกว่าฉันจะแก้ปัญหาได้

ฉันไม่อยากเสียเวลาไปกับแนวทางที่ผิดพื้นฐานอีกต่อไป


PUT ทำงานได้ดีเพียงแค่ลบพารามิเตอร์ที่ต้องกังวลเกี่ยวกับการตั้งค่าตอนนี้
Phil Sturgeon

1
คำถามนี้สับสน เกี่ยวกับการส่ง POST / DELETEพารามิเตอร์หรือการรับ POST / DELETEพารามิเตอร์?
jameshfisher

คำตอบ:


68

แทนการใช้CURLOPT_PUT = TRUEการใช้งานCURLOPT_CUSTOMREQUEST = 'PUT' และค่าแล้วเพียงแค่ตั้งค่าด้วยCURLOPT_CUSTOMREQUEST = 'DELETE'CURLOPT_POSTFIELDS


ฉันจะรับ POSTFIELDS ทางฝั่ง api / เซิร์ฟเวอร์ได้อย่างไร
Daniel

48

นี่คือโค้ดบางส่วนที่อาจเป็นประโยชน์สำหรับผู้อื่นที่ต้องการจัดการ PUT และ DELETE params คุณสามารถที่จะตั้งค่า$_PUTและ$_DELETEผ่าน$GLOBALS[]แต่พวกเขาจะไม่สามารถเข้าถึงได้โดยตรงในฟังก์ชั่นเว้นแต่ประกาศหรือเข้าถึงได้ผ่านทางglobal $GLOBALS[]เพื่อหลีกเลี่ยงสิ่งนี้ฉันได้สร้างคลาสง่ายๆสำหรับการอ่านอาร์กิวเมนต์คำขอ GET / POST / PUT / DELETE นอกจากนี้ยังเติม$_REQUESTด้วยพารามิเตอร์ PUT / DELETE

คลาสนี้จะแยกวิเคราะห์พารามิเตอร์ PUT / DELETE และรองรับ GET / POST ด้วย

class Params {
  private $params = Array();

  public function __construct() {
    $this->_parseParams();
  }

  /**
    * @brief Lookup request params
    * @param string $name Name of the argument to lookup
    * @param mixed $default Default value to return if argument is missing
    * @returns The value from the GET/POST/PUT/DELETE value, or $default if not set
    */
  public function get($name, $default = null) {
    if (isset($this->params[$name])) {
      return $this->params[$name];
    } else {
      return $default;
    }
  }

  private function _parseParams() {
    $method = $_SERVER['REQUEST_METHOD'];
    if ($method == "PUT" || $method == "DELETE") {
        parse_str(file_get_contents('php://input'), $this->params);
        $GLOBALS["_{$method}"] = $this->params;
        // Add these request vars into _REQUEST, mimicing default behavior, PUT/DELETE will override existing COOKIE/GET vars
        $_REQUEST = $this->params + $_REQUEST;
    } else if ($method == "GET") {
        $this->params = $_GET;
    } else if ($method == "POST") {
        $this->params = $_POST;
    }
  }
}

16

โปรดทราบว่าเว็บเซิร์ฟเวอร์ส่วนใหญ่ไม่จัดการคำขอ PUT & DELETE เนื่องจากคุณกำลังสร้างห้องสมุดฉันขอแนะนำให้คุณคิดเกี่ยวกับการบัญชีนี้ โดยทั่วไปมีสองรูปแบบที่คุณสามารถใช้เพื่อเลียนแบบ PUT & DELETE ผ่าน POST

  1. ใช้ตัวแปร POST ที่กำหนดเอง (เช่น _METHOD = PUT) ซึ่งแทนที่ POST
  2. ตั้งค่าส่วนหัว HTTP ที่กำหนดเอง (เช่น X-HTTP-Method-Override: PUT)

โดยทั่วไปแล้วบริการ RESTful ส่วนใหญ่ที่ไม่อนุญาตให้ PUT & DELETE โดยตรงจะรองรับกลยุทธ์เหล่านั้นอย่างน้อยหนึ่งอย่าง คุณสามารถใช้ cURL เพื่อตั้งค่าส่วนหัวที่กำหนดเองได้หากต้องการผ่านCURLOPT_HTTPHEADERตัวเลือก

// ex...
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-HTTP-Method-Override: PUT') );

3

ฉันคิดว่าคุณกำลังผสมกริยาของคุณ - PUT ใช้สำหรับวางไฟล์ POST ใช้สำหรับโพสต์ตัวแปร (แม้ว่าคุณจะสามารถโพสต์ไฟล์ได้)

ในการตั้งค่าตัวแปรโพสต์ให้ใช้CURLOPT_POSTFIELDSกับสตริงparam1=val1&param2=val2หรืออาร์เรย์เชื่อมโยง

ในการลบคุณจะต้องใช้ตัวเลือก curl CURLOPT_CUSTOMREQUEST


1
ทั้ง PUT และ DELETE รองรับการส่งอาร์กิวเมนต์เพิ่มเติม คุณสามารถทำได้ผ่านทางบรรทัดคำสั่งเมื่อทำงานกับ curl แต่ฉันไม่สามารถหาวิธีส่งด้วย PHP-cURL ได้ ตัวอย่างเช่นเนื่องจากเป็น REST ฉันต้องการวิธีทำเครื่องหมายสิ่งที่ฉันกำลังลบ หากฉันกำลังลบรหัสผู้ใช้ฉันต้องการที่จะสามารถส่งผ่าน id โดยไม่ต้องเกะกะ URL API เหมือนกับ Twitter รองรับ GET / POST เท่านั้นดังนั้นคุณสามารถใส่สิ่งนั้นใน URL ได้ แต่ REST API อื่น ๆ อาจไม่รองรับสิ่งนี้ดังนั้นฉันจึงต้องส่งพารามิเตอร์การลบไป
Phil Sturgeon

1
ตกลงฉันมีพารามิเตอร์ PUT ทำงานฉันเปลี่ยน CURLOPT_PUT = TRUE สำหรับ CURLOPT_CUSTOMREQUEST = 'PUT' และทำงานได้ดี ตอนนี้ฉันจะตั้งค่า DELETE ได้อย่างไร?
Phil Sturgeon

CURLOPT_CUSTOMREQUEST = 'DELETE' จากนั้นใช้สตริงการสืบค้นสำหรับพารามิเตอร์อาจ
Adam Hopkinson

1
ปิดฉันพยายามหลีกเลี่ยงการใช้มันในสตริงการค้นหาตามที่ฉันได้กล่าวไปแล้ว ปรากฎว่าคุณสามารถใช้ CURLOPT_POSTFIELDS กับ PUT และ DELETE เมื่อใช้ CURLOPT_CUSTOMREQUEST = 'DELETE ขอบคุณสำหรับคำติชมของคุณ แต่ฉันแก้ไขมันเองในที่สุด :-)
Phil Sturgeon

2
รึเปล่า? ฉันไม่ได้ช่วยเลยเหรอ?
Adam Hopkinson

2

นี่คือเวอร์ชัน DELETE สำหรับ CI ของฉัน ยอมรับอาร์กิวเมนต์ GET สำหรับ DELETE แม้กระทั่งอาร์กิวเมนต์ชื่อเดียวกันเช่น GET / some / url? id = 1 & id = 2 & id = 3

protected function _parse_delete()
{
    $query = $_SERVER['QUERY_STRING'];
    if ( !empty( $query ) )
    {
        foreach( explode('&', $query ) as $param )
        {
            list($k, $v) = explode('=', $param);
            $k = urldecode($k);
            $v = urldecode($v);
            if ( isset( $this->_delete_args[$k] ) )
            {
                if ( is_scalar( $this->_delete_args[$k] ) )
                {
                    $this->_delete_args[$k] = array( $this->_delete_args[$k] );
                }
                $this->_delete_args[$k][] = $v ;
            }
            else
            {
                $this->_delete_args[$k] = $v;
            }
        }
    }
}

1

นี่คือวิธีเดียวที่ฉันมีปัญหา DELETE:

== >> ในREST_Controller.phpฉันแทนที่ฟังก์ชัน_parse_delete () delaultโดย:

protected function _parse_delete()
{
    $this->_delete_args = $_DELETE;
    $this->request->format and $this->request->body = file_get_contents('php://input');
    // Set up out DELETE variables (which shouldn't really exist, but sssh!)
    parse_str(file_get_contents('php://input'), $this->_delete_args);
}

;) มันได้ผลสำหรับฉัน!


1
$ _DELETE;? ฉันเพิ่งได้รับ error undefined variable: _DELETE
Valor_
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.