May 8th 2008 – Controller::$beforeFilter has been deprecated a while ago, i’ve updated the example using Controller::beforeFilter()
Almost an half year ago I created jsonComponent for CakePHP, since then it has been used by quite a few people including myself.
About 3 months ago I started developing with CakePHP 1.2, one of the projects I’m working on is Pagebakery. Pagebakery relies heavily on AJAX and JSON and it’s therefore a perfect opportunity to experiment with CakePHP’s new features.
One of those features is Router::parseExtensions(). ParseExtensions allows you to parse the extension in your request and let Cake select alternate layouts and views automatically.
Another feature I found is JavascriptHelper::object(), this method is also available in CakePHP 1.1 but I only stumbled on it recently. It’s build-in JSON support in CakePHP, we no longer need the jsonComponent!
I’m going to explain you how to setup CakePHP 1.2 to output JSON with help of Router::parseExtensions() and the JavascriptHelper::object() method.
In this example we’re going to use a simple posts controller like the one in the Cake blog tutorial.
First we need to let Cake know to parse .json extentions. Add the following to /config/routes.php
Router::parseExtensions('json');
Because JSON is not a default content type in CakePHP currently, we need to add it. We also need enable the RequestHandler component. Add the following to your app_controller.php
var $components = array('RequestHandler');
function beforeFilter() {
$this->RequestHandler->setContent('json', 'text/x-json');
}
Note: if you use beforeFilter in your controllers you need to call parent::beforeFilter()
Now we need to create our JSON layout.
Create: /layouts/json/default.ctp
Paste the following code in the new layout
< ?php
header("Pragma: no-cache");
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
header('Content-Type: text/x-json');
header("X-JSON: ".$content_for_layout);
echo $content_for_layout;
?>
Note: the X-JSON header is used by prototype.js and is automatically evaluated into a JSON object.
Next is our view, we’ll use the index action of the posts controller.
Create: /views/posts/json/index.ctp
And insert the following code in the view
< ?php echo $javascript->object($aPosts); ?>
Note: the object method will convert the posts array into a json string, just like the jsonComponent.
Just to be clear here is the index action from the posts controller
function index() {
$this->set('aPosts', $this->Post->findAll());
}
Now access your posts controller in your browser, /posts/index/ will output the regular html view and /posts/index.json will output your json object!
Note that you can also use xml, rss (supported by default in CakePHP 1.2) to create your own feed in a snap!
Let me know if you have comments or additions.
excellent post eelco! You go girl :)
Hi, great post, found it really useful. Did run into a typo that caused me problems.
var $component = array(‘RequestHandler’);
should be
var $components = array(‘RequestHandler’);
Thanks for noticing Dai, glad to hear it’s useful!
Any chance of you doing something similar in explaining how to parse a JSON string coming in as an input?
My client UI does an asynchronous post to the server to post data in JSON. How do I go about getting that into my $data array sanitized properly to use inside my controller and model safely?
As far as I know the javascript helper only allows you to encode to JSON.
There are 2 options for you
Use my JsonCompontent to decode json.
Or if you have PHP 5.2 you can use json_decode
Good luck
Thanks ofr the tips Eelco
Just wondering, how do you pass a parameter to the URL when parseExtension is being used:
e.g.
normally you would be able to do this
http://localhost/products/list/1
but if you want to return the data in json format, where do you place the category_id within the URL?
http://localhost/products/list/1/data.json doesn’t work for some reasons.
Thanks for your help in advance.
Hi Melvin,
You got a good point there, I haven’t tested with that yet so I don’t have an answer for that yet.
My guess it would be:
localhost/products/list/1.json
I’m currently on vacation but will have a look at it when I’m back home.
Please leave a comment if you find the solution.
[...] Javascript Helper’s JSON object by Eelco Wiersma [...]
Just for confirmation.
the file extension should come after the last parameter.
localhost/controller/action/param1/param2.js is correct.
Shouldn’t Content-Type be ‘application/json’ instead of ‘text/x-json’ ?
how could i forget to thank you first for this excellent post … you really saved me a lot of headache and controller rewrites. have a great weekend!
This is amazing!
Thanks dude…
It’s now much much much easier to get what you looking for.
Thanks again. :)
thnaks a lot, i hope this code help me to change the content type of my rss when it’s cached !
cakephp is a cool framework, but it lucks documentation :S soo much
Very useful info for me. Thanx.
Nice and useful code n_n, this help me a lot, thanks.
This is amazing!
Thanks dude…
It’s now much much much easier to get what you looking for.
Thanks again. :
Hi, I can’t get it working following your steps. It seems to choke on this line in the json/default.ctp file:
header(“X-JSON: “.$content_for_layout);
If I removed this line, then it seems to work. Any idea why?
I’m using a lot of CakePHP’s built in stuff to generate my HTML, and I’m using jQuery to do some simple ajax stuff and some DOM manipulation. My problem is, how to do my client/server interaction with JSON. I have the facility in place for inline comments. When you see a paste, you can double click on each line to create and view the comments. When you create one, there is code that generates the comment and enters the line number and paste ID.
@peter
You probably have multiple lines in your view, check if there are any enters/spaces before or after < ?php and ?>
@kulak
You can send json to Cake with an ajax request, and decode it with my JsonComponent or json_encode(needs php5).
I’m not exactly sure what you’re trying to do but maybe this helps :)
Hi, thanks its a good and an easy how to, I followed all your steps but I’am getting this error:
Dispatcher::start – Controller::$beforeFilter property usage is deprecated and will no longer be supported. Use Controller::beforeFilter(). [CORE/cake/dispatcher.php, line 298]
can somebody help me please? thanks
hi everybody, thanks for this its very helpful, i am using it but i get an error with the $beforeFilter, can somebody help me please, thanks. the error is the following:
Dispatcher::start – Controller::$beforeFilter property usage is deprecated and will no longer be supported. Use Controller::beforeFilter(). CORE/cake/dispatcher.php, line 298
i am working with cakephp, and i have the next question, i need to send json data to cakephp to add a new record in the database, the question is: how can i past the data to the function in my controller, and how its supose i should handle, in $this->data or in $_POST, Thanks
@Alfredo
the piece of code in my example is outdated. You should use Controller::beforeFilter instead.
@Steve
you could use $this->params['form']
Hope this helps
I am also facing the same error as stated by Alfredo. Probably the new version of cakephp supports json now.
Please update us how to handle the Json part now and how to secure the json result so that it can only be asked by application and not viewed by just firing the url with extension json.
Thanks
Another thing that I want to accomplish is that I want to restrict few columns in the table from json view. So how can we customize the object before sending it for json encoding so that the table shows only particular columns.
Hi, thanks Eelco i actually get the json from my controller, i followed all your steps, and it was working fine but now i have a problem, i don’t know what i did but i now i can’t get the json, i am using jquery and the request is with the status 0 with the loading in the response, the problem is that, i have 22 records in the database, the funny here is that if i add one record,(23 records) the json stay in loading, but if i delete one record i get all the json, i have checked all, and it appears to be fine, i don’t know what’s the problem. i apreciate your help. thank you very much.
Hi, i couldn’t resolve my last problem, maybe because the query brings so much data, well i decide to reduce the query, but now i have other question i hope you can help me, i want to send and array of ids, to my controller, i am using jquery, the problem is i am getting [object Object] i caught it with $_POST because my array is not a form, how can i send and/or receive the data?
i want to send this {1,2,3} something like this.
Thanks
You’ll need to encode your json object to a string, to send it with your post.
i’m not sure jquery has something for that
[...] Aqui tenemos un buen ejemplo de uso del json component. [...]
thanks!! this is an example of what we need more of!!!
2 small notes for other newbs – if you experience any problems make sure you do not define $layout or have the pagination helper tuned on for the controller/action you are working with.
works well, except i’m trying to pass a link in the json code, the html is escaped.
eg.
// json/index.ctp
$html->link($rowValue, "/pilots/view/".$rowValue
results in:
"2"
how do i prevent this from happening?
in the post above, results in:”2″ should be:
“id”:”{a href=\”\/acass\/pilots\/view\/2\”}2{\/a}”
replacing { and } with
[...] ago, I found the handy post about using JSON with CakePHP 1.2 on Eelco Wiersma’s blog Pagebakers. Basically, it summarizes the best way to implement JSON on the page in order to separate your JSON [...]
A small tip, for anyone who is using this while in a dev/staging environment where Cake automatically spits out debug information (Configure::write(‘debug’, X) where X is > 0) —
Just toss the following “Configure::write(‘debug’, 0);” into your ‘views/layout/json/default.ctp’ at the top before the header() calls … and your JSON requests will not be affected by the rest of your calls (if using prototype which looks at X-JSON in the headers … this may not be a problem, but with jQuery it would be).
[...] for some nice Cake 1.2 JSON information, I ran across an interesting post on Pagebakers called Using JSON in CakePHP 1.2. I gave it a quick read (actually, I skimmed it for code snippets and just rolled my own from the [...]
Is there anyone know why my ajax-json request take so long time(around 6 second to get the response)?
url like this:http://localhost/products/list/1/data.json
Is there a way that I can trace this issue?
hi Pagebaker,
I have used your approach now for quite some time. However, I am getting end up with many view files that only have one line code, mainly $javascript->object($result);
Is there a way to set default view that all controller can use, so I won’t need to use the default file but simply use the default json view.
Yeah, this method is already outdated, but I haven’t had time to write a new article.
I’ll be short on this.
You’ll need to create a JsonView and in your AppController::beforeRender function you need to check of the current request is a json request, if it is then you use the JsonView
There are some articles on this on the net, you could also check the source of Pagebakery on GitHub, the code for it is in there.
Good luck
I would be happy to here what changed in 1.2 stable regarding this topic.
@rrd I’m planning to write a new post about this topic, stick around ;)
I want complete small application on cake PHP .
Please provide me as sson as possible.
how do you disable the timer/debug comment at the end for json calls? its breaking the requests.
you should put this:
Configure::write(‘debug’, 0);
above
echo $content_for_layout;
in default.ctp
This was a huge help – thanks!!!!!
i has translate it into chinese ,thank you!
I can’t make it work for admin routes, can anyone help me?
Thank you for this article. Hard to find a good one for this.
But you should do something about your code formatting. It’ not easy to read.
Thanks Benedikt, somehow my code formatting plugin stopped working.. stilll need to find another one :)
I had problems with this in FireFox 3. Some pages would pull some wouldn’t. I changed my headers to:
and firefox and everything started working again.
Comment stripped out code…
See: 50 for description.
header(“Pragma: no-cache”);
header(“Cache-Control: no-store, no-cache, max-age=0, must-revalidate”);
header(‘Content-type: application/json’);
echo $content_for_layout;
If I use the same tutorial, I am asked by browser to open or download the index.json file and in that file the json string is written.
[...] Using JSON in CakePHP 1.2 – Share and Enjoy: [...]