0

我刚开始使用 Phil Sturgeon 编写的 rest 库。我通过编写一些简单的示例开始使用它。我缺少“发布”和“获取”工作,但不适用于放置和删除。根据下面的代码,我有一些问题。

// a simple backbone model
var User = Backbone.Model.extend({
    urlRoot: '/user',
    defaults:{
        'name':'John',
        'age': 17
    }
});

var user1 = new User();
//user1.save(); // request method will be post unless the id attr is specified(put)
//user1.fetch(); // request method will be get unless the id attr is specified
//user1.destroy(); // request method will be Delete with id attr specified

在我的 CI REST 控制器中

class User extends REST_Controller
{
    public function index_get()
    {
        echo $this->get(null); //I can see the response data
    }

    public function index_post()
    {
        echo $this->post(null); //I can see the response data
    }

    public function index_put()
    {

    }

    public function index_delete()
    {

    }
}

基本上,当我保存模型或获取模型时,将调用控制器中的 get 和 post。使用模型中指定的 id,我可以使用 model.save() 和 model.destroy() 向服务器发出放置或删除请求。但是,我收到了服务器错误。看起来 index_put 或 index_delete 不能被调用。有谁知道我可以如何处理:

  1. 将请求放入控制器
  2. 在控制器中删除请求
  3. 获取指定 id 的单个记录

从 git 中,我只看到他列出了 index_post 和 index_put。没有 index_put 和 index_delete 演示。任何人都可以帮助我吗?谢谢

4

1 回答 1

2

我遇到了同样的问题,看起来浏览器/html/server 还没有完全支持 DELETE、PUT、PATCH 方法。你可能想看看这个堆栈溢出问题:PUT、DELETE、HEAD 等方法在大多数 Web 浏览器中都可用吗?

一个简单的解决方案是将methodMap主干线 1191 更改为以下内容:

 // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
 var methodMap = {
  'create': 'POST',
  'update': 'POST',     //'PUT',
  'patch':  'POST',     //'PATCH',
  'delete': 'POST',     //'DELETE',
  'read':   'GET'
 };

然后将动作类型作为模型的属性包含在内

 var Person = Backbone.Model.extend({
      defaults:{
         action_type : null,
         /*
          * rest of the attributes goes here
          */
      },
      url : 'index.php/person'
 });

现在,当您要保存模型时,请执行以下操作

 var person = new Person({ action_type: 'create' });
 person.set( attribute , value );  // do this for all attributes
 person.save();

在该application/controllers文件夹中,您应该有一个person.php名为 Person 的类扩展 REST_Controller 的控制器,它具有以下方法:

class Person extends REST_Controller {

   function index_get()  { /* this method will be invoked by read action */  }

   /*  the reason those methods are prefixed with underscore is to make them
    *  private, not invokable by code ignitor router. Also, because delete is
    *  might be a reserved word
    */

   function _create()  { /* insert new record */  }
   function _update()  { /* update existing record */  }
   function _delete()  { /* delete this record */  }
   function _patch ()  { /* patch this record */  }

   function index_post() {

      $action_type = $this->post('action_type');
      switch($action_type){

           case 'create' : $this->_create();  break;
           case 'update' : $this->_update();  break;
           case 'delete' : $this->_delete();  break;
           case 'patch'  : $this->_patch();   break;
           default:
               $this->response( array( 'Action '. $action_type .' not Found' , 404) );
               break;

      }
   }
}

话虽如此,这个解决方案是一个丑陋的解决方案。如果您在骨干实现中向上滚动,您将在第 1160 行找到以下代码:

// For older servers, emulate HTTP by mimicking the HTTP method with `_method`
// And an `X-HTTP-Method-Override` header.
if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
    params.type = 'POST';

这意味着您需要设置主干配置的模拟选项。将以下行添加到您的main.js

 Backbone.emulateHTTP = true;
 Backbone.emulateJSON = true;

为了测试效果,我创建了一个简单的模型,结果如下

你需要一个名为 Api 的控制器在applications/controllers文件夹中,在一个名为的文件中api.php

<?php defined('BASEPATH') OR exit('No direct script access allowed');

require_once APPPATH.'/libraries/REST_Controller.php';

class Api extends REST_Controller
{

   function index_get()
   {
    $this->response(array("GET is invoked"));
   }

   function index_put()
   {
    $this->response(array("PUT is invoked"));
   }

   function index_post()
   {
    $this->response(array("POST is invoked"));
   }

   function index_patch()
   {
    $this->response(array("PATCH is invoked"));
   }

   function index_delete()
   {
    $this->response(array("DELETE is invoked"));
   }

}

并在您的js/models文件夹中,创建一个名为api_model.js

var Api = Backbone.Model.extend({
       defaults:{ 
            id:      null, 
            name:    null
       },
       url: "index.php/api/"
});

var api = new Api();

api.fetch({ success: function(r,s) { console.log(s); } });  // GET is invoked

api.save({},{ success: function(r,s) { console.log(s); } }); // POST is invoked

//to make the record old ( api.isNew() = false now )
api.save({id:1},{ success: function(r,s) { console.log(s); } }); // PUT is invoked

api.destroy({ success: function(r,s) { console.log(s); } }); //DELETE is invoked

我不知道如何做补丁,但希望这会有所帮助。

编辑

我发现了如何做补丁,它不包含在代码点火器的 REST 实现中。在 REST_Controller 第 39 行中,您将找到以下内容,

protected $allowed_http_methods = array('get', 'delete', 'post', 'put');

您需要'patch'在最后添加以接受此方法,然后添加此代码

/**
 * The arguments for the PATCH request method
 *
 * @var array
 */ 
protected $_patch_args = array();

此外,您需要添加以下代码来解析补丁参数:

/**
 * Parse PATCH
 */
protected function _parse_patch()
{
    // It might be a HTTP body
    if ($this->request->format)
    {
        $this->request->body = file_get_contents('php://input');
    }

    // If no file type is provided, this is probably just arguments
    else
    {
        parse_str(file_get_contents('php://input'), $this->_patch_args);
    }
}

现在,根据主干文档,您需要通过{patch: true}发送一个 PATCH 方法,当您调用以下行时,您执行一个补丁:

 api.save({age:20},{patch: true, success: function(r,s) { console.log(s); } });

 // PATCH is invoked
于 2013-06-05T12:25:37.847 回答