Implementing SOAP on cakePHP

2 : Example

By Shawn Cook (scook)
I have recently (last week) started using cakePHP. I choose cake because it works with AMFPHP and because I thought cake had built in support for web services (including soap). I'm not complaining, but I was somewhat disappointed to find out that support for web services is limited to routing, which I could not get to work anyway...
This example uses the following notes table, and MVCs created with the bake script.
-- 
-- Table structure for table `notes`
-- 
CREATE TABLE `notes` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(50) default NULL,
  `body` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`)
) TYPE=MyISAM  AUTO_INCREMENT=2 ;
-- 
-- Dumping data for table `notes`
-- 
INSERT INTO `notes` VALUES (1, 'My first note', 'note body. bla, bla, bla, bla, bla.', '2006-10-29 07:23:42', '2006-10-29 07:23:42');


So, we have a controller named NotesController with the following functions: index, add, edit, delete. First thing I have to do is document my methods. Note: Currently all methods in a controller must be documented if you want to use the soap server on that class. This shouldn't be a big deal since we should be documenting all of our code anyway! The documentation uses a standard flower-box method. You must document each parameter and a return type. If the function doesn't return anything, declare the return type as void.
So my view function would go from this:
<?php
    
function view($id) {
        
$this->set('note'$this->Note->read(null$id));
    }
?>

to this:
<?php
    
/**
    * Get one record
    * @param int
    * @return void
    */
    
function view($id) {
        
$this->set('note'$this->Note->read(null$id));
    }
?>


This function will now work in the Soap5 server. However it doesn't return anything, so you won't get any results if you call it. So make two more changes: First return the note array that you previously had passed to the view, and then declare the return type to be a string array string[]
<?php
    
/**
    * Get one record
    * @param int
    * @return string[]
    */
    
function view($id) {
        
$note $this->Note->read(null$id);
        
$this->set('note'$note);
        return 
$note['Note'];
    }
?>


So we have a documented function that works just the same as before when you use the cake view, but now we can call it from a soap client and get the results back.

Client code:
<?php
$client 
= new SoapClient("http://domain.com/soap5/wsdl/NotesController/");
echo 
"<pre>";
try {    
    
print_r$client->view(1) );
} catch (
SoapFault $exception) {
    
$result .= '..'.var_export($exceptiontrue);
}
echo 
"</pre>";
?>

Client Results:

Array
(
    [0] => 1
    [1] => My first note
    [2] => note body. bla, bla, bla, bla, bla, bla, bla.
    [3] => 2006-10-29 07:23:42
    [4] => 2006-10-29 07:23:42
)


You can view the wsdl for this class by pointing your browser to:
domain.com/soap5/wsdl/NotesController/

Looks good right? Well no, actually there is one glaring problem here. The array keys to the result array have been dropped and replaced with numerical keys. For something as simple as a note, this might be sufficient. But it certainly is not very user(developer) friendly. To overcome this problem we need to use objects to return the data as complex types. Continued on next page...

Page 3: Complex Types

Comments 137

CakePHP Team Comments Author Comments
 

Comment

1 Fantastic

Fantastic article, thanks a lot.

One comment about securty: I've noticed that a lot of the public web services and api's have a login method which returns a "session id" which is then used on every other method. This helps as the login method can be done over SSL and the rest of them will be faster done over normal HTTP. In that way the username and password are not transferred in clear text over HTTP.
Posted Nov 8, 2006 by Mladen Mihajlovic
 

Comment

2 Nice

Hi Shawn,

I've also implemented some SOAP services using CakePHP. But I have slightly different way to do it.

First of all I made the wsdl files manually (using Eclipse tools). It's quite important for me to have full control over my wsdl files.

Each SOAP service (port) has it's own controller, called soap_service_name_controller and there is route to each soap service and wsdl file defined in the `routes.php`.

It's simple way to link SOAP services defined in wsdl file with cake controllers.

When I find some spare time I will put an article describing my way of implementing SOAP services.
Posted Jan 19, 2007 by Wojtek Oledzki
 

Question

3 Code and usage instructions

Are the code and usage instructions available yet? The snippets give me a pretty good idea of how to re-create the setup but something more concrete would be really helpful. Thanks!
Posted Dec 31, 1969 by James Kao
 

Comment

4 Example request

Hi Shawn,

I've also implemented some SOAP services using CakePHP. But I have slightly different way to do it.

First of all I made the wsdl files manually (using Eclipse tools). It's quite important for me to have full control over my wsdl files.

Each SOAP service (port) has it's own controller, called soap_service_name_controller and there is route to each soap service and wsdl file defined in the `routes.php`.

It's simple way to link SOAP services defined in wsdl file with cake controllers.

When I find some spare time I will put an article describing my way of implementing SOAP services.


Can you post your way of doing SOAP service on top of cakePHP? Would be intrested to see that.
Posted May 15, 2007 by Leo Jokinen