backbone.js - Codeigniter rest issue with backbone -
i started using rest library wrote phil sturgeon. started using writing simple examples. short of 'post' , 'get' work, not put , delete. have questions based on code below.
// simple backbone model var user = backbone.model.extend({ urlroot: '/user', defaults:{ 'name':'john', 'age': 17 } }); var user1 = new user(); //user1.save(); // request method post unless id attr specified(put) //user1.fetch(); // request method unless id attr specified //user1.destroy(); // request method delete id attr specified
in ci rest controller
class user extends rest_controller { public function index_get() { echo $this->get(null); //i can see response data } public function index_post() { echo $this->post(null); //i can see response data } public function index_put() { } public function index_delete() { } }
basically, , post in controller called when save model or fetch model. id specified in model, can make put or delete request server using model.save() , model.destroy(). however, got server error. looks index_put or index_delete can not called. know how can handle:
- put request in controller
- delete request in controller
- get single record id specified
from git, saw him list index_post , index_put. there no index_put , index_delete demo. should can me out? thanks
i faced same exact problem, looks delete, put, patch methods not supported browsers/html/server yet. may want @ stack overflow question: are put, delete, head, etc methods available in web browsers?
a simple solution change methodmap
of backbone line 1191 following:
// map crud http our default `backbone.sync` implementation. var methodmap = { 'create': 'post', 'update': 'post', //'put', 'patch': 'post', //'patch', 'delete': 'post', //'delete', 'read': 'get' };
and include action type attribute of model
var person = backbone.model.extend({ defaults:{ action_type : null, /* * rest of attributes goes here */ }, url : 'index.php/person' });
now when want save model, following
var person = new person({ action_type: 'create' }); person.set( attribute , value ); // attributes person.save();
in application/controllers
folder should have controller called person.php
class named person extending rest_controller, has following methods:
class person extends rest_controller { function index_get() { /* method invoked read action */ } /* reason methods prefixed underscore make them * private, not invokable code ignitor router. also, because delete * might reserved word */ function _create() { /* insert new record */ } function _update() { /* update existing record */ } function _delete() { /* delete record */ } function _patch () { /* patch 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; } } }
having said that, solution ugly one. if scroll in backbone implementation, find following code @ line 1160:
// older servers, emulate http mimicking http method `_method` // , `x-http-method-override` header. if (options.emulatehttp && (type === 'put' || type === 'delete' || type === 'patch')) { params.type = 'post';
which means need set emulate options of backbone configurations. add following lines main.js
backbone.emulatehttp = true; backbone.emulatejson = true;
to test effect of that, created simple model , here results
you need controller called api in applications/controllers
folder, in file named 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 invoked")); } function index_put() { $this->response(array("put invoked")); } function index_post() { $this->response(array("post invoked")); } function index_patch() { $this->response(array("patch invoked")); } function index_delete() { $this->response(array("delete invoked")); } }
and in js/models
folder, create model called 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); } }); // invoked api.save({},{ success: function(r,s) { console.log(s); } }); // post invoked //to make record old ( api.isnew() = false ) api.save({id:1},{ success: function(r,s) { console.log(s); } }); // put invoked api.destroy({ success: function(r,s) { console.log(s); } }); //delete invoked
i don't know how patch, hope helps.
edit
i found out how patch, not included in rest implementation of code ignitor. in rest_controller line 39, find following,
protected $allowed_http_methods = array('get', 'delete', 'post', 'put');
you need add 'patch'
@ end, accept method, also, after doing add code
/** * arguments patch request method * * @var array */ protected $_patch_args = array();
also, need add following code parse patch arguments:
/** * parse patch */ protected function _parse_patch() { // might http body if ($this->request->format) { $this->request->body = file_get_contents('php://input'); } // if no file type provided, arguments else { parse_str(file_get_contents('php://input'), $this->_patch_args); } }
now, according backbone docs, need pass {patch: true}
send patch method, when call following line, execute patch:
api.save({age:20},{patch: true, success: function(r,s) { console.log(s); } }); // patch invoked
Comments
Post a Comment