Codeigniter与骨干的休息问题

时间:2013-05-09 22:16:43

标签: codeigniter backbone.js httprequest httpresponse codeigniter-restserver

我刚开始使用Phil Sturgeon写的休息库。我开始使用它写一些简单的例子。我没有'post'和'get'工作,但不是put和delete。我根据下面的代码提出了一些问题。

// 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()向服务器发出put或delete请求。但是,我收到服务器错误。它看起来像无法调用index_put或index_delete。有谁知道我怎么处理:

  1. 将请求放入控制器
  2. 删除控制器中的请求
  3. 获取ID为
  4. 的单个记录

    从git中,我只看到他列出了index_post和index_put。没有index_put和index_delete演示。谁应该帮助我?感谢

1 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,看起来浏览器/ html /服务器还没有完全支持DELETE,PUT,PATCH方法。您可能希望查看此堆栈溢出问题:Are the PUT, DELETE, HEAD, etc methods available in most web browsers?

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

 // 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 extends 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;

为了测试它的效果,我创建了一个简单的模型,这里是结果

您需要applications/controllers文件夹中名为api.php

的文件中名为Api的控制器
<?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