Mar 202008

Jonathan Street has posted an article called Is PHP good enough for science? where he asks if anyone has experience with PHP in scientific contexts. I think PHP easily could be used to automate tasks, but I’m not aware of any toolkits or frameworks created for this purpose. Anyone seen anything like this around? If so, drop him a line.

[tags]PHP[/tags]

Mar 182008

Hia there. I’ve now moved my old blog to a self-hosted domain. This was mainly done to be free of the constraints that the wordpress hosting lays on you. As you might have noticed I’m experimenting with Google Adsense on various parts of the site. I’m sticking to text-only ads, and I’m trying to make them as non-intrusive as possible. If anyone has feedback or comments on this, I’d really like to hear from you.

Also, all code is now syntax highlighted :)

This post is pretty much a revamp of a previous post called “Working with X-Fire soap services and inheritance in PHP“. That title was a bit misleading, and not really that good when it came to providing a sample.

Let’s say we have a SOAP method called createCustomer(Customer c), and we have a base class called Customer, which has to subclasses, Person and Organization. Person has firstname, lastname, while Organization as orgname and orgid. Now, the createCustomer call accepts a object of the class Customer, and any derived classes.

When retrieving a Person / Organization over SOAP, PHP automatically creates instances of the correct classes, but when calling createCustomer, passing a Person / Organization it breaks. Out object is sent as a Customer, but with Person or Organization fields added. The SOAP server expects to find a xsi:type for the object we are sending to tell what kind of Customer it is. It seems like PHP does not set this itself (maybe it should?).

I spent quite some time looking for info on how to specify the xsi:type for the objects, and I finally came across SoapVar.

I created a base class which the SOAP classes extended. A method called pack is responsible for setting xsi:type.

(I’m very aware that my pasted code looks like a mess in this blog. I will fix that ASAP).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
class BaseClass{
  private  $namespace = "http://model.api.domain.com"; // from your WSDL
  protected function pack($obj){
    $class_name = get_class($obj);
    $namespace = "http://model.api.domain.com";
    $pack = new SoapVar($obj, XSD_STRING, "$class_name", $namespace);
    return $pack;
  }
}
 
class createCustomer extends BaseClass{
  public function setCustomer($customer){
    $this->customer = $this->pack($customer);
  }
}
 
$customer = new Person();
$customer->setName("John Doe");
 
$request = new createCustomer();
$request->setAccountID(123);
$request->setCustomer($customer);
 
$client->createCustomer($request);

That fixed the problems for me atleast.

PS: If your SOAP classes are prefixed you’ll need to strip the prefix in class_name when creating the SoapVar.

Related posts:

[tags]PHP, SOAP[/tags] 

Update:

I guess I didn’t make the purpose quite clear here. This method will allow you to show custom error messages when PHP hits a fatal error. The shutdown function will always run.

Scripts tend to die, and that’s not usually nice. We do not want to show the user a fatal error nor a blank page (display errors off) . PHP has a function called register_shutdown_function which lets us set up a function which is called at execution shutdown. What this means is that our function will be executed when our script is done executing / dying and PHP execution is about to shut down. By setting up a variable to false at the start of our script, and setting it to true at the very end of the script we can have our shutdown function check if the script completed successfully or not. If our variable is still false we know that we never made it to the last line of our script, hence it died somewhere. I’ve prepared a very basic sample which shows how you can give the user some proper feedback if a fatal error should arise. You’d want to turn of display of fatal errors for this to look nice.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$clean = false;
function shutdown_func(){
  global $clean;
  if (!$clean){
    die("not a clean shutdown");
  }
}
 
register_shutdown_function('shutdown_func');
 
$a = 1;
$a = new FooClass(); // will fail with fatal
 
$clean = true;
?>

As you can see, the shutdown_func prints something if the clean variable isn’t set to true when the shutdown function runs. This should of course be wrapped in a class (and NOT use globals), and for something more usable I recommend checking EZ Components way of doing this.

This is a follow up to my post about array problems with SOAP and PHP. The scenario was that when an array with only one object was returned over SOAP the array was discarded and pointed straight to the single object.

Cmm was kind enough to tip me this PHP bug report, which explains that this is actually not a bug, but a feature.

To get arrays containing one single element, simply create the SoapClient as follows:

1
$x = new SoapClient($wsdl, array('features' => SOAP_SINGLE_ELEMENT_ARRAYS));

Related articles: