New PHP Features in Flash Builder 4 - Part 2: Using Zend AMF and Flash Remoting
Join the DZone community and get the full member experience.
Join For FreeThe first of this three part series provided an overview of the new data-centric PHP development features in Flash Builder 4. This part looks at using Zend AMF and Flash Remoting.
If you have been integrating Flash and PHP for a while, it is likely that you have used Flash Remoting, or just "remoting", at some point along the way. Remoting leverages HTTP, just like the previous XML example, but serializes the raw data structures into a binary format called AMF. The result is a much smaller data packet going across the wire. AMF is also natively recognized by the Flash Player, so getting the data off the wire and into memory is also extremely efficient.
This ultimately translates into a much more scalable solution - especially as data load increases. It also means less development time writing the code necessary to expose an existing data access tier as XML character data. In order to gain this efficiency however you must be using PHP objects on the server. You also need to have a library on the server that can translate the incoming AMF into PHP data types, and outgoing PHP data types into AMF.
In 2009 Adobe worked closely with Zend to provide a modern, scalable implementation in the form of Zend AMF for PHP developers.
In my experience there is some confusion here as to how much of the Zend Framework you need to use. The Zend Framework has many different features, not the least of which is a robust MVC architecture. If you are already using another framework however, then you may be reluctant to jump ship and abandon your existing code base. The good news is that all that is needed to take advantage of remoting, is to have the Zend Framework available to your server. You don't need to use the Zend MVC component to gain the benefit of Zend AMF - just be using PHP objects.
Back in Flash Builder, along the top of Data/Services panel, on the right side is a set of icons. The third icon in has a tooltip of "Connect to Data/Service" which will present the same dialog we saw earlier. This time however, select the "PHP" option and then click on the "Next" button. Here you will be prompted to enter a service name, just like before. If you are already using PHP objects, then you can browse to that object directly.

Also notice however that there is the option to generate a sample PHP class as well. Even if you are already using PHP objects, even if you are already using remoting, and even if you are already using Zend AMF, I suggest that at some point you take the time to run through the wizard with the option to generate the sample class at least once. The stub code you will get in return is all but complete, nicely commented and very usable. The code also includes some specific method signatures you may not be used to seeing that we will find very useful in a moment. In the meantime, here is the PHP code for the object I will be using for this example.
<?php
include "Person.php";
class CensusService
{
public $host = "localhost:8889";
public $user = "root";
public $password = "root";
public $db = "demo";
private function connect()
{
mysql_connect( $this -> host, $this -> user, $this -> password );
mysql_select_db( $this -> db );
}
public function getAllItems()
{
$this -> connect();
$sql = "SELECT * FROM census";
$result = mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
$census = array();
while( $row = mysql_fetch_assoc( $result ) )
{
$person = new Person();
$person -> id = $row["id"];
$person -> age = $row["age"];
$person -> classofworker = $row["classofworker"];
$person -> education = $row["education"];
$person -> maritalstatus = $row["maritalstatus"];
$person -> race = $row["race"];
$person -> sex = $row["sex"];
array_push( $census, $person );
}
return $census;
}
public function getItem( $itemId )
{
$this -> connect();
$itemId = mysql_real_escape_string( $itemId );
$sql = "SELECT * FROM census WHERE id = $itemId";
$result = mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
$row = mysql_fetch_assoc( $result );
$person = new Person();
$person -> id = $row["id"];
$person -> age = $row["age"];
$person -> classofworker = $row["classofworker"];
$person -> education = $row["education"];
$person -> maritalstatus = $row["maritalstatus"];
$person -> race = $row["race"];
$person -> sex = $row["sex"];
return $person;
}
public function createItem( Person $item )
{
$this -> connect();
$sql = "INSERT INTO census VALUES ( " .
"'" . $item -> age . "', " .
"'" . $item -> classofworker . "', " .
"'" . $item -> education . "', " .
"'" . $item -> maritalstatus . "', " .
"'" . $item -> race . "', " .
"'" . $item -> sex . "', " .
"NULL )";
mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
return mysql_insert_id();
}
public function updateItem( Person $item )
{
$this -> connect();
$sql = "UPDATE census SET " .
"age = '" . $item -> age . "', " .
"classofworker = '" . $item -> classofworker . "', " .
"education = '" . $item -> education . "', " .
"maritalstatus = '" . $item -> maritalstatus . "', " .
"race = '" . $item -> race . "', " .
"sex = '" . $item -> sex . "' " .
"WHERE id = " . $item -> id;
mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
}
public function deleteItem( Person $item )
{
$this -> connect();
$sql = "DELETE FROM census " .
"WHERE id = " . $item -> id;
mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
}
public function count()
{
$this -> connect();
$sql = "SELECT * FROM census";
$result = mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
$count = mysql_num_rows( $result );
mysql_free_result( $result );
return $count;
}
public function getItemsPaged( $startIndex, $numItems )
{
$this -> connect();
$startIndex = mysql_real_escape_string( $startIndex );
$numItems = mysql_real_escape_string( $numItems );
$sql = "SELECT * FROM census " .
"LIMIT $startIndex, $numItems";
$result = mysql_query( $sql ) or die( "Query failed: " .
mysql_error() );
$census = array();
while( $row = mysql_fetch_assoc( $result ) )
{
$person = new Person();
$person -> id = $row["id"];
$person -> age = $row["age"];
$person -> classofworker = $row["classofworker"];
$person -> education = $row["education"];
$person -> maritalstatus = $row["maritalstatus"];
$person -> race = $row["race"];
$person -> sex = $row["sex"];
array_push( $census, $person );
}
return $census;
}
}
?>
<?php
class Person
{
public $id = 0;
public $age = "";
public $classofworker = "";
public $education = "";
public $maritalstatus = "";
public $race = "";
public $sex = "";
}
?>
When you have selected an object and then click the "Next" button, you will get a prompt to have Flash Builder install Zend Framework on your system if it is not already present. This takes just a few moments, and does not do much more than drop an additional directory in the web root. It is not particularly invasive, and very easy to undo (delete the directory), so if you have not yet given Zend AMF a chance, this would be a great opportunity to take a look. Once the deployment is complete, you will also get some extra information about custom configuration if you are so inclined.
At this point in the wizard Flash Builder shows us the methods it found, which we can use to confirm that we selected the right object. When you click the "Finish" button, you will again be presented with the reminder to setup your data types. The workflow is very similar to what we did with the HTTP service, so I will not repeat it here. With a return type configured, you can drag a method from the Data/Services panel to a data list control and be on your way viewing data from your objects.
In the third and final part of this series, we will look at how Flash Builder 4 is pushing new boundaries with features such as implicit paging and data management.
Opinions expressed by DZone contributors are their own.
Comments