Symfony 1.4, Component Caching and SOAP

No Gravatar

I recently found myself having to get some data from a SOAP service onto a Symfony 1.4 site.  The data consisted of a simple title, location and posting date of the two most recent records from the service.

When accessing a SOAP service – especially when your API access is metered – it’s often a good idea to set up a local cache of the data.  That way you’re not burning your page load times with server-side HTTP requests, using up precious request allotments or concurrent connection limits.  Which means you have to mirror or abstract the remote inside of your app.
Initially my design consisted of creating a local Doctrine 1.2 data model, a handful of application configuration options and then adding some methods to the model and table classes to fetch locally and update the database with forced or timed expiries.

This design is elegant and it works very well, there’s nothing wrong with it.  Unfortunately, due to the size of the data being retrieved (two most recent records) and the simplicity of the operation, it seemed like overkill.  We were only using the data in one place and had no other use for it, so modelling it locally didn’t make much sense.

Enter Symfony Component Caching.

Conveniently, Symfony offers the ability to cache components and their output.  This includes caching the result of running the sfComponents‘ action code, which ensures that the API calls found within aren’t executed between cache expiries.

Enabling Component Caching

I’ll cover the simple part first, which is the configuration required to enable caching.  Keep in mind that other cache settings in your app may have an effect on what I put here:

Create or edit :  app/yourApp/modules/yourModule/config/cache.yml
_yourComponent:
  enabled: true

The main thing I’ve left out here is the cache expiry time.  The Symfony 1.4 cache.yml reference lists all the additional options available in this context.  In most cases, this may be the only documentation you will end up having to read.  Otherwise, that’s it!  We can thank the clever folks over at the Symfony project for making this so easy!  This is also a good opportunity to see the neat cache highlighting offered by the Symfony toolbar.

SOAP and Using it in a Component

I’m going to first take a moment to talk about SOAP in general.  That way if you’ve just discovered you have a project that must use SOAP or are getting started with SOAP in PHP or Symfony, your landing here will be a bit softer.

SOAP

Most of the time when people talk about SOAP, they are talking about a service, exposed via HTTP that communicates using XML.  There’s one additional facet which is that these services are usually documented by a WSDL file that indexes the available operations, and data types the service offers.

To many PHP programmers, SOAP will seem arcane and convoluted.  Several steps are often necessary just to formulate your request for data and usually there are more steps beyond that to retrieve the actual results.

As frustrating as this is, keep in mind that SOAP was designed with strongly typed languages like Java and .NET in mind.  For them – and even PHP – when exchanging complex data structures, it can be helpful to agree upon a format, and the WSDL file does exactly that by incorporating a schema along with the service definitions.

This also has the added benefit of allowing SOAP client libraries to automatically generate the services based on the WSDL file, shaving quite a fair bit off of development time.  As a good exercise, grab the latest copy of Netbeans and check out the services tab.  You’ll see that with no effort from you, Netbeans can index and call against the service with only the WSDL file!  If you’re really new to all this, I do recommend that you try it to better understand the next section.

SOAP and Symfony Components

Using SOAP from Symfony is a matter of becoming familiar with PHP’s SOAP extension and then understanding where to design it into your application.  With most SOAP services, you will be responsible for assembling requests for data, fetching the data as well as managing a session token that is returned with every response.

Thankfully, you’re not going to have to work with XML directly as the PHP SOAP extension abstracts that and much more away.  Making use of a SOAP service from PHP is a simple matter of instantiating it with the WSDL file (just like in Netbeans!) to generate and configure a local representation of the service.  To use the methods found in the WSDL definition, you just have to call them off of your instance of SoapClient.  It sounds like magic, because in many ways, it is:

Create or edit :  app/yourApp/modules/yourModule/actions/components.class.php
Inside         :  public function __construct()
     $this->soapClient = new SoapClient(
          "http://your_wsdl.wsdl",          // Path to the WSDL Service.
          array(                            // Various options can go here.
               'trace'  => 1,
               'soap_version'  => SOAP_1_1
          )
     );
     // What is stdClass?
     $config = new stdClass();
     $config->username = "some_username";
     $config->password = "some_password";
     $config->apiKey = "usually_provided_to_you";
     $this->session = $this->soapClient->startSession($config);

Depending on the service you are accessing, the last 4 lines of code here may not match up for you, but it’s helpful to see a small example of how things can work.  More importantly however is to learn about stdClass which isn’t documented officially, but is used heavily when working with PHP SOAP.
The interactions I was doing with the SOAP service depended on creating arrays and casting them using SoapVar to the appropriate data type found in the WSDL.  Remember, because PHP is inherently typeless, this step might not occur to you naturally.  Every bit of data you end up transmitting will have to go through something along these lines:

     $request = array(
          'session' => $this->sessionKey
     );
     $request = new SoapVar(
          $request, SOAP_ENC_OBJECT,
          "dataTypeFoundInWSDL",
          "http://service_xml_namespace_goes_here"
     );

Because every SoapClient is different past this point, I can only offer general tips.  For my project, my design approach was to identify the data type that I was after, cleanly obtain the data and then make it available to my template.  The private methods I created on my instance of sfComponents focused on encapsulating the various operations while simultaneously managing the session token.  Down to the point where my action code was just a matter of calling $this->getTheDataTypeIWant(); and then passing that on to my template.

Conclusion

As with all solutions, one will always think about ways the job could have been done better:

  • For the original design that I didn’t use, I had some reservations about putting SOAP calls in the table class.
  • Further to the previous item:  For the design I did end up using, I still wasn’t 100% confident with puting SOAP calls inside of private methods in my sfComponents class.
  • I would have liked to have spent more time preparing the returned data as arrays rather than having my template access the members of an anonymous instance of stdClass.

Making use of SOAP from PHP and Symfony is easy enough and the only major challenge is getting the design right in your application.  Creating the service and making use of it is as simple as knowing where the WSDL file is and the benefits from there are obvious once you get going.

You’ll notice however that the advantages all center around the use of the WSDL file and not the use of SOAP.  Using XML to exchange data – especially over the internet – can be controversial as it tends to eat up a lot of resources everywhere it goes.  It’s even worse on mobile devices when this excess costs precious battery life!

This is in contrast to JSON which has become a fast friend of the internet because it is simple, inexpensive to parse and readily usable by the vast majority of clients as it is a subset of JavaScript.  For those interested, keep an eye on WSDL 2.0 and JSON Schema.

Tags: , , , , , , , , ,

One Response to “Symfony 1.4, Component Caching and SOAP”

  1. Jonathan DartNo Gravatar says:

    Syfmony’s 1.4′s caching system is really nice. Despite all its flaws, it’s a great framework.

Leave a Reply