What is SCA for PHP?Service Component Architecture (SCA) is a technology supporting an idea. The idea in question is a big idea, Service Oriented Architecture (SOA), and which encompasses much more than just a technology. SOA is the idea that an enterprise might want to define their business processes—those that involve people just as much as those that involve IT—and model those business processes, assemble them from reusable components, deploy them, and monitor them, and furthermore that the right building blocks to use are services. A service, in this context, might mean a Web Service or it might not—it can mean almost anything that supports a clear interface that defines verbs, or actions, and messages. There is a tacit acknowledgement that no single technology dominates, and to insist on just one technology, whether it is Web Services, J2EE, message passing, distributed objects or whatever will not work. Large enterprises lready have far too many different technologies in place.
SCA also supports an old idea, that of separation of concerns. The two concerns it separates are those that concern the development programmer, that of building the correct business logic, and those that concern solution architects and the people who have to deploy and look after solutions, that of where services are positioned. SCA keeps business logic separate from what we like to call the ‘wiring’ that connects services together.
So, for example, an important principle in SCA is local/remote transparency—one component can call another without needing to know whether it is calling another component on the same machine, in the same call stack, or whether the other component is halfway round the world and accessible via a web service.
It is hard to make technology simpler by writing more technology, but that is what SCA aims to do; to smooth out the differences between different underlying technologies, by making a service the common building block.
What Does an SCA Component Look Like?Let’s begin with the simplest SCA component we can. The traditional greeting in all branches of computing is “hello, world” so our first component can be one that returns the PHP string containing “hello, world”. See Listing 1.
Listing 1
GreetComponent.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*/
class GreetComponent
{
public function greet() {
return ‘hello, world’;
}
}
?>
Two things identify this otherwise undistinguished PHP class as an SCA component. One is the @service annotation. The other is the
include for “
SCA.php”. In this simple example these do not have much to do. The
include for
SCA.php does contain some executable code, but it only has to do anything when the component is called as a result of web service request and we shall not see this until later.
In due course we are going to add a number of features to this class that make it a more worthwhile component: we shalldefine a second component and make this one use it, we shall make them both generate WSDL so that they can be called via a web service as well as locally, we shall make one of them throw an exception and see how they are handled, and so on. But the first thing to do is to call the component. Let’s see fi rst how we call it from a plain ordinary PHP script. Listing 2 holds a script that does just that.
Listing 2
client.php
<?php
include ‘SCA/SCA.php’;
$service = SCA::getService(‘./GreetComponent.php’);
echo $service->greet();
?>
First, we use the static method
SCA::getService(), passing it a path to the component. The path can be either absolute or relative. If it is relative, it is resolved relative to the location of the script that issues the
getService() call, and not against the PHP include path. We do this for a reason that will become clearer when we consider how calls are made to remote components.
getService() returns a proxy for the component. This is an instance of SCA_LocalProxy, which we always call the local proxy. It is in fact half proxy and half wrapper, as it contains within itself an instance of the component we are calling. This is jumping ahead, but the proxy is there to intercept all calls and ensure that all arguments are copied and only copies are passed to the component, so that pass-by-value is assured, regardless of what the component tries to do with the arguments. We do this because we want the calling behaviour to remain the same regardless of whether a component is being called locally or remotely. Further, when the component is called remotely, pass-by-value is more or less the only possibility. Hence we also enforce it when the call is local. If we now execute the script it will duly call the component and echo the return as follows:
hello, world
Now to add a second component. Suppose for some unaccountable reason we want the greeting reversed to read “dlrow ,olleh”, but do not feel like calling the PHP function strrev() for ourselves. We might want a component to do it for us. Of course in any sensible real world application we would be calling a component to do something more meaningful: authorising a credit card, logging a transaction, telling the warehouse to dispatch something, or whatever.
The new component, ReverseComponent, is shown in Listing 3.
Listing 3
ReverseComponent.php
<?php
include_once ‘SCA/SCA.php’;
/**
*@service
*/
class ReverseComponent
{
function reverse($in)
{
return strrev ($in);
}
}
?>
You will see that in structure it is more or less identical to our first component. The only difference is that the single method also takes a parameter. Incidentally this is the second time we have showed you a component that has just one method, which has a close kinship with the class name.
This is just a consequence of the fact we are looking at simple examples. To be clear, components can have many methods, and none of them need to be related to the name of the component.
Now let us make the first component call the second. This is component GreetComponent2, which is shown in Listing 4.
This has introduced a reference to a component reference and the annotations that defi ne it. The @reference indicates that the instance variable that follows is a proxy for another service, which must be initialised before the business logic in the greet() method can be called. This is done automatically by the executable code within SCA.php, which inspect the class, finds any such dependencies and initialises them. The @binding.php annotation indicates how the service is to be found and follows the same rules we saw for getService() previously, that is to say that relative paths are allowed and if present will be resolved relative to this component, not the PHP include path. This gives a degree of location independence to cross-component references. You will see this grouping of @reference, @binding plus an instance variable again; it is the required pattern for adding a dependency on another component.
Listing 4
GreetComponent2.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*/
class GreetComponent2
{
/**
*@reference
*@binding.php ReverseComponent.php
*/
public $reversing_component;
public function greet()
{
return
$this->reversing_component->reverse(‘hello, world’); }
}?>
We will need a second client script to call GreetComponent2 this time, otherwise we are fi nished. See Listing 5.
Listing 5
client2.php
<?php
include ‘SCA/SCA.php’;
$service = SCA::getService(‘./GreetComponent2.php’);
echo $service->greet();
}?>
To summarise, we have a client script that gets a proxy for an SCA component. This first component declares a dependency on a second component. During initialisation, an instance variable within the component gets initialised to a proxy for a second component that is used by the business logic. Running the client of course produces the desired result:
dlrow ,olleh
So far all the calls have been local. If we were to breakpoint the ReverseComponent::reverse() method and inspect the call stack in a debugger, we could see the client script has called a local proxy that has called greet(), which has in turn called a second instance of the local proxy, which has called reverse().
Our First Remote Component
Now I’ll show how to get the components to expose a web service binding. Almost all the work is done for you: you have to add some annotations and copy the script where you want it to go under the web server, and that is all. Listing 6 shows the component annotated to become a web service, GreetComponent3.
You will see two changes. The @binding annotation indicates that the service is to expose a web service binding. Our rules are that all components have a local binding automatically but other bindings (of which @binding.ws is currently the only example) must be asked for explicitly. Secondly we now need some more detail about the interface to the component. Some we can derive, but some has to be supplied. All public methods are automatically part of the interface and these can be found by refl ecting on the class but the types of any arguments and return value must be specified, so that SCA can generate the right types in the WSDL. In this case there is only the one return type so there is only the @return annotation. When you add a web service binding to the reverse component you will also see the @param annotation to define the type for a parameter.
Listing 6
GreetComponent3.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*@binding.ws
*/
class GreetComponent3
{
/**
*@reference
*@binding.php ReverseComponent.php
*/
public $reversing_component;
/**
*@return string (Our greeting)
*/
public function greet()
{
return $this->reversing_component->reverse(‘hello, world’);
}
}
?>
Once we add these annotations, the component is able to generate its own WSDL. We request the WSDL by placing the component somewhere under the document root of a web server— wherever we expect it to reside when executed—and sending it an HTTP GET request with a parameter of Web Service Definition Language (WSDL) by putting ?wsdl on the end of the URL of the component. For example, if the component is directly under the document root of the server running at www.example.com we could enter into a browser http://www.example.com/GreetComponent3.php?wsdl. This would generate and return the WSDL to our end and also cache it at the far end, in the same directory, so that we could then also retrieve it later with the URL http://www.example.com/GreetComponent3.wsdl. Note the difference—?wsdl is a parameter to the script; .wsdl is the extension of a separate file.
It is the executable code inside SCA.php that actually generates the WSDL, of course. This detects the HTTP GET request and the ?wsdl parameter and responds by loading the class, inspecting the annotations, and generating and returning the WSDL.
So, all you have to do to deploy the component as a web service is to add the needed annotations and copy the component to the right place under the web server.
Listing 7 includes the WSDL that would be generated for the class so far.
There are several things to point out in this WSDL.
The first is that we generate WSDL in the document-literal/ wrapped style, where the method name to be called is included as a top-level element in the message. We can see this in the element defi nition that reads <xs:element name=“greet”> early on in the schema section. This is just one of several ways to write WSDL, but this style has the advantage that the message formats are described very explicitly within the schema section at the top, and in principle the messages can be verified against the schema. Document/literal wrapped style WSDL is WS-I compliant and is increasingly common.
Much of the rest of the WSDL is fairly ordinary but there is something to say about the location attribute. The rest of the WSDL is all determined once the annotations have been added but the value here—http://www.example.com/GreetComponent3. php—cannot be decided until the moment the WSDL is generated, because it depends on the location of the component.
Finally you will see that at the very bottom there is a distinctive comment that identifi es that this is WSDL for an SCA component. As you will shortly see it is quite possible for an SCA component to consume any web service and not just another SCA component, but we can handle errors differently if we know that both ends are SCA components; this comment lets a component know if the service it is using is also a component.
So we have deployed the component as a web service and generated the WSDL. How do we now call it?
We were calling the service by obtaining a reference with getService() and this is what we continue to do, but now that we want to call the component as a web service we specify the location of the WSDL file rather than a PHP script. client3.php is shown in Listing 8.
Here we have pointed directly at the WSDL where it has been cached on the server. We could have, if we had preferred, obtained a copy of the WSDL, saved it locally, and pointed at that instead. client4.php is shown in Listing 9.
Once again the path can be absolute or relative. Relative paths are interpreted as relative to the script containing the call, using the debug_backtrace call. This is different from the normal PHP behaviour which is to interpret relative paths as relative to the PHP current working directory, which is usually the location of the first script that was called. However, we do it so that relative paths are resolved in the same way whether they are for local calls, where we specify a PHP class, or for remote calls where we specify a WSDL file. It is also in keeping with RFC 1808 that describes how relative URLs should be interpreted.
Whichever WSDL we point getService() at, what we get back is a reference to a proxy, but this time to an instance of SCA_SoapProxy, which we always call the Simple Object Access Protocol (SOAP) proxy. This contains within it an instance of the PHP SoapClient, which SCA has initialised with the WSDL. Most of the hard work of performing the web service call will be done by the SOAP extension.
Listing 7
GreetComponent3.wsdl
<?xml version=”1.0” encoding=”UTF-8”?>
<defi nitions xmlns=”http://schemas.xmlsoap.org/wsdl/” xsi:
type=”tDefi nitions” xmlns:tns2=”http://GreetComponent3”
xmlns:tns=”http://schemas.xmlsoap.org/wsdl/” xmlns:tns3=”http://
schemas.xmlsoap.org/wsdl/soap/” xmlns:xsi=”http://www.
w3.org/2001/XMLSchema-instance” targetNamespace=”http://
GreetComponent3”>
<types>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
targetNamespace=”http://GreetComponent3”>
<xs:element name=”greet”>
<xs:complexType>
<xs:sequence>
</xs:sequence></xs:complexType>
</xs:element>
<xs:element name=”greetResponse”>
<xs:complexType>
<xs:sequence>
<xs:element name=”greetReturn” type=”xs:string”/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</types>
<message name=”greetRequest”>
<part name=”greetRequest” element=”tns2:greet”/>
</message>
<message name=”greetResponse”>
<part name=”return” element=”tns2:greetResponse”/>
</message>
<portType name=”GreetComponent3PortType”>
<operation name=”greet”>
<input message=”tns2:greetRequest”/>
<output message=”tns2:greetResponse”/>
</operation>
</portType>
<binding name=”GreetComponent3Binding” type=”tns2:
GreetComponent3PortType”>
<operation name=”greet”>
<input>
<tns3:body xsi:type=”tBody” use=”literal”/>
</input>
<output>
<tns3:body xsi:type=”tBody” use=”literal”/>
</output>
<tns3:operation xsi:type=”tOperation” soapAction=””/>
</operation>
<tns3:binding xsi:type=”tBinding” transport=”http://schemas.
xmlsoap.org/soap/http” style=”document”/>
</binding>
<service name=”GreetComponent3Service”>
<port name=”GreetComponent3Port” binding=”tns2:
GreetComponent3Binding”>
<tns3:address xsi:type=”tAddress” location=”http://www.
example.com/GreetComponent3.php”/>
</port>
</service>
</defi nitions>
<!-- this line identifi es this fi le as WSDL generated by SCA for PHP.
Do not remove -->
SCA Components Can Call Plain Old Web Services, and Vice Versa
The fact that the SOAP proxy contains an instance of the SOAP client under the covers introduces a new possibility. Because the SOAP extension can call any web service, getService() can be used to obtain a reference to any web service for which you have the WSDL, and not just WSDL generated by SCA components. Unless errors occur, or we want to pass data structures between services, the SOAP proxy keeps out of the way and just forwards the calls to the SoapClient. Incidentally the SoapClient has useful methods that allow you to get hold of the last SOAP request and SOAP response, and the SOAP proxy has the same methods to allow you to get these.
Just as you can use getService() to get a proxy for a web service that is not an SCA component, if an SCA component is deployed and exposed as a web service it can be called by any client PHP script, including one that knows nothing about SCA and did not use getService(). So we might call GreetComponent3 by using the SoapClient directly as follows. Listing 10 shows client5.php, the first script that does not include SCA.php and need not know anything about SCA.
In fact, the client program might not even be a PHP script. However, if you are not used to WSDL written to document/ literal wrapped style, the result might surprise you. Notice that we do not echo the result from the SOAP client directly but instead the greetReturn property. If you var_dump the return value from this call to the SOAPp client what you will see will be:
object(stdClass)#2 (1) {
[“greetReturn”]=>
string(12) “dlrow ,olleh”
}
The SOAP client has returned to us the wrapped response.
To ensure that SCA components works the same regardless of whether the calls are local or remote, the SCA soap proxy, which knows the name of the relevant property, removes this layer of wrapping and returns just the string to the client.
Listing 8
client3.php
<?php
include ‘SCA/SCA.php’;
$service = SCA::getService(‘http://www.example.com/
GreetComponent3.wsdl’);
echo $service->greet();
?>
Listing 9
client4.php
<?php
include ‘SCA/SCA.php’;
$service = SCA::getService(‘GreetComponent3.wsdl’);
echo $service->greet();
?>
Listing 10
client5.php
<?php
$soap_client = new SoapClient(‘./GreetComponent3.
wsdl’,array(‘trace’ => true, ‘exception’ => true));
echo $soap_client->greet()->greetReturn;
?>
Two Remote Components
To complete the picture let’s take a look at how one SCA component calls another via a web service. First let’s make the reverse component expose a web service binding, which we do by adding the @binding, @param and @return annotations. The result, ReverseComponent2.php, is shown in Listing 11.
Now we want to make the greet component make use of it. We use an annotation to define the target WSDL. Further, for web service bindings, we use @binding.ws, this time for the reference. So suppose that the reverse component is hosted at www.example2.com. You would obtain its WSDL by sending it a ?wsdl request in the same way you saw before. To cache the wsdl you can cache it where the greet component could fi nd it (we last left the greet component on www.example.com). Our changed greet component, GreetComponent4 is shown in Listing 12, which assumes the WSDL for the reverse component is cached locally in the same directory.
If we now generate the WSDL for GreetComponent4 and call it with a client, it will return the same reversed string that we have seen repeatedly. In the process it will have performed two Web Service calls—one from the client to GreetComponent4, and one from GreetComponent4 to ReverseComponent.
Interlude
Let us step back a moment and see what we have achieved. We have seen a client program use SCA::getService() to get a proxy for a local component, which in turn uses @binding.php to get a proxy for a second local component. In case it is not clear, the rule is that in a component the way to obtain a proxy for another component is through an annotation, whereas in a client program that is not a component and has no annotations you must use getService().
You have also seen how, if the components are annotated in the right way, they will generate WSDL on demand, and can be called via web service requests. So we showed the two components both local, and both separated, and the only changes we needed to make when we moved the components were the ‘wiring’ lines—the arguments to getService() or the @ binding annotations within the components. We did not need to change the business logic in any way, trivial though it might have been.
Some might say, “But you did have to change the files themselves.” This is true. As we worked on the SCA for PHP project we decided that we wanted no separate artefacts—no side files, no confi guration files, no generated code. The only generated artefact is the WSDL. We also considered that given the fact that PHP scripts are interpreted and do not need a recompile when changed, changing an annotation within a PHP script is hardly very different from changing a line in a configuration file.
Listing 11
ReverseComponent2.php
<?php
include_once ‘SCA/SCA.php’;
/**
*@service
*@binding.ws
*/
class ReverseComponent2 {
/**
*@param string $in
*@return string
*/
function reverse($in)
{
return strrev ($in);
}
}?>
Listing 12
GreetComponent4.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*@binding.ws
*/
class GreetComponent4
{
/**
*@reference
*@binding.ws ./ReverseComponent2.wsdl
*/
public $reversing_component;
/**
*@return string (Our greeting)
*/
public function greet()
{
return $this->reversing_component->reverse(‘hello, world’);
}
}}?>
It is more important that the wiring and the business logic are logically separated although they are in the same file—the wiring in annotations and the logic in PHP code.
For comparison, the Java and C++ versions of SCA take a different approach. They use a separate confi guration file to contain the wiring information. This is written in XML and is conceptually the same information that we have in annotations, but held in one place.
Before we move on and look at two more virtues of SCA, consider also that SCA allows a component to be called via a web service from a script that is not a SCA component, and allows our components to make use of web services that are not SCA components. This is an acknowledgement that although SCA components might find themselves operating in a ‘safe’ environment where they only connect to other SCA components, this cannot be relied on—and is probably even unusual. There is an edge to the ‘safe’ world. Furthermore, although the SCA for PHP project can only cope with local and web service calls at the moment, there is no reason in principle why other bindings should not be possible to connect to other non-SCA services—perhaps to services supplied by AtomPub, a feed from RSS, a web site organised according to the REST style, and so on.
Now let’s complete the survey of SCA for PHP by looking at two other aspects—how errors and exceptions are handled and how data structures can be passed.
Errors and Exceptions
SCA defines an SCA_RuntimeException and uses it to signal most sorts of error—problems if there is a mistake in an annotation, for example. Much more interesting is what happens to business exceptions thrown by a component.
Suppose that the greet() method does not want to greet the world but instead remain mute and throw an exception instead, where elsewhere we have defined a GreetException as extending the PHP Exception class. See Listing 13.
When our client program calls greet() locally, the local proxy that we create does not attempt to catch any exceptions. So if the greet() method throws an exception it will be passed straight through to the caller.
Listing 13
GreetComponent5.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*@binding.ws
*/
class GreetComponent5
{
public function greet()
{
throw new GreetException();
}
}
?>
What happens when the call is remote and both caller and called programs are SCA components? On the far end of the call the incoming web service request goes first to an instance of SCA_ ServiceWrapper, which does surround the call to the component with a try/catch block. As a consequence it does catch the exception. It serialises it and returns it to the calling end in a SoapFault. There the serialised exception is extracted from the SoapFault, deserialised and re-thrown, so the client code can catch it, and will see the exception looking the same as it was if it were thrown locally; for example, the getFile() and getLine() methods on the exception will refer to the original location of the error, in this case within the greet() method. The only proviso is that the calling end must have access to a definition of the exception—an include fi le for the exception, probably—else, it will not de-serialise correctly.
In this way exception behaviour is largely the same regardless of whether calls are local or remote. Further, this works regardless of how far down a chain of calls the exception is thrown—exceptions are serialised, returned, de-serialised, re-thrown at each stage in a chain until it reaches a catch block that accepts it, just as it would be for local calls.
Data Structures
So far the parameter and return types for the two components have been PHP strings. They could equally well have been the other PHP scalar types—float, integer or Boolean, or could be also be Null. They cannot however be arrays or PHP objects. SCA has a different method for dealing with data structures. SCA takes advantage of another project, Service Data Object (SDO), to handle data structures. SDOs are a generalisation of the data transfer object pattern. An SDO is a PHP object that has properties, with values, much like a one-level associative array. The properties of an SDO can contain PHP scalar values, or references to other SDOs, to form nested structures. In SDO terminology this is a data graph. It contains much the same sort of information that one could build with nested associative arrays, or store as an XML document.
SCA uses SDOs as the arguments and return values when data structures are needed. The SDO project already provides substantial support for serialising and de-serialising SDOs, converting SDOs to and from XML, and for exchanging SDOs between different programming languages, making SDOs an obvious choice for exchanging data structures between components.
Let’s look at an example. We will have a client program calling a component as before, but this time the component will implement a directory lookup. We will pass a person’s name to the component and get back in return a single SDO with some data about that person. The SDO will have just three fields—their name, place of birth, and data of birth. This is just about the simplest example possible; of course, in a more complex example both the arguments and return values might be more complex and interesting data structures. See Listing 14.
The client passes a name and gets back an SDO whereupon it prints the three fi elds. See Listing 15. As you can see, this is a pretty rudimentary lookup routine that only knows the details of one person.
Unlike associative arrays, which are more or less unconstrained, SDOs are created according to a model or schema. An SDO model defi nes a set of types, and a set of properties for each type. Some of those properties will be simple types like strings and integers, and some will be references to other SDO types. So for any given application, this model defines the sort of data graphs that can be constructed.
Listing 14
personclient.php
<?php
include ‘SCA/SCA.php’;
$lookup_service = SCA::getService(‘LookupComponent.php’);
$person = $lookup_service->lookup(‘William Shakespeare’);
echo “$person->name was born on $person->dob, at$person-
>pob\n”;
?>
For SCA components, the usual way to specify the model is with an XML schema file, specifi ed on the @types annotation. All SDOs have both a type and namespace, and the @types annotation in our lookup component says that defi nitions for any of the types in the namespace PersonNamespace will be found in the person.xsd schema file.
The model needs to be loaded into something that will act as a data factory, which will construct SDOs according to the model. For our component here this special object is the SCA class itself: when the component calls SCA::createDataObject (‘personNamespace’,’personType’) the SCA class examines the annotations within the component, finds any with a matching namespace, loads the schema files that defi ne the to build the SDO model, and then creates the person SDO with the correct set of properties.
The XML schema file that defines the SDO model is as shown in Listing 16.
SDOs can also be created by proxy objects. For example, had we had an interface that we needed to pass a person object into a method on the lookup service (so that we needed to create an SDO in the client) we could have used the reference we obtained from getService() to create an SDO, rather than the SCA class.
Although in this example we defined the SDO according to an XML schema, they are not XML objects in themselves— they are just capable of modelling and making available in memory the sort of structured data that when stored would likely be stored in an XML document. SDOs are deliberately intended to be independent of how or where the data might have been stored. So, data in a relational database for example can be made available to a program as SDOs just like XML data. Used as data transfer objects by SCA components is a natural use for SDOs; almost what they were designed for.
Listing 15
LookupComponent.php
<?php
include ‘SCA/SCA.php’;
/**
*@service
*@types PersonNamespace person.xsd
*/
class LookupComponent
{
public function lookup()
{
if ( $name == ‘William Shakespeare’) {
$person = SCA::createDataObject(‘PersonNamespace’,’p
ersonType’);
$person->name = $name;
$person->dob = ‘April 1564, most likely 23rd’;
$person->pob = ‘Stratford-upon-Avon, Warwickshire’;
return $person;
} else {
return null;
}
}
}
?>
Listing 16
person.xsd
<?xml version=”1.0” encoding=”UTF-8”?>
<schema xmlns=”http://www.w3.org/2001/XMLSchema”
targetNamespace=”PersonNamespace”
xmlns:personNS=” PersonNamespace”>
<complexType name=”personType”>
<sequence>
<element name=”name”
type=”string”></element>
<element name=”dob”
type=”string”></element>
<element name=”pob”
type=”string”></element>
</sequence>
</complexType>
</schema>
Futures
The journey does not end here. SCA for PHP is still under active development. For example, by the time you read this, we hope to have demonstrated binding to REST-style services using both JSON and XML messages. This would be implemented as a new @binding annotation.
We welcome involvement from the PHP community. The current code-base is available on the Open SOA (OSOA) site[1]. Here you will also find the documentation and samples. The OSOA site is our main site for SCA and SDO work, both for PHP and for other programming languages. We also have an active PHPSOA Google group[2] where we discuss SCA or SDO for PHP.
It is our sincere wish that you will find something of interest, something of use, and perhaps get involved and help us drive where SCA for PHP goes!