How Easy Are Web Services in CakePHP 1.2? Really Easy!

In a previous post I talked about how to use the built-in web services in CakePHP 1.1.x.x. A very popular piece too according to my site statistics too. Well, I've discovered that it's even easier in Cake 1.2.x.x. I bugged Nate via IM for some tips on how to put it together, and it's really very simple.

The biggest change is that the old way of doing custom routing in web services is gone in favour of handling them via extensions. In the past, you would go into app/config/core.php and enable the special web services routing. I was trying to do a web service with the URL http://localhost/cake_dev/foo and have it spit out an XML response. According to what I was told "...going forward the routes part / extensions on the end of the URL is the recommended way of doing it". So, if I was doing this the standard way I would be calling http://localhost/cake_dev/foo/index.xml. I just like the cleaner URL. Now, if I was to do it the proper way, I would add in the following to my app/config/routes.php file:

PHP:
  1. /**
  2. * Add in support for web services by enabling generating output based on extension
  3. */
  4. Router::parseExtensions();

Now, go and create your controller that will handle spitting out some XML:

PHP:
  1. /**
  2. * Test controller for built-in web services in Cake 1.2.x.x
  3. *
  4. * @author Chris Hartjes
  5. *
  6. */
  7.  
  8. class FooController extends AppController
  9. {
  10.     var $components = array('RequestHandler');
  11.     var $uses = '';
  12.     var $helpers = array('Text', 'Xml');
  13.    
  14.     function index()
  15.     {
  16.         $message = 'Testing';
  17.         $this->set('message', $message);
  18.         $this->RequestHandler->respondAs('xml');
  19.         $this->viewPath .= '/xml';
  20.         $this->layoutPath = 'xml';
  21.     }
  22. }

So what am I doing here? I make sure to use the RequestHandler component so it understands that I want to spit out some XML, and I made sure to include the Xml helper. Next, I tell the request handler that I want the output to be XML instead of HTML by using respondAs('xml'). Finally, I do some more controller voodoo (Nate contributed this part) by setting $this->viewPath and $this->layoutPath so that I don't have to specify index.xml to get it to spit out results. A call to http://localhost/cake_dev/foo will spit out an XML result based on my template, which I put into app/views/foo/xml/index.ctp:

PHP:
  1. <foo>
  2.     <bar><?php print $message; ?></bar>
  3. </foo>

That spits out the following XML document:

PHP:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <foo>
  3.     <bar>Testing</bar>
  4. </foo>

I'm hoping to use this setup for some web services I have to write for work but my boss likes some other framework, which isn't surprising since he used to work for them. I will continue to fight for my right to eat Cake. Besides, it's all part of my evil plan to get paid to contribute code to the CakePHP project. I mean, if I need to create an interactive console to do testing then I can build it with Cake and give it back to the community while getting paid at the same time. What could be better?

20 Responses to this post.

  1. Andrew's Gravatar

    Posted by Andrew on 13.03.07 at 10:16 pm

    Is there a simple way to use SOAP with CakePHP?

  2. sdevore's Gravatar

    Posted by sdevore on 13.03.07 at 10:16 pm

    Chris I'll have to write up how to do rest style stuff in 1.2 since I'm about to take the app I did in 1.1 and move it to 1.2

  3. Felix Geisendörfer's Gravatar

    Posted by Felix Geisendörfer on 13.03.07 at 10:16 pm

    Hey Chris,

    I'm not building a web service for my app right now (not yet), but I need the ability to update most of my Models via Ajax as well as regular http posts. So I'm not sure what version you use, but when playing around with the latest 1.2 I didn't have to do any manual xml / json / whatever settings in my controller actions. The RequestHandler automatically realized that I was requesting /tasks/index.xml and used the xml layout/view path and responded as xml and there was nothing left to do for me. So go ahead and give that a try and see if it works for you as well ; ).

    -- Felix

  4. poLK's Gravatar

    Posted by poLK on 13.03.07 at 10:16 pm

    Hi Chris,

    there is more beauty in CakePHP 1.2... ;)

    In case You're calling
    Router::parseExtensions();
    without passed arguments and You have RequestHandler in $components, You really do not need 'Xml' in $helpers (RequestHandler will include it automatically for You for url which ends with .xml).

    Also lines with

    $this->RequestHandler->respondAs('xml');
    $this->viewPath .= '/xml';
    $this->layoutPath = 'xml';

    are not necessary - see implementation of RequestHandler::startup() - those commands are executed there also.

    Regards, poLK

  5. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 13.03.07 at 10:16 pm

    @Felix:

    You're right that if I comment out setting viewPath and layoutPath and then call my action as http://localhost/cake_dev/foo/index.xml I get the same results. The reason I add that other stuff in is so I don't have to specify index.xml, just http://localhost/cake_dev/foo.

  6. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 13.03.07 at 10:16 pm

    @poLK

    Yes, I realize that if I use Router::parseExtensions(); that I don't need the other stuff. I use that so that I don't have to add index.xml to the end of my URL. This technique is essential to creating any sort of REST service, where you are doing HTTP calls like http://localhost/noun/verb

  7. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 13.03.07 at 10:16 pm

    @Andrew,

    Check out this link for an example on using SOAP with CakePHP.

    A simple SOAP example

    Hope that helps.

  8. othman ouahbi aka CraZyLeGs's Gravatar

    Posted by othman ouahbi aka CraZyLeGs on 13.03.07 at 10:16 pm

    if you want http://localhost/cake_dev/foo/index.xml in place of
    http://localhost/cake_dev/foo then you can use a route.

  9. PHPDeveloper.org's Gravatar

    Posted by PHPDeveloper.org on 13.03.07 at 10:16 pm

    Chris Hartjes' Blog: How Easy Are Web Services in CakePHP 1.2? Really Easy!...

    ...

  10. developercast.com » Blog Archive » Chris Hartjes’ Blog: How Easy Are Web Services in CakePHP 1.2? Really Easy!'s Gravatar

    [...] a new post to his blog today, Chris Hartjes points out how easy it is to use web services in the latest [...]

  11. poLK's Gravatar

    Posted by poLK on 13.03.07 at 10:16 pm

    You don't have to modivy $this->viewPath and $this->layoutPath in controller - RequestHandler does it automatically (if Router::parseExtensions() was called).

  12. poLK's Gravatar

    Posted by poLK on 13.03.07 at 10:16 pm

    Oh, sorry Chris - I just posted something we already discussed before - I talk about it with someone at IRC and I was so busy for reading older comments... :)

  13. CakePHP 1.2: The Romance Continues … « Ahsan’s Laboratory's Gravatar

    [...] RSS Feeds for your app cant get easier. Super-easy RSS feeds with CakePHP 1.2 by Jiri Kupiainen and How Easy Are Web Services in CakePHP 1.2? Really Easy! by Chris Hartjes explains it all. Don’t forget to go through the [...]

  14. T0aD's Gravatar

    Posted by T0aD on 13.03.07 at 10:16 pm

    I was looking for a generic way to handle different extensions using Router::parseExtensions() and unfortunately extensions like rest (which used to be a web service routed just fine in cake 1.1) are not supported (you can have a look at RequestHandler::__requestContent to see which extensions are correctly supported under cakephp 1.2).

    I didn't like your way to do it as well, since it means to do it manually in each method you want to export as a webservice, so I implemented it using the beforeFilter() hook:

    class WebsitesController extends AppController {
    var $name = 'Websites';
    var $uses = array('Website');

    function beforeFilter() {
    if (isset($this->params['url']['ext']) &&
    strlen($this->params['url']['ext'])) {
    $this->viewPath .= DS . $this->params['url']['ext'];
    $this->layoutPath = $this->params['url']['ext'];
    /* We don't want to have time in the end of our REST response for instance */
    Configure::write('debug', 0);
    }
    parent::beforeFilter();
    }

    function count() {
    $this->set('numberWebsites', $this->Website->findCount());
    }

    Simply call http://www.example.com/websites/count.rest

    This wasn't fully tested so any feedback are welcome.

  15. Tim Daldini's Gravatar

    Posted by Tim Daldini on 13.03.07 at 10:16 pm

    If you only need the foo method to spit out xml, is there any point in calling parseExtensions() in the first place? Just wondering.

  16. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 13.03.07 at 10:16 pm

    @Tim
    Well, the main reason is so that I don't actually have to generate the XML myself, instead getting Cake to do it for me. Keep in mind that some of this stuff may have changed since this tutorial was written, maybe I need to go back and see what still holds true...

  17. rdeman's Gravatar

    Posted by rdeman on 13.03.07 at 10:16 pm

    so how does this work when I want to post arguments?
    http://localhost/cake_dev/foo/index.xml/argumentg1/argument2/ ??

  18. DieHard's Gravatar

    Posted by DieHard on 13.03.07 at 10:16 pm

    Chris, can you show us how you do web services with JSON? And, also how to do session with web services? Please! :)

    Thanks for the help!

  19. Phil Taylor's Gravatar

    Posted by Phil Taylor on 13.03.07 at 10:16 pm

    So have you developed any real wed services with CakePHP?

    Also, Nate gave a presentation at the CakeFest on REST webservices and CakePHP. Is this available for public consumption?

  20. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 13.03.07 at 10:16 pm

    @Phil

    If by "real web service" you mean "script that spits out something other than HTML upon request" then the answer is yes. I have web services that feed data to a companion site for my simulation baseball league. Nothing fancy like XML or JSON, just text formatted in a specific way.

    None of the presentations from CakeFest have made their way out on the web as far as I know.

Respond to this post

Want to advertise on this blog? Send email to chartjes@littlehart.net
GTcars Canadian Car Audio TurboDodge Car For Sale Sign
Audi Forum Mustang Forum Dodge Intrepid Miata Turbo
GTscene Pontiac Bonneville