SoapSource, a SOAP Client Datasource for CakePHP

18/12/2008

Update: Fixed some stupid typo’s in the documentation.

I’ve published my SOAP Datasource on Github, you can find the sourcecode in the ‘soapsource‘ repository.

SoapSource allows you to connect with SOAP servers that support Wsdl. I also started implementing functionality for non Wsdl SOAP servers, but I don’t think I will continue on this.
SoapSource now supports non wsdl servers also, you can add ‘uri’ and ‘location’ parameters to your datasource configuration now.

In order to use the Datasource you will need to have PHP5 installed with the SOAP extension.

Here’s how you use it:

Copy the soap_source.php file to your app/models/datasources/ directory

Add a configuration to your database.php in app/config/

var $soap = array(
‘datasource’ => ‘soap’,
‘wsdl’ => ‘http://localhost/soapservice.wsdl’, // wsdl mode
‘location’ => ”, // Required for non wsdl mode
‘uri’ => ” // Required for non wsdl mode
);

Then in your model set:

var $useDbConfig = ‘soap’;

var $useTable = false;

And you’re ready to go.

In your controller you can now use

$this->Model->query(‘SoapMethod’, array(‘mySoapParams’));

or

$this->Model->SoapMethod(array(‘mySoapParams’));

Bookmark and Share
Filed under: Cakephp,Webdevelopment
  • http://cakephp.org/ nate

    Hey, spiffy!

    This is almost exactly the API I had envisioned for this stuff, right down to the use of query() and custom methods. Good job on figuring out all the DataSource API stuff.

  • http://www.pagebakers.nl Eelco Wiersma

    Thanks a lot nate!

    Any chance we’ll see something like this in Cake in the future? I noticed there’s a soap class in the 2.x sandbox.

  • Ricky

    Hi,

    that’s the component for working with soap in CakePHP I was looking for: simple to integrate, simple to use. Great work so far. But it doesn’t work for me… :-(

    I downloaded the soap_source.php, added this wsdl-url in the database.php

    http://www.thomas-bayer.com/names-service/soap?wsdl

    and called this code in my test_controller.php:

    $this->Test->query(‘getCountries’, array());
    pr($this->Test);
    exit();

    If I understand this right, I should get an array with country-names.

    It doesn’t work – there is no array of country-names – and I don’t get any error-message.
    The webservice itself works, I tested it with soapUI 2.5.

    The extension for php_soap.dll is activated in php.ini and both options are shown as ‘enabled’ in phpinfo.php

    I am working on my local machine at localhost:8080.

    Do you have any ideas what could be my mistake? Could you also please tell what format the params in the array must have if I have any?

    Greetings,
    Ricky

  • http://www.pagebakers.nl Eelco Wiersma

    Ricky,

    First of all to output the result you should use something like:

    $result = $this->Test->query(’getCountries’, array());
    pr($result);
    exit();

    If you use wsdl, you can just pass the parameters in the correct order in the params array. The soap extension will take care of the rest.

    Hope this helps

  • Ricky

    Hi again!

    I’m sorry, but there is still no result. :-(
    Could you please try it with this WSDL and if it was successful, mail me your code? Perhaps I’ve did something basically wrong and am searching on the wrong place…

    Ah, I forget to say: I use the newest CakePHP-Version available: 1.2.0.7962.

    Thanks a lot and happy new year!

    Greetings,
    Ricky

  • http://www.linkedin.com/in/vincedelmonte Vince Delmonte

    After reading through this article, I just feel that I really need more info. Could you suggest some more resources please?

  • http://www.pagebakers.nl Eelco Wiersma
  • Craft

    Hi,

    After reading your article, I tried to implement the SoapSource to a web application that I have to develop for my work. My WebApp is like a directory of documents. And the Documents belong to User. The model User is a DataSource from another WebApp. I have to load the users information from a SOAP webservice called getLiteMemberList.
    How could I use your code ? I tried to implement it but, I have this error:

    Fatal error: Call to undefined method SoapSource::calculate() in ###\cake\libs\model\model.php on line 2015

  • Steven Wrigh

    Thanks for the work. I have set up the code as you showed but when I make a call to the API I get the following error:
    SOAP Error: Function (“QuerySub”) is not a valid method for this service [APP\models\datasources\soap_source.php, line 201]

    I know for a fact that this method exists as I use it in my own SOAP class.

    Any suggestions you can offer would be appreciated.

    Thanks.

  • Steven Wright

    Forget my last message. I was in error.

  • Steven Wright

    Ok now I have discovered a problem. When I send a transaction to my API I have specific field names for the data. Your class seems to be overwriting these. Here is my set up:

    function view($id = null)
    {
    // http://www.pagebakers.nl/2008/12/18/soapsource-a-soap-client-datasource-for-cakephp/
    //$this->Subscriber->id = $id;
    $this->TransactionParams = array();
    $this->TransactionParams['loginName'] = ‘XXX’;
    $this->TransactionParams['loginPassword'] = ‘XXX’;
    $this->TransactionParams['orgName'] = ‘Solo Field Dev’;

    $this->TransactionParams['transaction']['id'] = ‘cake_test’;
    $this->TransactionParams['transaction']['wait'] = ’0′;
    $this->TransactionParams['transaction']['version'] = ’3.2′;
    $this->TransactionParams['transaction']['TransactionCommandList'] = array();
    $this->TransactionParams['transaction']['TransactionCommandList']['QuerySub']['SubscriberId'] = 456;
    $this->set(‘subscriber’, $this->Subscriber->query(‘SendTransaction’, $this->TransactionParams ));
    }

    Here is the Resulting XML:

    client6065
    Solo Field Dev

    id
    cake_test

    wait
    0

    version
    3.2

    TransactionCommandList

    QuerySub

    SubscriberId
    456

    As you can see the fields names are wiped and replaced with Param(n)

    Am I doing something wrong?

  • Steven Wright

    XML

    client6065
    Solo Field Dev

    id
    cake_test

    wait
    0

    version
    3.2

    TransactionCommandList

    QuerySub

    SubscriberId
    456

  • Steven Wright

    Sorry man I cant seem to post the XML. But essentially I need to know why the field names are overwritten.

    Thanks

  • Steven Wright

    I changed the following line in your class:

    $result = $this->client->__soapCall($method, $queryData);

    to:

    $result = $this->client->sendTransaction($queryData);

  • Sean

    I am interested in serializing and then caching the response as is offered in the nuSOAP library, where would I start? Or would I have been luck just starting from scratch with nuSOAP?

  • http://www.pagebakers.nl Eelco Wiersma

    @Sean, well you could use my code as a start, replace the standard SoapClient code with the nuSOAP class’ methods

  • Pingback: [PRONIQUE] CakePHP Developer Links

  • Mark

    Hi,

    Followed all the steps.
    Calling a webservice like this:
    $response = $this->Employee->query(‘getAuthorisation’, array(‘john’, ‘password1′));
    (I’ve tried many, many notations, varieties)

    In my webservice console i see that the webservice getAuthorisation is called, but no parameters are passed along!
    When i print the value of $method and $queryData right before the webservice in soap_source.php is called i get this:
    string(16) “getAuthorisation”
    array(2) {
    [0]=>
    string(4) “john”
    [1]=>
    string(4) “password1″
    }

    Somehow the parameters are not accepted/passed along at some later point!

    If anyone can help me out here, would be greatly appreciated!!

  • Steven Wright

    I am having a problem adding attributes and was wondering if you could shed some light. I have pasted below a portion of XSD that defines the section I am working with as well as the PHP I am using to create the structure. Right before sendTransaction I can see the params are there but they are not getting converted to XML.

    public function AddUpdateServices($subscriber_id, $actions)
    {
    $this->add_transaction_id(‘AddUpdateSub’);
    $command = array();

    $command['AddUpdateSub']['SubscriberId'] = $subscriber_id;

    $command['AddUpdateSub']['ServiceList']['replace'] = ‘yes’;

    foreach($actions['DeleteSubService'] as $service_name)
    {
    $service = array();
    $service['action'] = ‘delete’;
    $service['ServiceName'] = $service_name;
    $command['AddUpdateSub']['ServiceList'][]->Service = $service;
    }

    foreach($actions['AddUpdateSubService'] as $service_name)
    {
    $service = array();
    $service['action'] = ‘add’;
    $service['ServiceName'] = $service_name;
    $command['AddUpdateSub']['ServiceList'][]->Service = $service;
    }

    $this->add_command_to_transaction($command);
    return $this->formatResult($this->query(‘SendTransaction’,$this->TransactionParams));
    }

  • http://www.pagebakers.nl Eelco Wiersma

    Steven, can you paste a print_r of $this->TransactionParams ?

  • Ian

    Calls make to getRequest and getResponse after query do not output anything. Am I missing something here?

  • Ian

    By the way my debug level is set to 2 so I would assume this line in the SoapSource class -

    $options = array(‘trace’ => Configure::read(‘debug’) > 0);

    would set the trace option to ‘true’ and therefore enable output from __getLastRequest / __getLastResponse.

  • http://www.pagebakers.nl Eelco Wiersma

    @Ian unfortunately you can’t call those methods directly from your controller currently

  • Aldo

    soap_source – line 163
    Change

    if(!$method || !$queryData) {

    with

    if(!isset($method) || !isset($queryData)) {

    because “!$queryData” is TRUE if args array is empty.

  • Pingback: David E Jones

  • http://www.wordpress-top-rank.info Fae Housel

    Hello Web Admin, I noticed that your On-Page SEO is is missing a few factors, for one you do not use all three H tags in your post, also I notice that you are not using bold or italics properly in your SEO optimization. On-Page SEO means more now than ever since the new Google update: Panda. No longer are backlinks and simply pinging or sending out a RSS feed the key to getting Google PageRank or Alexa Rankings, You now NEED On-Page SEO. So what is good On-Page SEO?First your keyword must appear in the title.Then it must appear in the URL.You have to optimize your keyword and make sure that it has a nice keyword density of 3-5% in your article with relevant LSI (Latent Semantic Indexing). Then you should spread all H1,H2,H3 tags in your article.Your Keyword should appear in your first paragraph and in the last sentence of the page. You should have relevant usage of Bold and italics of your keyword.There should be one internal link to a page on your blog and you should have one image with an alt tag that has your keyword….wait there’s even more Now what if i told you there was a simple WordPress plugin that does all the On-Page SEO, and automatically for you? That’s right AUTOMATICALLY, just watch this 4minute video for more information at. WordPress Seo Plugin

  • Jeff

    Nate, this is just great. I’m working on an app that uses it, and it works great, right up until I need to pass in an array.

    The XSD calls for something like this (paraphrased for clarity and so I can post it here):

    MYDATA
    . FIELD1
    . . field1Val
    . /FIELD1
    . FIELD2LIST
    . . FIELD2ITEM
    . . . first item
    . . /FIELD2ITEM
    . . FIELD2ITEM
    . . . second item
    . . /FIELD2ITEM
    . /FIELD2LIST
    /MYDATA

    So, I tried:

    $data = array();
    $data['FIELD1'] = ‘field1val’;
    $data['FIELD2LIST'] = array();
    $data['FIELD2LIST'][] = array(‘FIELD2ITEM’, ‘first item’);
    $data['FIELD2LIST'][] = array(‘FIELD2ITEM’, ‘second item’);

    and I got ARRAY where the first item and second item should be in the XML output.

    So, I tried:

    $data = array();
    $data['FIELD1'] = ‘field1val’;
    $data['FIELD2LIST'] = array();
    $obj = new stdClass();
    $obj->FIELD2ITEM = ‘first item’;
    $data['FIELD2LIST'][] = $obj;
    $obj = new stdClass();
    $obj->FIELD2ITEM = ‘second item’;
    $data['FIELD2LIST'][] = $obj;

    This gives me OBJECT where the first and second items should be. Any ideas? We’re getting a little desperate here…

  • Jeff

    Okay, for the benefit of anyone who lands here looking for a hint how to pass an array with SOAP in PHP, here’s how it works:

    1- You create an ARRAY as a named item in the master data array. The name of the array is the name of the array in the XSD (usually has “List” in the name).

    2- You add the values to the array, WITHOUT regard for the name of the element in which they must be encapsulated, and rely on the SOAP connector to put in the element names correctly, based on the XSD.

    So, in the example above, it goes like this:

    $data = array();
    $data['FIELD1'] = ‘field1val’;
    $data['FIELD2LIST'] = array();
    $data['FIELD2LIST'][] = ‘first item’;
    $data['FIELD2LIST'][] = ‘second item’;

    And the FIELD2ITEM tags get put in by magic, and it all works.

    Like everything else, simple when you know how.