ajax - Switch rendering according to headers, application-wide -
this question case in hand.
let's imagine website page displays filtered products list :
if request
/products?foo=bar
in browser, full page wrapped in layout, layout contains header form allowing change search criterias.if change
foo
valuebaz
, submit form, reloads dynamically results (with jquery$.load()
, example), calling/products?foo=baz
in ajax.if enter same criteria iphone app, app requests
/products?foo=bar
server, replies json object.
all 3 calls refer same resource ("the products list", resource intended in rest resource), need different rendering.
- in first case, need full html page (with layout)
- in second case, need partial html page (without layout)
- in third case, need plain json response
this rendering switch can triggered headers x-requested-with
(with or without layout) , accept
(html/json).
in phalcon, given example implemented :
class productscontroller extends \phalcon\mvc\controller { public function indexaction() { // build data $products = products::find(array( 'foo' => $this->request->get('foo') )); // json identified if ($this->request->getbestaccept() == 'application/json') { // json rendering (case 3) $this->response->setcontenttype('application/json'); $this->response->setjsoncontent($products); $this->view->disable(); return $this->response; } // otherwise, defaults html else { // passing data view $this->view->products = $products; // ajax call identified if ($this->request->isajax()) { // partial rendering (case 2) $view->disablelevel(array( view::level_layout => true, view::level_main_layout => true )); } // defaults normal rendering else { // layout rendering (case 1) } } } }
how implement mechanism application-wide, rather duplicate behavior in every single action ?
the easiest data in unified format (if isn't already) , pass method in base controller handle logic in pretty same way showed in example.
abstract class abstractcontroller extends \phalcon\mvc\controller { protected function prepareresponse($data) { // json identified if ($this->request->getbestaccept() == 'application/json') { // json rendering (case 3) $this->response->setcontenttype('application/json'); $this->response->setjsoncontent($data); $this->view->disable(); return $this->response; } // otherwise, defaults html // passing data view $this->view->setvars($data); // ajax call identified if ($this->request->isajax()) { // partial rendering (case 2) $view->disablelevel(array( view::level_layout => true, view::level_main_layout => true )); } // defaults normal rendering else { // layout rendering (case 1) } return null; } } class productscontroller extends abstractcontroller { public function indexaction() { // build data , prepare response return this->prepareresponse(array( 'products' => products::find(array( 'foo' => $this->request->get('foo') )) )); } }
otherwise, might bit tricky. see following alternative scenarios.
extend base controller with, say, renderjson
, renderpartial
methods, handle bits of logic (default otherwise), in action still need check 1 call. duplication…
do crazy shit router go different action, e.g., indexjsonaction
, indexpartialaction
(default otherwise), depending on conditions. you'd end bloated controllers.
Comments
Post a Comment