I used the WebORB for PHP Web application server, when I wrote the InsideRIA article titled Photo Gallery Mate Framework, With Photo Caching. The thrust of the article was about a photo gallery written in Flex 3. I had to modify the internals of the WebORB for PHP Web application server in order to make the Adobe Action Message Format 3 (AMF 3) photo data remote messaging transfer from the PHP server to the Flex client work properly.
The detailed and involved modifications of WebORB for PHP internals were part of the article along with a larger more involved set of “how to” information on my blog. Since publishing this article, I have replaced using WebORB for PHP Web application server with the Zend Framework Zend_Amf class for Adobe Action Message Format 3 (AMF 3) client / server messaging transfers. I accidently discovered a way to transfer photo data using the PHP Zend_Amf class, which works without modification of the AMF 3 data streaming internal code. This is the first PHP centric AMF 3 based server that I am aware of where I did not have to modify the internal PHP code for server to Flex client photo data transfers.
I thought it best to share this information with by describing the problem, how you can easily work around it, show how you can use this information, and to provide a server side update to my Photo Gallery Mate Framework, With Photo Caching article. I have another article about using the Zend Framework titled Flex 4 / PHP Web-Centric Solutions that I will be addressing in more detail later in this article. I hope that this information helps you as it has for me by making PHP centric photo data transfers using AMF 3 messaging much more easy to perform.
PHP Server to Client Photo Transfers—The Issue
Have you ever-wondered why you mostly see Flex client example code where the photo display galleries are rendered using the ActionScript 3 (AS 3) Loader.load (request:URLRequest, context:LoaderContext=null) class.method? There’s another way to render photos in a Flex client gallery using the AS 3 Loader.loadBytes(bytes:ByteArray, context:LoaderContext=null) that you see used to a lesser degree. Why is this? There are a couple of valid reasons. First, using a URL, whether it is photos included with the Flex client package or remotely from a Web server, making a simple HTTP calls to load the photo is a snap. Second, photo files are stored as bytes of data and not a convenient AS 3 ByteArray data type.
For my photo gallery needs AS 3 Loader.load class.method URL HTTP calls to load photo data into a Flex client does not cut it. Here are my reasons:
- Photo loading is slow: one photo (image) at a time, per HTTP request.
- Difficult to manage photo resources via a folder of photos or folder hierarchy of photo folders.
- No photo metadata (keywords, and captions) directly managed and linked with individual photos.
- Cannot search for and retrieve photos for photo gallery rendering based on the photo’s metadata.
Instead, if you use AMF 3 remote messaging via AS 3 RemoteObject the binary format is significantly faster than any HTTP photo request. Additionally AMF 3 messaging provides mechanisms to transfer arrays of photos with one remoting call. So the transfer rate of gallery photos occurs an order of magnitude faster than with a group of on-at-a-time URL HTTP calls. But wait, there’s more. You need a Web application server such as Adobe BlazeDS, (Java), Adobe ColdFusion, or PHP based app server (from a choice open source options) for remote messaging via AS 3 RemoteObjects. Oops, all of a sudden more development effort is required for the server-side. Yeah, no wonder that you see so many more use examples of AS 3 Loader.load class.method URL HTTP calls to load photo data.
Lets suppose that you decide that using a remote Web application server photo data repository is worth the effort to take advantage of a more interactive photo gallery solution. And by using AMF 3 remote messaging you desire to return photos as AS 3 ByteArray data type for Flex client rendering using the AS 3 Loader.loadBytes class.method. Returning AS 3 ByteArray photo data to the Flex client, in arrays, is fairly straightforward using either of the two Web application servers Adobe BlazeDS or Adobe ColdFusion. This is because both servers intrinsically support a byte type easily converted into an array of bytes (AS 3 ByteArray) via data assignment, and then arrays of photos via programmatic looping.
For photo data transfers, this is not so true and easy when using a PHP Web application server, as there is no such thing as a byte data type within the programming language. Yes but, PHP has a String data type and the photos are simply retrieved from the relational database server as a String, which is actually an array of bytes. Send an array of photo objects to the Flex client—arrays of arrays of strings present a problem, as PHP and Flex disagree as to their data type. PHP insists that photos have a String data type format and allows no other data type, even if force-cast. Flex prefers, and actually insists on, receiving photos as (AS3) ByteArray object data type. Simply put, PHP photo String and Flex photo ByteArray objects are not compatible in any way.
By now, you are probably wondering why this won’t work. The PHP photo String is returned to the Flex client and you should be able to cast the photo String object to an AS 3 ByteArray object using an assignment cast notation. Many of you have found out through countless hours of effort that this does not work. You end up stymied and wonder were to turn next—even wondering why this does not work despite all upside down coding chicanery you can muster to try.
Let’s discuss the “why” of the issue. You need to know this so you are never trapped again or even a first time by this issue. The AS 3 String data type represents a sequence of 16-bit characters. AS 3 Strings are stored internally as Unicode characters, using the UTF-16 format. Strings are immutable values, just as they are in the Java programming language. An operation on a String value returns a new instance of the String. Have you guessed the issue by now? The PHP photo data String when cast to an AS3 ByteArray defaults the String source—as UTF-16 Unicode characters—when assigning to the AS 3 ByteArray destination. What does the rendered photo display look like? Answer: random garbage.
By now, you are assuming that the PHP-based app server (from a choice of several open source options) will not transfer photos from a server-based photo database repository to the Flex client using AMF 3 remoting messaging. You could make this work by some code translation complexity within the PHP Web application server’s AMF 3 data serialization objects. It is not easy to do. One simple code error breaks all operations and the required code modification needs to be again reverse-engineered for each new release of the Web application server.
I even published a few “how to” articles per the PHP app server code modifications over the past couple years. Recently Zend added an AMF 3 serialization and deserialization data stream module to the Zend Framework. Additionally Adobe tightly integrated the Flash Builder 4 IDE with automated access to the ZendFramework Web application server. Integrating the Flex client to PHP server is now a relative snap. For details, see my O’Reilly InsideRIA article titled Flex 4 / PHP Web-Centric Solutions.
The good news is that the photo PHP String to flex client AS 3 ByteArray translation is handled transparently within the ZendFramwork and it’s most easy to implement. I don’t have to write any more “how to” articles per the PHP Web application server code modifications. The bad news is that what you need to do to make this PHP server-to-client photo transfer work has not been publically documented—at least from what I have researched so far. Hence this article, where you will find the solution to “The Issue” is quite simple.
My hat is off to both Adobe and Zend for providing a photo gallery transfer solution that has nagged us PHP server side developers for several years.
PHP Server to Client Photo Transfers—The Solution
This section is about how the photo PHP String to flex client AS 3 ByteArray translation is handled within the Zend Framework AMF 3 data transfer.
First, lets start by taking a look a look at a PHP class I doubt that you are familiar with. See Listing 1, which is a copy of a file named ByteArray.php, found inside the Zend Framework at the folder data path hierarchy of: ~/ZendFramework/library/Zend/Amf/Value
Listing 1: PHP Class: Zend_AMF_Value_ByteArray as ByteArray.php file
Note that the ByteArray.php file contains a PHP class named Zend_Amf_Value_ByteArray with one object method named getData. The protected $_data object property is set any time the object is instantiated from this class. There is no other way to set the protected $_data object property other than instantiation of the class into an object.
For a moment, lets hold on to how this PHP class is used as an object for AMF 3 photo data transfers to first run a PHP test script named ByteArrayCallExample.php in order to observe the operation of the Zend_Amf_Value_ByteArray class. Our PHP test script is shown next in Listing 2.
Listing 2: PHP Script: ByteArrayCallExample.php
This PHP test script includes the Zend_Amf_Value_ByteArray class contained in the ByteArray.php file on line #2. Our simulated photo data—a short dummy test string—is assigned into the $photoData variable at line #4. Line #5 instantiates the Zend_Amf_Value_ByteArray object and assigns the $photoData variable to the object’s $_data protected property while the object is being instantiated.
Purposely, there is no way to rewrite the object’s $_data protected property value after object instantiation. You can though, read the object’s $_data protected property by calling the object’s getData method. This is what is performed in the example line #6 and the result is assigned to the $photo_Data PHP variable.
The balance of the example PHP code, in lines #8, #9, and #10, displays the results of our example using the var_dump() PHP debugging function call to display our PHP code operation results. Listing 3 shows the output of our example code generated from the example’s lines #4, #5, and #6 PHP code and is discussed next.
I used PHP echo calls followed by the var_dump() PHP debugging function to produce the results shown in Listing 3. It is worth noting that the var_dump() PHP debugging function displays the variable’s data type followed by the actual value data.
Listing 3: Run script output from: ByteArrayCallExample.php
There are three lines of resultant output test data defined by Listing 3 and numbered as 1, 2, and 3 respectively. The summary description of the resultant out data follows:
- Identifies that our simulated photo data test data is a String of 36 bytes.
- Shows the object pointer is a Zend_Amf_Value_ByteArray object and its protected _data property contains a String of 36 bytes. (Assigned from $photoData at object instantiation time.)
- Show that the return of the _data property contains a String of 36 bytes from the getData object method call.
Now imagine wrapping our server-side photo data occurring as a PHP String data type inside of a Zend_Amf_Value_ByteArray object. We then pass this object to the Zend_Amf object call of the Zend Framework for transfer to the Flex client. The Zend_Amf class object prepares to AMF 3 serialize format the data for transfer to the Flex client. The Zend_Amf class must look for the data type for each portion of data structure arriving from the server-side data repository via a PHP services class.
Zend_Amf recognizes all the base PHP data types and also with a special addition of Zend_Amf_Value_ByteArray object data type. When this object type is recognized Zend_Amf extracts the $photoData String from the object using the: Zend_Amf_Value_ByteArray->getData(); method call , which serializes the data by placing an AMF 3 ByteArray Type header on the PHP String photo data. The AMF 3 serial data stream is then passed to the Flex client where the AMF 3 ByteArray Type is deserialized into an AS 3 ByteArray object for rendering using the AS 3 Loader class.
Figure 1 shows the photo data flow from the server database repository via Web server and the ZendFramework Zend_Amf class. We start with Photo data as a PHP String from the Photo Database Repository and the Photo data ultimately shows up on the Flex client as an AS 3 ByteArray data type. As a photo gallery developer you only need to deal within your PHP services class on the Web server side.
Figure 1: Run script output from: ByteArrayCallExample.phpYou write your server-side PHP services class to transfer a photo or an array of photos to a remote Flex client photo gallery. As usual, your PHP code—there are many examples available, see next section—reads the photo or photos from the Photo Database Repository. You need to make one additional change to your PHP services code. That is to pass your photo data from your PHP services object to Zend Framework Zend_Amf class as a Zend_Amf_Value_ByteArray object.
That’s about all there is that is new to transfer photo data from the server to the client. I will show some code examples and a way to deploy a working photo gallery where you can evaluate and view its operation.
PHP Server to Client Photo Transfers—Code Test Run
Requirements
Adobe Flash Builder 4—formerly Flex Builder 3 (includes the Flex 4 SDK)Eclipse-based development environment for Flex. Supports visual and code-centric development, code hinting, visual debugging, and so forth. Includes the Flex 4 SDK and Flash Player 10
- Try - 60 days
- Buy
- Note: This article’s RIA solution is also buildable using Adobe Flex Builder 3.x
The Flex SDK is the foundation of Flex, providing the core Flex compilers, component library and debugger. Using only the free SDK and an IDE of your choice, you can build and deploy rich Flex applications. Learn more about the Flex Open Source project.
PHP (both workstation and production server deployment required)
Web Server (both workstation and production server deployment required)
- Apache HTTP Server
- Alternately Microsoft IIS Web server (preinstalled with Windows XP or 7 Pro)
Zend Framework (Either Full or Minimal download will meet your needs)
Example files
- Flex 4 - PHP Data-Centric Photo Transfers.zip (ZIP, 65 KB)
PHP Code Overview
Listing 4 provides selected code excised from one of my photo gallery server-side PHP services. The PHP while loop is packaging arrays of photos and their respective photo metadata into an array of SQPhoto objects. Each time through the while loop a photo data and metadata is read from the Photo Database Repository, a new SQPhoto object and the actual photo String data is packaged into the object’s imageBA object property as Zend_Amf_Value_ByteArray object data type. The assignment is shown in line #6 of Listing 4.
Listing 4: Photo Data Transfer from Database To Zend_Amf Class
The above coding scenario is all that is required to perform the photo data server to Flex client transfer. Really not much extra work providing you are using the Zend Framework for your PHP Web application server. If you are inclined to want to build and run an example photo gallery, then continue on with the next section, Build and Deploy a Working Photo Gallery, otherwise good-luck with coding your own Flex/PHP centric photo gallery solutions.
Build and Deploy A Working Photo Gallery
Our working photo gallery example code will be drawn from the latter two of my previous O’Reilly InsideRIA four articles, shown below. While not related to what I’m going to talk about in the following photo gallery discussion, the first two articles are here for your reference.
- AMF3 PHP Server Objects to Flex Client Object Relational Mapping
- Processing AMF 3 PHP Server Object Arrays on the Flex Client Using Object Relational Mapping
- Photo Gallery Mate Framework, With Photo Caching
- Flex 4 / PHP Web-Centric Solutions
Follow the following procedural steps to create and deploy a working photo gallery example. You will use both code and information from the above two articles, Photo Gallery Mate Framework, With Photo Caching and Flex 4 / PHP Web-Centric Solutions.
- Create a folder named SQGallery in the root of your workstation Web server.
- Create the photo gallery Web server environment and the shared Zend Framework Web application server by following the instructions in the Web Application Server PHP Data Services Layout and Environment section of the Flex 4 / PHP Web-Centric Solutions article.
- In particular this means following the instructions in the Server: Using the PHPFrameworks WEB-INF/SiteGenScripts to establish the PHP files in the SQGallery folder in order to establish the connections from the Flex client to the just deployed shared Zend Framework
- The Zip file from the above Example files, Flex 4 - PHP Data-Centric Photo Transfers.zip contains a services folder. Copy (move) this services folder to the SQGallery folder in the root of your workstation Web server.
- This PHP services folder contains a slightly modified version of the PHP services from the Photo Gallery Mate Framework, With Photo Caching article. Specifically, three lines of code were modified as follows:
- GetSQPhotos.php, line #47
- SearchSQPhotos.php, line #99
- SQPhotosPaged.php, line #96
- Install the MySQL photo database using a schema file and the photo content data. The Zip file download from Example files, Example Photos Database.zip, in the Photo Gallery Mate Framework, With Photo Caching article contains the photo database schema file and the photo content data. There is a text file in this Zip download package titled, “Creating the Propagating the SQPhoto Database.txt,” which describes how to create the photo database table from the schema file and install the photo and photo metadata into the database repository.
- Also see The Server Side PHP Code, MySQL Photo Repository section of the Photo Gallery Mate Framework, With Photo Caching article for information about the photo database.
- Last, deploy the Flex 3 project into Flex Builder 3 or Flash Builder 4. The Flex 3 client install files you need are in the Zip download from Example files, SQGallery.zip in the Photo Gallery Mate Framework, With Photo Caching article. You can read about the Flex 3 client in The Photo Gallery Maté Framework section of the Photo Gallery Mate Framework, With Photo Caching article.
- You should now be ready for a Flex client build and review run of the SQGallery photo gallery example.
