I just came across a annoying “feature” in Zend Studio. In the project I’m working on I have branches, trunk and export/releases. The workspace I set up in Zend uses the root folder as project directory so I can easily browse all branches and trunk. I’ve been working in trunk all day, adding type hinting and documentation for several classes, but when I got around to actually using the classes the auto-completer didn’t find the additions I had made. After checking around a bit I found out that Zend reads the folders alphabetically, so when I was working in trunk Zend got the auto-completer data from branches. Nice to know.

May 242007

I spent some time figuring out how acegi tokens works and how to use them with Prado in PHP. An acegi token is a hash-key-ish token that you can use to identify yourself with a web service instead of signing on with user-name and password for every page load. The way this works is as follows:

1.) First time, sign in with username and password
2.) Soap server returns a ageci token and sets in in a cookie on the soap client
3.) Grab the token and store it across page requests.
4.) All subsequent calls, set the token in the soap clients cookies.

The token stays the same across the whole session. I’ve experienced two different behaviours when it comes to returning the token. Some services returns the token with each response, while other services only return the token on the first call and sends null in the subsequent calls. There is one exception to the first, and that’s when I encounter soap-faults. The token seems to be null with those no matter what.

It took me some time to get this right. I had never worked with acegi tokens until last week, so I was pretty much blank on the topic. Google didn’t offer much in terms of samples with PHP.

When a user signs on for the first time I connect to the web service in the user login method in the Prado user-manager. I make sure the token is returned and I store it a field in the user object. The token is encrypted, but I do some extra magic to make sure everything is as secure as possible. The token is then serialized and stored with the Prado user object. On page load I make sure to retrieve the token from the current user and set it for the service. This is done in the preRunService method in a custom TApplication class.

It’s been a few days since I got this implemented now, and everything seems to work very well. It’s nice to have the extra layer of security so the user-name and password can be used once and then thrown away.

I’ve got a upcoming project that requires some complex interaction services and I’m looking around for frameworks that suits my needs. Almost everything I develop gets done using the Prado Framework. The AJAX support in Prado is pretty new (at least for the 3.x version), so I’ll probably need something that offers more in terms of integrated services and controls. Prado supplies some of the underlying features, but I do not have the time to re-invent several wheels. I know that there are plans for new ajax features and controls in Prado 3.1, but I can’t sit around waiting for that.

It’s been quite some time since the first time I heard about the Backbase framework. I’ve never gotten around to take it for a spin, but I’ve spent some time reading the documentation and checking out the samples. The Backbase Travel Demo is especially impressive. The controls and widgets that ships with the package are pretty impressive as well. I hope to get time to give it a spin this weekend. If I do I’ll do a short writeup on my impressions and experiences.

I’ve made a profile module for Prado that lets you store user preferences etc in a database. I got the idea from the ASP.net Profile classes (visit) . At the moment the module uses SQL-Lite as storage engine, but I plan on adding support for XML and SQL databases. The module overrides PHP’s “magic methods” __get and __set, which makes access to the keys really easy. I’ve submitted this to the Prado TRAC asking them to add it to the framework. The code could use some cleaning.
Usage:

1
2
$this->Profile->SomeSetting = “some value”; // creates the key SomeSetting for the current user ID with the value “some value”
$foo = $this->Profile->SomeSetting; // retrieves the value of SomeSetting for the current user ID

The first version is available here. I plan on refactoring it a bit to make sure it can be used with different kinds of user setups.

The results for the 2007 PHP-IDE polls are ready. They are available here. The top three are:

1. Eclipse (at 30%)

2. Simple editors (at 26%)

3. Zend (at 25%, my favorite)

I see that Komodo is at only 3% which is a bit surprising. I plan on evaluating that when I get the time. The extension support there is supposed to be as good as Firefox.

I’ve been working with X-fire / ageis services in SOAP now for a while, and there’s been only one issue I’ve not been able to solve. Arrays.

When the back-end send an array with item count > 1 everything works fine. The problems start when there is only one item in the array. The array is collapsed and instead there is a object that is the only item. At first I thought this was the java back-end that screwed up, but after inspecting the SOAP messages from NGREP I found out that it’s PHP that screws up.

I’ve prepared a short example called lookupPerson which takes a username and returns a Person with his related cars.

Consider the first sample, where the person has three cars:

SOAP request:
<pre line="1" lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://api.service.com/temp/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:Service">
<SOAP-ENV:Header>
<ns2:RemoteAddress xsi:type="SOAP-ENC:string">127.0.0.1</ns2:RemoteAddress>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:lookupPerson>
<ns1:in0>john</ns1:in0>
</ns1:lookupPerson>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

</pre>

SOAP response:
<pre line="1" lang="xml">

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<lookupPersonResponse xmlns="http://api.service.com/temp/">
<out xmlns="http://api.service.com/temp/">
<username xmlns="http://users.model.service.com">john</username>
<cars xmlns="http://users.model.service.com">
<Car>
<car>HUMMER</car>
</Car>
<Car>
<car>BMW</car>
</Car>
</cars>
</out>
</lookupPersonResponse>
</soap:Body>
</soap:Envelope>

</pre>

Now that looks pretty much right. Lets take a look at a var_dump of the returned object:

object(lookupPersonResponse)#571 (1) {
["out"]=> object(Person)#570 (2) {
["username"]=> string(11) "john"
["cars"]=> object(stdClass)#573 (1) {
["Car"]=> array(2) {
[0]=> object(Car)#572 (1) {
["car"]=> string(17) "BMW"
}
[1]=> object(Car)#574 (1) {
["car"]=> string(19) "HUMMER"
}
}
}
}
}

Yep. Everything is correct. The class map works as intended. Now, lets get over to the bad stuff. The following output is the same call, but this time John has lost his Hummer.

SOAP response:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<lookupPersonResponse xmlns="http://api.service.com/temp/">
<out xmlns="http://api.service.com/temp/">
<username xmlns="http://users.model.service.com">john</username>
<cars xmlns="http://users.model.service.com">
<Car>
<car>BMW</car>
</Car>
</cars>
</out>
</lookupPersonResponse>
</soap:Body>
</soap:Envelope>

Well, the SOAP response is pretty much like the first one.

PHP object:

object(lookupPersonResponse)#571 (1) {
["out"]=> object(Person)#570 (2) {
["username"]=> string(11) "john"
["cars"]=> object(stdClass)#573 (1) {
["Car"]=> object(Car)#572 (1) {
["car"]=> string(17) "BMW"
}
}
}
}

Do you see the difference here? Car is pointing to the car object instance instead of an array. This lays the path for some ass logic work for everything that returns an array.

Lets take a look at the relevant parts of the WSDL:

<xsd:complexType name="Person">
<xsd:sequence>
<xsd:element minOccurs="0" name="username" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="cars" nillable="true" type="ns1:ArrayOfCar"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfCar">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="Car" nillable="true" type="ns1:Car"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Car">
<xsd:sequence>
<xsd:element minOccurs="0" name="car" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="lookupPersonResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="ns1:Person"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

According to WSDL standard this is legal and should work, but I dont think PHP is too happy about it. I’ve tried doing similar stuff with a service that describes arrays as :


<complexType name="ArrayOf_soapenc_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="soapenc:string[]"/>
</restriction>
</complexContent>
</complexType>

This way seems to work just fine, so I fear that the problem has something to do with X-Fire and ageis. I’m very interested in some hints on how to get this running properly.

I’ve been working on a community tutorial project for a while now. The current “release” is available here. The idea is to create a framework on top of Prado that consists of a set of interfaces, classes, components and services. With this framework people should be able to create services like Facebook, YouTube, Blogs, Online News etc with very little development time.

The main features:
* User management with permissions
* Forum
* Ads management
* Guest books
* Messages between users
* Blog / notes
* Social relations between users
* Themes and localization
* Media albums (music, movies, music)
* File uploads

The current state of the project is that I’ve pretty much set up the user system and the basics like messages and blogs. I’ll be pretty busy with work for the next month, but I also have a project which I need this framework for.. So I’ll try to get some hours each weekend to work on this. I’d really like some comments and suggestions, so feel free to email me or send me a private message on the Prado forums. My user name is eirikhm.

The PradoCamp unconference happening this Thursday from 10:00 to 18:00 at Film- und Medienzentrum Ludwigsburg in Stuttgart, Germany. I unfortunately had to stay at work, but there will be a number of very experienced members from the Prado community such as Knut Urdalen, Carl G. Mathisen and Tobias Munk. If you happen to be in the area, be sure to drop in and have a chat with them.

A while ago we started using X-Fire for soap services. The new soap services we created used inheritance in the returned classes, which wasn’t really that straight forward to implement in PHP. Let’s say we have a abstract class Person, which holds whatever common data we need to have about a person. In addition there are two sub-classes of Person called Runner and Madman. The runner holds info about max speed while the madman has a insanity score (I rock at examples!).

I set up three classes in PHP called MyPerson, MyMadman and MyRunner. MyMadman and MyRunner inherits MyPerson. The class map was set up to map Person to MyPerson, Madman to MyMadman and Runner to MyRunner. This worked like a charm for retriving data that was sent from the backend. A madman came over the wire as a Person with xsi:type set to Madman. The problems started when I was supposed to send a Madman back over soap. Let’s call the method GiveCake(Person p, string cake). The soap side expected any kind of Person to arrive. First I tired just sending a Madman with a delicious cake title, but to my surprise that didn’t work at all. The problem is that the object was sent as a Person with the Madman taggs added, but with no xsi:type to tell the soap server that this in fact was a Madman. After looking all over for hints on how make this work I came across SoapVar. Thef following one-liner solved the problems: $soapObject = new SoapVar($obj, XSD_STRING, “$class_name”, $namespace). Class name is the xsi:tag here.