JsonView.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\View;
  15. use Cake\Controller\Controller;
  16. use Cake\Core\Configure;
  17. use Cake\Network\Response;
  18. /**
  19. * A view class that is used for JSON responses.
  20. *
  21. * By setting the '_serialize' key in your controller, you can specify a view variable
  22. * that should be serialized to JSON and used as the response for the request.
  23. * This allows you to omit views and layouts if you just need to emit a single view
  24. * variable as the JSON response.
  25. *
  26. * In your controller, you could do the following:
  27. *
  28. * `$this->set(array('posts' => $posts, '_serialize' => 'posts'));`
  29. *
  30. * When the view is rendered, the `$posts` view variable will be serialized
  31. * into JSON.
  32. *
  33. * You can also define `'_serialize'` as an array. This will create a top level object containing
  34. * all the named view variables:
  35. *
  36. * {{{
  37. * $this->set(compact('posts', 'users', 'stuff'));
  38. * $this->set('_serialize', array('posts', 'users'));
  39. * }}}
  40. *
  41. * The above would generate a JSON object that looks like:
  42. *
  43. * `{"posts": [...], "users": [...]}`
  44. *
  45. * If you don't use the `_serialize` key, you will need a view. You can use extended
  46. * views to provide layout-like functionality.
  47. *
  48. * You can also enable JSONP support by setting parameter `_jsonp` to true or a string to specify
  49. * custom query string paramater name which will contain the callback function name.
  50. *
  51. * @since CakePHP(tm) v 2.1.0
  52. */
  53. class JsonView extends View {
  54. /**
  55. * JSON views are always located in the 'json' sub directory for
  56. * controllers' views.
  57. *
  58. * @var string
  59. */
  60. public $subDir = 'json';
  61. /**
  62. * Constructor
  63. *
  64. * @param Controller $controller
  65. */
  66. public function __construct(Controller $controller = null) {
  67. parent::__construct($controller);
  68. if (isset($controller->response) && $controller->response instanceof Response) {
  69. $controller->response->type('json');
  70. }
  71. }
  72. /**
  73. * Skip loading helpers if this is a _serialize based view.
  74. *
  75. * @return void
  76. */
  77. public function loadHelpers() {
  78. if (isset($this->viewVars['_serialize'])) {
  79. return;
  80. }
  81. parent::loadHelpers();
  82. }
  83. /**
  84. * Render a JSON view.
  85. *
  86. * ### Special parameters
  87. * `_serialize` To convert a set of view variables into a JSON response.
  88. * Its value can be a string for single variable name or array for multiple names.
  89. * You can omit the`_serialize` parameter, and use a normal view + layout as well.
  90. * `_jsonp` Enables JSONP support and wraps response in callback function provided in query string.
  91. * - Setting it to true enables the default query string parameter "callback".
  92. * - Setting it to a string value, uses the provided query string parameter for finding the
  93. * JSONP callback name.
  94. *
  95. * @param string $view The view being rendered.
  96. * @param string $layout The layout being rendered.
  97. * @return string The rendered view.
  98. */
  99. public function render($view = null, $layout = null) {
  100. $return = null;
  101. if (isset($this->viewVars['_serialize'])) {
  102. $return = $this->_serialize($this->viewVars['_serialize']);
  103. } elseif ($view !== false && $this->_getViewFileName($view)) {
  104. $return = parent::render($view, false);
  105. }
  106. if (!empty($this->viewVars['_jsonp'])) {
  107. $jsonpParam = $this->viewVars['_jsonp'];
  108. if ($this->viewVars['_jsonp'] === true) {
  109. $jsonpParam = 'callback';
  110. }
  111. if (isset($this->request->query[$jsonpParam])) {
  112. $return = sprintf('%s(%s)', h($this->request->query[$jsonpParam]), $return);
  113. $this->response->type('js');
  114. }
  115. }
  116. return $return;
  117. }
  118. /**
  119. * Serialize view vars
  120. *
  121. * @param array $serialize The viewVars that need to be serialized
  122. * @return string The serialized data
  123. */
  124. protected function _serialize($serialize) {
  125. if (is_array($serialize)) {
  126. $data = array();
  127. foreach ($serialize as $alias => $key) {
  128. if (is_numeric($alias)) {
  129. $alias = $key;
  130. }
  131. if (array_key_exists($key, $this->viewVars)) {
  132. $data[$alias] = $this->viewVars[$key];
  133. }
  134. }
  135. $data = !empty($data) ? $data : null;
  136. } else {
  137. $data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
  138. }
  139. if (Configure::read('debug')) {
  140. return json_encode($data, JSON_PRETTY_PRINT);
  141. }
  142. return json_encode($data);
  143. }
  144. }