我遇到了同样的问题,看起来浏览器/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