<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.barros.ws &#187; soap</title>
	<atom:link href="http://blog.barros.ws/tag/soap/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.barros.ws</link>
	<description>web development tips</description>
	<lastBuildDate>Sun, 06 Jun 2010 00:34:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SOAP WebService in Symfony</title>
		<link>http://blog.barros.ws/2008/11/16/soap-webservice-in-symfony/</link>
		<comments>http://blog.barros.ws/2008/11/16/soap-webservice-in-symfony/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 01:05:34 +0000</pubDate>
		<dc:creator>Carlos Barros</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[webservice]]></category>

		<guid isPermaLink="false">http://blog.barros.ws/?p=69</guid>
		<description><![CDATA[One interesting topic on web development is webservice development. There are several techniques to implement a webservice out there, and today I&#8217;ll talk about one technique that I worked in the recent past that I really like: SOAP. As per wikipedia:
SOAP, originally defined as Simple Object Access Protocol, is a protocol specification for exchanging structured [...]]]></description>
			<content:encoded><![CDATA[<p>One interesting topic on web development is <em>webservice development</em>. There are several techniques to implement a webservice out there, and today I&#8217;ll talk about one technique that I worked in the recent past that I really like: <a href="http://en.wikipedia.org/wiki/SOAP_(protocol)" target="_blank">SOAP</a>. As per wikipedia:</p>
<p><em>SOAP, originally defined as Simple Object Access Protocol, is a protocol specification for exchanging structured information in the implementation of Web Services in computer networks. It relies on Extensible Markup Language (XML) as its message format and usually relies on other Application Layer protocols, most notably Remote Procedure Call (RPC) and HTTP for message negotiation and transmission. SOAP forms the foundation layer of the web services protocol stack providing a basic messaging framework upon which abstract layers can be built.</em></p>
<p>The plan for this tutorial is to build a complete set of webservice methods to interact with the citypicker, <a href="http://blog.barros.ws/2008/10/26/countrystatecity-picker-in-symfony-11/">built in a previous post</a>. For this, I&#8217;ll use a great symfony plugin called <a href="http://www.symfony-project.org/plugins/ckWebServicePlugin">ckWebService</a>. This plugin enables the developer to expose your actions as a SOAP webservices. Another great functionality is the built-in WSDL generator, that parses module&#8217;s doc comment in order to identify which actions should be exposed and it&#8217;s input/output parameters. </p>
<p><span id="more-69"></span></p>
<p>Let&#8217;s start by installing ckWebService plugin in our symfony project. I&#8217;ll not install the latest release, instead I&#8217;ll checkout from trunk svn, as it contains some nice improvements if compared to latest release:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">barrosws@barros.ws [~/symfony/blog]# cd plugins/
barrosws@barros.ws [~/symfony/blog/plugins]# svn co http://svn.symfony-project.com/plugins/ckWebServicePlugin/trunk ckWebServicePlugin</pre></div></div>

<p>OBSERVATION: Current trunk version has a small bug (actually a wrong variable name) that must be fixed before continuing:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getResultProperty<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #339933;">-</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resultMember</span><span style="color: #339933;">;</span>
    <span style="color: #339933;">+</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resultProperty</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we need to configure the plugin in order to make it work. The <a href="http://www.symfony-project.org/plugins/ckWebServicePlugin/2_1_0?tab=plugin_readme">read-me located at plugin page</a> provides a complete guide to configure it. For this project we use a basic configuration:</p>
<p>apps/frontend/config/app.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">soap:
  enable_soap_parameter: on
  ck_web_service_plugin:
    wsdl: soap.wsdl 
    handler: ckSoapHandler
    persist: %SOAP_PERSISTENCE_SESSION%
    render: off
    result_callback: getSoapResult
    soap_options:
      encoding: utf-8
      soap_version: %SOAP_1_2%</pre></div></div>

<p>apps/frontend/config/filters.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">soap_parameter:
  class: ckSoapParameterFilter
  param:
    condition: %APP_ENABLE_SOAP_PARAMETER%</pre></div></div>

<p>apps/frondend/config/factories.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">soap:
  controller:
    class: ckWebServiceController</pre></div></div>

<p>Done! That&#8217;s all we need to start exposing actions as SOAP webservices. For now on we can expose any of our previously created action by adding a special tag to the doc comment, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
  * Action description
  * @ws-enable
  *
  * @param string $name
  * @return boolean
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeSomeAction<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #666666; font-style: italic;">/* action here */</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>This doc comment will expose the action and instruct the WSDL generator that this action expects a string input parameter, called $name and that it will return a boolean value. An interesting thing about this plugin is that it will place all input parameters in the $request object, so the action can access it as if it was called from a browser, passing name as a query string or a post value:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #339933;">...</span>
    <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #339933;">...</span></pre></div></div>

<p>Also, notice that $request parameter was removed from the doc comment. This is necessary because if we keep it, the WSDL generator will add $request as a parameter to the webservice, what is not the case here.</p>
<p>Let&#8217;s start the implementation for this project. We have three actions that will be exposed:</p>
<ul>
<li>executeIndex: to list users;</li>
<li>executeEdit: to insert/edit users;</li>
<li>executeDel: to delete users.</li>
</ul>
<p>One might think that we will need to add @ws-enable to these actions doc comment&#8230; well, yes, that&#8217;s the original idea, but I prefer using a different approach. My approach is to create a new module, called soap (or whatever you want) and create <em>wrappers</em> to actual actions. This will reduce the number changes needed to be done in the actual actions (sometimes it won&#8217;t require any change at all) and will make it possible for the developer to code the entire system without even caring about webservice, all adjustments can be easily made only when actually implementing the webservice. In some emails I exchanged with Christian Kerl, the plugin author, he said me that this is not the best way to achieve this result. The correct way to do this is to create a custom SoapHandler, but this will <strong>kill</strong> WSDL generator (he said work is in progress), so I&#8217;ll stick to my way by now (trunk version has all the necessary changes to make this possible &#8211; it&#8217;s not the case with latest release).</p>
<p>So, let&#8217;s create our new module:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">barrosws@barros.ws [~/symfony/blog]# symfony generate:module frontend soap
&gt;&gt; dir+      /home/barrosws/symfony/blog/apps/frontend/modules/soap/templates
&gt;&gt; file+     /home/barrosws/symfony/blog/app...soap/templates/indexSuccess.php
&gt;&gt; dir+      /home/barrosws/symfony/blog/apps/frontend/modules/soap/actions
&gt;&gt; file+     /home/barrosws/symfony/blog/app.../soap/actions/actions.class.php
&gt;&gt; file+     /home/barrosws/symfony/blog/tes...al/frontend/soapActionsTest.php
&gt;&gt; tokens    /home/barrosws/symfony/blog/tes...al/frontend/soapActionsTest.php
&gt;&gt; tokens    /home/barrosws/symfony/blog/app...soap/templates/indexSuccess.php
&gt;&gt; tokens    /home/barrosws/symfony/blog/app.../soap/actions/actions.class.php</pre></div></div>

<p>The first action will expose is executeIndex, that will return a list of all users registered in the system. This is the simplest one and I&#8217;ll use to explain some important points:</p>
<p>apps/frontend/modules/soap/actions/actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
  * Get users
  *
  * @ws-enable
  * 
  * @return SoapUser[]
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetUsers<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #666666; font-style: italic;">// call actual action</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #666666; font-style: italic;">// set result</span>
  	<span style="color: #000088;">$actionInstance</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastActionInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">users</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>As I said before, we will create <em>wrappers</em> to actual actions. For this action, we don&#8217;t have any input parameter, so we don&#8217;t need any extra processing. First thing the action does is a forward to actual action. Note that I use the forward method from the <strong>controller</strong> instead of forward method from sfAction. This is necessary because we need continue our execution flow AFTER actual action returns (sfAction&#8217;s forward won&#8217;t return control to us). Return value is expected to be located in the deepest action instance, in our case, citypicker/index action, in a property called <em>result</em> (in our case, we store the result of a UserPeer::doSelect() call &#8211; made in citypicker/index action and stored in users property). In order to do this we need to get this action&#8217;s instance and that&#8217;s what getLastActionInstance method do: </p>
<p>apps/frontend/modules/soap/actions/actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
   * Get last action instance
   * 
   * @return sfActionInstance
   */</span>  
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> getLastActionInstance<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionStack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastEntry</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>This method will simply return last actions instance from the action stack, and we will use it in all of our <em>wrappers</em>.  If you look at doc comments, you will notice return value is declared as an array of SoapUser objects. SoapUser class is defined as follows:</p>
<p>lib/soap/SoapUser.class.php</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> SoapUser
<span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * User name
	 * 
	 * @var string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Country ID
	 * 
	 * @var integer
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$country_id</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * State ID
	 * 
	 * @var integer
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$state_id</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * City ID
	 * 
	 * @var integer
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$city_id</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Doc comments are <strong>REQUIRED</strong> here too, because WSDL generator will use it to build the object definition. When sending result back, our result (array of User objects) will be converted into SoapUser objects, making these properties available.</p>
<p>Our first method is complete. In order to start using it, we need to generate the WSDL definition, using the built-in WSDL generator. The generator will also create the frontend dispatcher, in web/ directory:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">barrosws@barros.ws [~/symfony/blog]# symfony webservice:generate-wsdl frontend soap http://blog.barros.ws/symfony
&gt;&gt; file-     /home/barrosws/symfony/blog/web/soap.php
&gt;&gt; file+     /home/barrosws/symfony/blog/web/soap.php
&gt;&gt; tokens    /home/barrosws/symfony/blog/web/soap.php
&gt;&gt; file+     /home/barrosws/symfony/blog/web/soap.wsdl</pre></div></div>

<p>In order to test it we can use a nice piece of software called <a href="http://www.soapui.org/">SoapUI</a>. This software will read soap.wsdl and build the request, all using a nice GUI. I recommend downloading the trial of PRO version, as it is capable of generating forms (web like) where you can input parameters:</p>
<p><center><a href="http://blog.barros.ws/wp-content/uploads/2008/11/picture-3.png"><img src="http://blog.barros.ws/wp-content/uploads/2008/11/picture-3-300x224.png" alt="" title="SoapUI - getUsers request" width="300" height="224" class="alignnone size-medium wp-image-83" /></a></center></p>
<p>executeDel actions is similar to executeIndex:</p>
<p>apps/frontend/modules/soap/actions/actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
  * Deletes an user
  *
  * @ws-enable
  * @param integer $id
  * 
  * @return boolean
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeDelUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #666666; font-style: italic;">// call actual action</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'del'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #666666; font-style: italic;">// set result</span>
  	<span style="color: #000088;">$actionInstance</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastActionInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now, executeEdit (executeNewUser in our wrapper) is a bit trickier:</p>
<p>apps/frontend/modules/soap/actions/actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
  * Creates a new user in the system
  *
  * @ws-enable
  * @param SoapUser $user
  * 
  * @return boolean
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeNewUser<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #666666; font-style: italic;">// convert input param from OBJECT to ARRAY</span>
  	<span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #339933;">,</span><span style="color: #990000;">get_object_vars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #666666; font-style: italic;">// call actual action</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'edit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #666666; font-style: italic;">// check errors</span>
  	<span style="color: #000088;">$actionInstance</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastActionInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">throwSoapFormException</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #000088;">$actionInstance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>First difference we can note is the fact this action requires one input parameters. In doc comment we declare that this action expects an SoapUser object as input, but the actual action expects an simple array. The first step then is to convert received object into an array. For this we use <em>get_object_vars</em> and after conversion, we set it back to the $request object. Finally we call actual action, that will act as if the user had submitted the form. Next difference is that we need to check if there was any error processing input data. We do this by checking if form, in actual action instance, is valid, and if not return an error message. In order to throw an exception with detailed errors, I created an small method called throwSoapFormException, that will iterate through all errors in the form and build  single string, with one error per line:</p>
<p>apps/frontend/modules/soap/actions/actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
   * Throw a SoapFault error based on form errors
   * 
   * @param sfForm $form
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> throwSoapFormException<span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFormFieldSchema</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getError</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
		<span style="color: #000088;">$errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$e</span><span style="color: #339933;">;</span>
&nbsp;
	throw <span style="color: #000000; font-weight: bold;">new</span> SoapFault<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ERROR'</span><span style="color: #339933;">,</span><span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;n&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>And that&#8217;s it, we can now create new users using the new SOAP interface:</p>
<p><center><a href="http://blog.barros.ws/wp-content/uploads/2008/11/picture-4.png"><img src="http://blog.barros.ws/wp-content/uploads/2008/11/picture-4-300x225.png" alt="" title="SoapUI - newUser" width="300" height="225" class="alignnone size-medium wp-image-85" /></a></center></p>
<p>Well, actually one small thing is missing to make it really work&#8230; Did u notice that I didn&#8217;t touch actual actions yet? Sometimes we don&#8217;t need to touch it, but that&#8217;s not our case. If you look at <a href="http://blog.barros.ws/2008/10/26/countrystatecity-picker-in-symfony-11/">citypicker post</a> you will notice that both &#8220;del&#8221; and &#8220;edit&#8221; actions redirect the user back to index page on success. We <strong>can&#8217;t</strong> do this when running on soap mode, or we will lose control and we won&#8217;t be able to send correct result back to the client. To fix this, we just need to make an small change:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isSoapRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker/index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>isSoapRequest is a new method added by ckWebservicePlugin and it will return true when executing the actions via SOAP. Adding this check we just perform the redirect when NOT in SOAP mode.</p>
<p>That&#8217;s all we need to talk about how to expose your actions via SOAP, but in order to complete our example, we need to create some methods to fetch countries/states/cities informations. For this we create 6 new actions:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
  * Get countries list
  * @ws-enable
  *
  * @return SoapGeo[]
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetCountries<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> CountryPeer<span style="color: #339933;">::</span><span style="color: #004000;">doSelect</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Get a country
  *
  * @ws-enable
  * @param integer $id
  * 
  * @return SoapGeo
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetCountry<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> CountryPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Get states list
  *
  * @ws-enable
  * @param integer $country_id
  *
  * @return SoapGeo[]
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetStates<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$country</span> <span style="color: #339933;">=</span> CountryPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'country_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$country</span><span style="color: #009900;">&#41;</span> throw <span style="color: #000000; font-weight: bold;">new</span> SoapFault<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ERROR'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Invalid country'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$country</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStates</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Get a state
  *
  * @ws-enable
  * @param integer $id
  * 
  * @return SoapGeo
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetState<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> StatePeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Get cities list
  *
  * @ws-enable
  * @param integer $state_id
  *
  * @return SoapGeo[]
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetCities<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$state</span> <span style="color: #339933;">=</span> StatePeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span> throw <span style="color: #000000; font-weight: bold;">new</span> SoapFault<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ERROR'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Invalid state'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$state</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCitys</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Get a city
  *
  * @ws-enable
  * @param integer $id
  * 
  * @return SoapGeo
  */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeGetCity<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span> <span style="color: #339933;">=</span> CityPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>And to finish, we need to create the SoapGeo class, that will store country name and id:</p>
<p>lib/soap/SoapGeo.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> SoapGeo
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * ID
     *
     * @var integer
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Name
     *
     * @var string
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And we&#8217;re done. With this we can now build an external app to create/edit/delete users in the database. I spent several days working with the plugin before coming up with this solution and I hope this will save other developers some time dealing with SOAP implementations. Also, I&#8217;d like to thank Christian Kerl for all new changes made to trunk version that is making this plugin even better.</p>
<p>If one wants to test our SOAP interface, the .wsdl file is located at <a href="http://blog.barros.ws/symfony/soap.wsdl">http://blog.barros.ws/symfony/soap.wsdl</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.barros.ws/2008/11/16/soap-webservice-in-symfony/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
	</channel>
</rss>
