A Component to help creating SOAP services

This article is also available in the following languages:
By char101
A component providing automatic WSDL generation using jool.nl Webservice Helper library, CakePHP caching of generated WSDL, and automatic handling of SOAP calls.

Concepts

  • SOAP methods will be implemented as model class methods. Models that will handle SOAP calls will have suffix Service, for example BookService
  • The Soap component will provide function to generate WSDL from the model class definition and to handle SOAP calls to the model class methods.
  • A controller will act as a SOAP proxy to the service models using the SOAP component

Requirements

  • PHP Soap extension
  • CakePHP 1.2 (haven't tested it in CakePHP 1.1)

Webservice Handler library

Download Webservice Handler library from jool.nl site and extract the contents into app/vendors/wshelper.

Create the SOAP component

Save the code below into app/controllers/components/soap.php.
The generated WSDL will be cached into app/tmp/cache directory. If DEBUG configuration
is greater than 0, the cache file modified time will be compared the model file
modified time and updated appropriately.

Component Class:

<?php 
vendor
('wshelper/lib/soap/IPReflectionClass.class');
vendor('wshelper/lib/soap/IPReflectionCommentParser.class');
vendor('wshelper/lib/soap/IPXMLSchema.class');
vendor('wshelper/lib/soap/IPReflectionMethod.class');
vendor('wshelper/lib/soap/WSDLStruct.class');
vendor('wshelper/lib/soap/WSDLException.class');

/**
 * Class SoapComponent
 *
 * Generate WSDL and handle SOAP calls
 */
class SoapComponent extends Component
{
    var 
$params = array();

    function 
initialize(&$controller)
    {
        
$this->params $controller->params;
    }
    
    
/**
     * Get WSDL for specified model.
     *
     * @param string $modelClass : model name in camel case
     * @param string $serviceMethod : method of the controller that will handle SOAP calls
     */
    
function getWSDL($modelId$serviceMethod 'call')
    {
        
$modelClass $this->__getModelClass($modelId);
        
$expireTime '+1 year';
        
$cachePath $modelClass '.wsdl';
        
        
// Check cache if exist
        
$wsdl cache($cachePathnull$expireTime);

        
// If DEBUG > 0, compare cache modified time to model file modified time
        
if ((Configure::read() > 0) && (! is_null($wsdl))) {

            
$cacheFile CACHE $cachePath;
            if (
is_file($cacheFile)) {
                
$modelMtime filemtime($this->__getModelFile($modelId));
                
$cacheMtime filemtime(CACHE $cachePath);
                if (
$modelMtime $cacheMtime) {
                    
$wsdl null;
                }
            }

        }
        
        
// Generate WSDL if not cached
        
if (is_null($wsdl)) {
        
            
$refl = new IPReflectionClass($modelClass);
            
            
$controllerName $this->params['controller'];
            
$serviceURL Router::url("/$controllerName/$serviceMethod"true);

            
$wsdlStruct = new WSDLStruct('http://schema.example.com'
                                         
$serviceURL '/' $modelId
                                         
SOAP_RPC
                                         
SOAP_LITERAL);
            
$wsdlStruct->setService($refl);
            try {
                
$wsdl $wsdlStruct->generateDocument();
                
// cache($cachePath, $wsdl, $expireTime);
            
} catch (WSDLException $exception) {
                if (
Configure::read() > 0) {
                    
$exception->Display();
                    exit();
                } else {
                    return 
null;
                }
            }
        }

        return 
$wsdl;
    }

    
/**
     * Handle SOAP service call
     *
     * @param string $modelId : underscore notation of the called model
     *                          without _service ending
     * @param string $wsdlMethod : method of the controller that will generate the WSDL
     */
    
function handle($modelId$wsdlMethod 'wsdl')
    {
        
$modelClass $this->__getModelClass($modelId);
        
$wsdlCacheFile CACHE $modelClass '.wsdl';

        
// Try to create cache file if not exists
        
if (! is_file($wsdlCacheFile)) {
            
$this->getWSDL($modelId);
        }

        if (
is_file($wsdlCacheFile)) {
            
$server = new SoapServer($wsdlCacheFile);
        } else {
            
$controllerName $this->params['controller'];
            
$wsdlURL Router::url("/$controllerName/$wsdlMethod"true);
            
$server = new SoapServer($wsdlURL '/' $modelId);
        }
        
$server->setClass($modelClass);
        
$server->handle();
    }

    
/**
     * Get model class for specified model id
     *
     * @access private
     * @return string : the model id
     */
    
function __getModelClass($modelId)
    {
        
$inflector = new Inflector;
        return (
$inflector->camelize($modelId) . 'Service');
    }

    
/**
     * Get model id for specified model class
     *
     * @access private
     * @return string : the model id
     */
    
function __getModelId($modelClass)
    {
        
$inflector = new Inflector;
        return 
$inflector->underscore(substr($class0, -7));
    }

    
/**
     * Get model file for specified model id
     *
     * @access private
     * @return string : the filename
     */
    
function __getModelFile($modelId)
    {
        
$modelDir dirname(dirname(dirname(__FILE__))) . DS 'models';
        return 
$modelDir DS $modelId '_service.php';
    }
}
?>

Create the controller that will handle SOAP calls

This is an example controller. You can change the method name
that will handle SOAP calls and provide WSDL definition as you wish.
But don't forget to change the arguments to the handle and
getWSDL methods.
Save the file into app/controllers/service_controller.php

Controller Class:

<?php 
class ServiceController extends AppController
{
    public 
$name 'Service';
    public 
$uses = array('TestService');
    public 
$helpers = array();
    public 
$components = array('Soap');

    
/**
     * Handle SOAP calls
     */
    
function call($model)
    {
        
$this->autoRender FALSE;
        
$this->Soap->handle($model'wsdl');
    }

    
/**
     * Provide WSDL for a model
     */
    
function wsdl($model)
    {
        
$this->autoRender FALSE;
        
header('Content-Type: text/xml'); // Add encoding if this doesn't work e.g. header('Content-Type: text/xml; charset=UTF-8'); 
        
echo $this->Soap->getWSDL($model'call');
    }
}
?>

Create the service model

This is a test model. Save it into app/models/test_service.php. Note that the webservice handler library parses the method comments to create the WSDL, so you'll need to make sure that all the function parameters and return value are documented in the function docblock. Make sure that you specify the type of each parameters and make sure the ordering matches the order of the parameters in the function. (Thanks to Brett Nemeroff for pointing this).

Model Class:

<?php 
class TestService extends AppModel
{
    var 
$name 'TestService';
    var 
$useTable false;

    
/**
     * Divide two numbers
     *
     * @param float $a
     * @param float $b
     * @return float
     */
    
function divide($a$b)
    {
        if (
$b != 0) {
            return 
$a $b;
        }
        return 
0;
    }
}
?>

Testing the service

My favorite tool for testing SOAP services is SoapUI. You can use it or your
favorite tool to test the service. To access the WSDL, direct your tool to
http://yourhost/service/wsdl/test. The SOAPAction URL will be
http://yourhost/service/call/test.

Comments

  • Posted 07/02/10 07:26:35 PM
    Hi,

    This component shows a lot of promise, but one problem I can't seem to get my head around is that it calls methods inside a Model rather than a Controller.

    I only seem to be able to create methods in the Model. How do I query other (multiple) tables and perform business logic?

    Thanks,
    Jonathan
  • Posted 03/21/10 04:07:01 PM
    Due to SoapComponent extending Component, I ran into issues with infinite redirects when auth'ing. Is there a reason it must extend Component versus Object like the docs suggest (http://book.cakephp.org/view/64/Creating-Components)?
  • Posted 12/22/09 03:19:08 AM
    Hi all,
    Thanks so far for all the help. I got the component working to the point where the WSDL XML is generated. I am using SoapUi to test and the example requests are generated when I start a new project in SoapUI.

    My problem is that when I call a method I get an zero sized return.

    The Request (This is the request generated by SoapUI)


    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://schema.example.com">
       <soapenv:Header/>
       <soapenv:Body>
          <sch:divide>
             <a>16</a>
             <b>4</b>
          </sch:divide>
       </soapenv:Body>
    </soapenv:Envelope>

    Raw return


    HTTP/1.1 200 OK

    Date: Tue, 22 Dec 2009 09:07:41 GMT

    Server: Apache/2.2.3 (CentOS)

    X-Powered-By: PHP/5.2.5

    Set-Cookie: CAKEPHP_SOAP=ce95c4abe9787b51a41b92c47ada9eba; path=/

    P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

    Content-Length: 0

    Connection: close

    Content-Type: text/xml


    Does anyone have an idea what I am doing wrong.

    So It was a problem with my PHP en server config

    1. Make sure that you PHP has the SOAP compiled in or a PHP SOAP module is loaded via the php.ini file.
    2. SOAP seems to be quite strict on hostnames. Make sure that your server and client resolves the same IP for the name that you are using in your soap call. I had to add the hostname of my dev server on the servers hosts file to make it work.
  • Posted 12/10/09 07:55:44 PM
    Note that the wsdl generator recognizes a very limited subset of attribute types. If your docblock parameter type is anything other than string, int, integer, boolean, or float, the output will fail with no notice (even if the debug flag is turned on in the soap component).

    The array of recognized types is in IPXMLSchema.class.php, around line 145 (in release 1.5 of the jool.nl webservice helper).


    /**
     * Checks if the given type is a valid XML Schema type or can be casted to a schema type
     * @param string The datatype
     * @return string
     */
    public static function checkSchemaType($type) {
        //XML Schema types
        $types = Array("string" => "string",
              "int" => "int",
              "integer" => "int",
              "boolean" => "boolean",
              "float" => "float");
        if(isset($types[$type])) return $types[$type];
        else return false;
    }
  • Posted 11/11/09 01:07:19 PM
    This is a little tip for those just setting it up and run into the issues described in Comment #9 - Problem with customization.
    I checked out my phpinfo() and found under the soap section, soap.wsdl_cache=1
    Seems once a wsdl is cached, your changes the webservice model would not be automatically updated.

    After removing the cache files [wsdl*] located in soap.wsdl_cache_dir and disabling soap.wsdl_cache everything works perfectly.

    ini_set('soap.wsdl_cache', 0);

    That in beforeFilter was enough to disable it.

    Hope this helps someone.
  • Posted 10/04/09 07:11:52 AM
    guy's please help me.
    if i'm call http://localhost/myapp/service/wsdl/test
    the result is good (noting wrong, maybe...)
    but if i'm call with http://localhost/myapp/service/call/test
    the result is

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
       <faultcode>
        WSDL
       </faultcode>
       <faultstring>
        SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/myapp/service/service/wsdl/test.wsdl' : failed to load external entity "http://localhost/myapp/service/service/wsdl/test.wsdl" 
       </faultstring>
      </SOAP-ENV:Fault>
     </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    Is there any solution??
    thanks for reply
    • Posted 12/22/09 05:29:31 AM
      guy's please help me.
      if i'm call http://localhost/myapp/service/wsdl/test
      the result is good (noting wrong, maybe...)
      but if i'm call with http://localhost/myapp/service/call/test
      the result is

      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
         <faultcode>
          WSDL
         </faultcode>
         <faultstring>
          SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/myapp/service/service/wsdl/test.wsdl' : failed to load external entity "http://localhost/myapp/service/service/wsdl/test.wsdl" 
         </faultstring>
        </SOAP-ENV:Fault>
       </SOAP-ENV:Body>
      </SOAP-ENV:Envelope>
      Is there any solution??
      thanks for reply

      Make sure that you server and client both resolve the same IP for the hostname that you use in your SOAP call. I had the same error when the server could not resolve the correct IP for the hostname in die SOAP call.
  • Posted 09/22/09 01:01:53 PM
    I found some bugs related to the generation of the xmlschema when the parameter is an object. I fixed them and I'm trying to make these fixes available. If anyone know how to make these fixes available please let me know.
  • Posted 06/18/09 02:12:34 AM
    Wsdl cache caused me headache when I was testing my web service while changing return types (objects in particular) - saying no method with that name is available. After I deleted /tmp/wsdl* it started working as expected.
  • Posted 06/16/09 08:03:32 AM
    I have checked my model, controller, and component files. And there are one space caracter at the end of the files after ?>. I've deleted them and now it works perfectly. Thanks everyone !
  • Posted 06/05/09 08:18:33 AM
    @Matt Mendick

    My bad, I sure was confused :D. Sorry about that.
    • Posted 06/05/09 12:23:52 PM
      No problem, thanks for all your work on this.

      @Matt Mendick

      My bad, I sure was confused :D. Sorry about that.
  • Posted 06/05/09 07:59:51 AM
    Hi again - I think there's some confusion with @Charles about who was commenting on what here, not that it makes a big difference to the ultimate decyphering of the code, but the person who posted the comment has their name below the comment, not above it, so I was the one who posted about the @params, and @Kwan Joel was posting about the xml header issues.

    To complicate things more, I'll now talk about the xml header issues:

    I was also having the problem where the generated text was a valid wsdl (determined by copying and pasting the source into a plain .xml static file, then viewing it with firefox: valid wsdl), but the header was still coming through as text/html on the generated document. I haven't had time to dig through and figure out exactly what is going on, but it seems as if the method showWSDL in WSHelper.class.php is not getting called, as the header() call in that method is not being called, therefore the header is not being set and is defaulting to text/html. So, I "fixed" the problem (at least my problem) by removing the header() call in showWSDL, and adding this line:


    header('Content-type: text/xml; charset=UTF-8');

    as the first line in the method getWSDL, which is in soap.php (component class).

    This seems to work quite well, and I get valid xml, which is shown in "nice form" in firefox.

    Now I really have working code, thanks a lot. For people talking about having spaces, I definitely would check all php files involved with the service, to make sure there are no spaces or newlines at the beginning or end of the files (before or after the tags) because that will definitely be causing you troubles.
  • Posted 06/04/09 08:20:20 AM
    @Matt Mendick

    Thanks, I have added some more explanation to the article.
    • Posted 06/05/09 12:43:49 AM
      @Matt Mendick
      Hi thanks. I've found that the generated xml has three space characters at the beginning of the file. How could I delete them ? I don't really know what file I have to edit.
  • Posted 06/04/09 06:59:48 AM
    hi,

    I recently working with CakePHP and I have to implement a SOAP Server with my models. I have follow all the tutorial, and the comments. But My server can not generate the wdsl xml.

    In a first time, I have to add

    header('Content-type: text/xml; charset=UTF-8');
    in the getWSDL method in the component soap.php. If I do not have this line in this method, the wdsl file is not considered as an xml file but as an html file.

    And when I add the type of the content, I get this error:

    Erreur d'analyse XML : instruction de traitement XML ou texte pas au début d'une entité externe
    Emplacement : http://127.0.0.1/siv/service/wsdl/test
    Numéro de ligne 1, Colonne 4 :   <?xml version="1.0"?>
    ---^

    Is there any solution to delete the default line ?

    • Posted 06/15/09 06:09:38 PM
      And when I add the type of the content, I get this error:

      Erreur d'analyse XML : instruction de traitement XML ou texte pas au début d'une entité externe
      Emplacement : http://127.0.0.1/siv/service/wsdl/test
      Numéro de ligne 1, Colonne 4 :   <?xml version="1.0"?>
      ---^

      Is there any solution to delete the default line ?


      check if there are any trailing spaces after ?> in your component/controller/model files.
      I had some and that caused the same problem
  • Posted 06/03/09 12:20:47 PM
    Earlier in the comments, people were having problems dealing with parameters, as was I. In the article, the author shows an example model method as this:


        /**
         * Divide two numbers
         *
         * @param float $a
         * @param float $b
         * @return float
         */
        function divide($a, $b)
        {
            if ($b != 0) {
                return $a / $b;
            }
            return 0;
        }

    But they probably forgot to mention that the comments appearing above the function are extremely important! The vendor wshelper files must read them to determine the structure of the WSDL. Therefore, if I wanted 4 parameters in my function (name, age, height, weight) and for it to return a string, I would need to put them in the comments, like so:

    [code] /**
    * Divide two numbers
    *
    * @param string $name
    * @param int $age
    * @param int $height
    * @param int $weight
    * @return string
    */
    function divide($name, $age, $height, $weight)
    {
    // your code
    return $mystring;
    }

    [code]
    So, in case anyone else couldn't figure that out, it's there now, explicitly stated.

    Thanks for this article, it's made soap so much easier for me, I really appreciate your time put into this.
  • Posted 03/13/09 12:13:39 PM
    Can someone post an example of a custom complex type?

    Here's what I'm trying, proof of concept style:


            /**
             * List of patients
             *
             * @return string[]
             */
            function getlist() {
                    $val=array('one',array('joe','mack','rob'),'three');
                    return $val;
            }

    This produces:


    <SOAP-ENV:Body>
    -<ns1:getlistResponse xmlns:ns1="http://schema.example.com">
    -<getlistReturn>
    -<xsd:string>one</xsd:string>
    -<xsd:string>Array</xsd:string>
    -<xsd:string>three</xsd:string>
    </getlistReturn>
    </ns1:getlistResponse>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

    I know I probably need to make a class and reference it, but I'm not really sure how to even define the class as a complex type. A small example would go a long way. :)

    Thanks,
    Brett

  • Posted 03/02/09 07:11:38 AM
    Has anyone had luck implementing custom types and then using it as an array.

    eg:
    class appointment
    {
    /** @var float */
    public $patient;

    /** @var string */
    public $time;
    }

    /**
    * Add appointments
    *
    * @param appointment[] $a
    * @return int
    */
    function add($a)
    {
    ...
    }

    I'm trying to send an array of appointments from a C# app. But either get a null passed into param $a or an empty StdClass.

    Thanks in advanced.
    Alix
    • Posted 03/02/09 07:57:39 AM
      Are you getting just one StdClass or an array of empty objects with StdClass?

      If its the later then try using a classmap when you instantiate your soap server so that it can map the array objects to your class.
      $server = new SoapServer("appointments.wsdl", array("classmap" => array("appointment" => "localAppointmentClass")));
      • Posted 09/17/09 11:35:36 AM
        Are you getting just one StdClass or an array of empty objects with StdClass?

        If its the later then try using a classmap when you instantiate your soap server so that it can map the array objects to your class.
        $server = new SoapServer("appointments.wsdl", array("classmap" => array("appointment" => "localAppointmentClass")));

        But in example is "$server = new SoapServer($wsdlURL . '/' . $modelId);" ,how I could modify to using a classmap ?

        thanks a lot of.
      • Posted 03/03/09 03:07:28 AM
        I added the classmap map however now I get an empty Appointment object instead of an array of Appointments.

        By the way thanks for the component Charles.


        Are you getting just one StdClass or an array of empty objects with StdClass?

        If its the later then try using a classmap when you instantiate your soap server so that it can map the array objects to your class.
        $server = new SoapServer("appointments.wsdl", array("classmap" => array("appointment" => "localAppointmentClass")));
  • Posted 02/27/09 10:01:20 AM
    Ok, I don't know what I'm missing here. I've followed these directions and it works perfectly with Max's recommended changes. However, if I change the code, presumably to actually use it for something useful, things break.. Even little changes. Take the model:

    Model Class:

    <?php 

            
    function divide($a$b)
            {
                    if (
    $b != 0) {
                            return 
    $a $b;
                    }
                    return 
    0;
            }
    ?>

    if I change it to:

    Model Class:

    <?php 
            
    function divide($a$c)
            {
                    if (
    $c != 0) {
                            return 
    $a $c;
                    }
                    return 
    0;
            }
    ?>


    It doesn't work. It returns 0 everytime. In fact, if I just return $c in that example, it returns null. It's worth mentioning that the wsdl IS rendered properly requesting a 'c' var instead of a 'b' var. The soap request changed to 'c' looks good too:


    <SOAP-ENV:Body>
        <m:divide xmlns:m="http://www.example.com/">
          <a xsi:type="xsd:float">5</a>
          <c xsi:type="xsd:float">6</c>
        </m:divide>
    </SOAP-ENV:Body>


    I'm not sure what I'm missing here..

    Now I added a function to the model:

    Model Class:

    <?php 
            
    /**
             * Add two numbers
             *
             * @param float $a
             * @param float $b
             * @return float
             */
            
    function add($a,$b)
            {
                    return 
    $a $b;
            }
    }
    ?>

    Which once again, the WSDL is generated perfectly, but when I make a request I get "Procedure 'add' not present. Am I supposed to register my functions somewhere? That would explain all of this, but in the working example, I don't see the functions or the variables registered. So I'm really confused.

    Lastly, and this I'm sure will expose my lack of experience in Cake, why are the functions in the model, and not the controller? I'm not sure how to do all the same controller type actions from the model. Am I missing something?

    Thanks!
    -Brett

    • Posted 02/27/09 10:34:13 AM
      @Brett
      Are you using some opcode cache (eAccelerator, APC). Probably you can try disabling it. Also check that the file refered by $wsdlCacheFile exists and that the content is right.

      The functions are placed in the model because SoapServer needs a class and it will be rather messy if the controller that calls the component will be used by the component to handle the request. Besides, controller outputs view and models returns data. Web service functions does not deal with view and more with data so I think it fits more in the model.
  • Posted 02/19/09 05:53:34 AM
    I've just used this with cake 1.2 and it works fine.

    I did have to change a couple of things.

    1) Vendor imports

    App::import('Vendor', 'IPReflectionClass', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'IPReflectionClass.class.php'));
    App::import('Vendor', 'IPReflectionCommentParser', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'IPReflectionCommentParser.class.php'));
    App::import('Vendor', 'IPXMLSchema', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'IPXMLSchema.class.php'));
    App::import('Vendor', 'IPReflectionMethod', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'IPReflectionMethod.class.php'));
    App::import('Vendor', 'WSDLStruct', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'WSDLStruct.class.php'));
    App::import('Vendor', 'WSDLException', array('file' => 'wshelper' . DS . 'lib' . DS . 'soap' . DS . 'WSDLException.class.php'));

    2) If debug is 2 the xml output is not valid so i turned it off in the controller

    function afterFilter()
    {
        if (Configure::read('debug') > 1){
            Configure::write('debug', 0);
        }
    }

    I also found a couple of things that you might want to consider mentioning or changing

    1) The WSDL file generated makes references to the http://schema.example.com namespace.

    An alternative would be

    $wsdlStruct = new WSDLStruct(Router::url('/', true),
                        $serviceURL . '/' . $modelId,
                        SOAP_RPC,
                        SOAP_LITERAL);

    2) The line that saves the generated WSDL file in cache is commented

    //cache($cachePath, $wsdl, $expireTime);
    Thanks again for the component, it integrates nicely with cakephp.
  • Posted 11/20/08 01:42:21 PM
    Hi,

    I have a problem loading the vendor... i'm using CakePHP 1.2 RC3...

    can anyone help me...
  • Posted 03/27/08 08:31:53 PM
    I make SOAP service, but with authorization(SOAP headers) and handler - controller and i have problems with it.
    http://groups.google.com/group/cake-php/browse_thread/thread/1856af46a3589303#
  • Posted 11/19/07 08:05:11 PM
    I have just two question.

    In your model example, there is a function Divide.. ok.
    But if I create :

    function minus($a, $b)
    {
    return $a - $b;
    }

    I received in my Soap client this message :

    "Procedure 'addition' not present"

    Need I to create this function elsewhere ?

    Otherwise, how to simply get a listing of a any model ?

    Thank you very much for your help !
  • Posted 11/16/07 08:32:57 PM
    Just curious if anyone has implemented this tutorial successfully...
    • Posted 11/17/07 01:32:21 AM
      The model class inherits some functions from its parent class (cakePHP's base model class). The wshelper library requires that methods that do not return anything be tagged with @return void but since there are some of the inherited methods that do not have the @return tag, the library emits notice.

      To fix it, simply edit the IPReflectionCommentParser.class.php around line 135, add the check

      if (! isset($tagArr[1])) {
          $tagArr[1] = 'void';
      }
      just below the

      case 'return':

      Sorry if I didn't put this in the article.
  • Posted 11/15/07 11:14:46 AM
    Thanks for the article.

    I am getting the following error after following this tutorial:


    Notice (8): Undefined offset:  1 [CORE\app\vendors\wshelper\lib\soap\IPReflectionCommentParser.class.php, line 136]

    I am using:
    cake 1.2.0.5875 pre-beta
    php 5.2.3
    jool.nl webservices helper 1.5.0


    It appears to throw an error when it attempts to generate the wsdl file for the first time from the ->setService($refl) call on line 64 of the soap.php component:


    60            $wsdlStruct = new WSDLStruct('http://schema.example.com', 
    61                                         $serviceURL . '/' . $modelId, 
    62                                         SOAP_RPC, 
    63                                         SOAP_LITERAL);
    64            $wsdlStruct->setService($refl);
    65            try {
    66                $wsdl = $wsdlStruct->generateDocument();
    67                // cache($cachePath, $wsdl, $expireTime);
    68            } catch (WSDLException $exception) {

    Any ideas?

    NSM

Comments are closed for articles over a year old