New Zend Amf with 10x Performance Boost

Wade just blogged about a patch that was submitted by Mark Reidenbach to Zend AMF that provides a 10x performance boost over the old one. This isn’t a final release and everyone is still making sure the patch hasn’t introduced any new bugs so he’s encouraging everyone to download this one and make sure it works correctly. If you have issues, add it to the current open bug.

From Wade’s post:

Thanks so much Mark! I have also added a reference check optimization that uses SPL_object_hash to quickly see if an object has been seen before or not. Overall you should see a big performance increase. The test case I used was the James Ward’s census data from my ZendCon talk which consists of random people objects ranging from 1 – 100 duplicates totaling 5k total rows. Xdebug profiling analyzed by KCacheGrind showed roughly a 10X increase in performance!

Mapping Data Types from PHP to Flex with Zend AMF and Flash Builder 4

I assume this has to be out there somewhere but I couldn’t find it so hopefully this helps someone who Google’s things the same way I do. And Wade has a great tutorial for doing this when you’re just dealing with the Zend AMF code but I was looking for something that worked with Flash Buidler 4’s wizards.

While using the Flash Builder 4 data-centric design wizards to generate the service calls for a PHP class I was having trouble figuring out how to make sure that the data types I had set up in my MySQL database were being carried all the way through to my Flex application. When I retrieved data from the database in PHP and then had Flash Builder 4 inspect my class, the properties of my returned class were all strings.

If you use the data-centric design wizards to create a class based on a database, the class properties are typed correctly. If you use a class you’ve already written, all of the properties come back as strings. Luckily I chatted with our Flex/PHP guru, Mihai Corlan, and he pointed me in the direction of type casting.

Essentially you just need to add a bit of extra data when the properties are returned in the class so that Zend AMF knows what type of data to expect. So for my getAllItems() method, I iterate through the records of my database and create a PHP object for each one.

As you can see in the code below, to return as an int, just add a 0, to set it as a number, add 0.0, to set it as a date, just create a new DateTime object with the data from MySQL. As you can see from the Mapping Table you’ve got coverage for pretty much every data type.

public function getAllForests()
{
$this->connect();
$rs = mysql_query("select * from national_forests")
or die ("Unable to complete query.");
 
$national_forests = array();
 
while( $row = mysql_fetch_assoc($rs) )
{
$forest = new NationalForest();
$forest->id = $row['id']+0;
$forest->state = $row['state'];
$forest->area = $row['area']+0.0;
$forest->established = new DateTime($row['established']);
$forest->closest_city = $row['closest_city'];
$forest->name = $row['name'];
 
array_push($national_forests,$forest);
}
 
return $national_forests;
}

If there’s a better way to do this, I’d love to have it.

Flex and PHP: Authentication With an HTML Login Page

One of the first things to think about when building a Flex application is how you’re going to do authentication. Most people seem to include a username and password box in Flex and then make an HTTPService or AMF call to pass the authentication credentials. But I hate that solution. Most major browsers now have support to save usernames and passwords with autocomplete and that’s become something people expect from their logins. I think it’s also important to be able to clear the “remember me” cookie just like any other cookie as opposed to having it saved in a Flash cookie. Whenever you can provide the behavior people expect from their browser, you should.

So in this example I’m going to show how you might implement an HTML form with PHP for a Flex application. As I’m new to PHP there may be some bad practices here but I’ll update the post as I get feedback.

Creating the login page in PHP and HTML

To start, we can just use PHP’s built in session functions to create the session variables and build the login page called login.php. You start off by creating a session with session_start() and then you set some session variables to their defaults. Then you’ll show the username and password fields only if the form hasn’t been submitted and use the $_SESSION variables to store the information from the user. Finally, when everything is authenticated you use the header() function to send the user to the Flex application.

<?php
session_start();
$_SESSION['logged_in'] = false;
$_SESSION['username'] = "";
 
if(isset($_POST['is_submitted']))
{
$username = $_POST['username'];
$password = $_POST['password'];
 
// If the "Remember my username" box is checked
// then we use the setcookie function to save it.
// Otherwise, we clear it out. 
if($_POST['keep_username'] == true)
{
setcookie("username",$username,time()+36000);
} else {
setcookie("username");
}
 
// This is where you would look up the username
// and password. Normally this would be an LDAP call
// or a query to a database. In this case, I'm just
// accepting everything.
if($username && $password)
{
// Set our session variables.
$_SESSION['logged_in'] = true;
$_SESSION['username'] = $username;
 
// Redirect to the Flex application
header("location:flex/index.php");
} else
{
echo "Go back and put in a username and password.";
}
} else {
?>
 
<form name="login" action="<?php$_SERVER['PHP_SELF'] ?>" method="post">
Username: <input type="text" name="username" value="<?php echo $_COOKIE['username']; ?>" /><br/>
Password: <input type="password" name="password" /><br/>
Remember my username: <input type="checkbox" name="keep_username" value="true"><br/>
<input type="hidden" name="is_submitted" value="true" />
<input type="submit" value="Submit" />
</form>
 
<?php
}
?>

Notice the keep_username checkbox above. If the user checks that, you use the setcookie() method to create a cookie that will store the username on the next visit. If it is unchecked, the username will be blank.

Setting up the Flex Project

Even though most Flex applications take up the entire page, nearly all of the time you embed the actual SWF file on an HTML page. In Flash Builder when you create a new Flex application in creates the SWF files and the HTML files for you that embed your application. To do that it uses a template file that you can find in the html-template folder of your project. If you haven’t done so yet, go ahead and create a new Flex project. Use the defaults (do not use PHP as the server, leave it at None/Other). When you get to the second screen, set the output folder to a subdirectory named “flex” in the directory where your login.php file is located.

With the project created the first thing you’ll want to do is edit the template file. Go into the html-template directory and rename index.template.html to index.template.php. That will let you run PHP code inside of the template file. Flash Builder will automatically create an index.php file in the flex folder you specified in the create project wizard. Next you need to make sure your application will use the right file when you run or debug it. Right click on your project, select properties, and then select Run/Debug Settings. Now select your project in that box and click the “Edit” button. On the next screen, uncheck “Use default” in lowest box and put in the path to your application. You can see mine below (I’ve got http://localhost:8888 mapped to http://rainier.cascade.mtn but your local PHP server will probably use http://localhost).

Modifying the Index Template

Next you need to edit the template we just renamed. Open it up in Flash Builder (or your favorite text editor) and you should see a bunch of HTML. At the very top of that page you’re going to add some PHP code. First, you are going to check for a url parameter of logout to be passed. If it is, you destroy the session and log the user out. If that isn’t passed, you’re going to use the session information from your login page and save that information to variables on this page. This code goes at the very top before all of the HTML in your template page.

<?php
// Always start the session first.
session_start();
 
// You will also use this page to log out. If 
// ?logout=1 is passed in the URL, destroy the 
// session and log the user out.
if(isset($_GET['logout']))
{
if($_GET['logout'] == 1)
{
$params = session_get_cookie_params();
setcookie(session_name(),"", time()-3600,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]);
session_unset();
session_destroy();
}
}
 
// Create the default values for our session.    
$session_id = "";
$logged_in = false;
$username = "";
 
// If the session is valid, replace the default
// values with our session values.
if($_SESSION['logged_in'] == true)
{
$logged_in = true;
$session_id = $_COOKIE['PHPSESSID'];
$username = $_SESSION['username'];
?>

Now that your variables are set, you’ll send those to the Flash Player. There are a number of ways to get data into your Flex application but the most straight forward is to use a concept referred to as “flashvars”. Flashvars are parameters you can put within the embed code that will then be accessible by the Flex application. Flashvars are a great way to take a dynamic site, like one written in PHP, and change the behavior of a Flex or Flash application based on that dynamic PHP data. Look for the JavaScript in the template that includes var flashvars = {} and replace it with this code.

var flashvars = {session_id:"<?php echo $session_id; ?>",
logged_in:"<?php echo $logged_in; ?>",
username:"<?php echo $username; ?>"};

That code will make those three variables available to your Flex application. That way before you let the user do anything in your Flex application you can check to make sure the user is logged in correctly.

Finally, at the end of the template you’ll add some code to show the user an error message if they try to access the page without logging in.

<?php
} else {
echo "Not authorized, go back and log in.";
}
?>

Creating the Flex Application

In this example you’ll just create a very, very basic Flex application with two states, a beginning state and a logged in state. When the application loads, check the flashvars you added to the embed code and then change to the logged in state. In the logged in state also contains a button that uses the logout functionality you added to the template code. Here’s the whole Flex application.

<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600" currentState="startingScreen"
creationComplete="application1_creationCompleteHandler(event)">
 
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
 
protected function btn_clickHandler(event:MouseEvent):void
{
navigateToURL( new URLRequest( encodeURI("index.php?logout=1")), "_self");
}
 
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
if(this.parameters.logged_in == 1)
{
currentState = 'loggedIn';
}
}
 
]]>
</fx:Script>
 
<fx:Declarations>
<s:State name="startingScreen" />
<s:State name="loggedIn" />
</fx:Declarations>
 
<s:Panel name="Test" left="25" right="25" top="20"
bottom="25" title="My Application">
<s:Button id="btn" left="10" top="10"
click="btn_clickHandler(event)"
label="Log Out" includeIn="loggedIn" />
<s:Label id="lbl" left="10" top="10"
text="You need to log in"
includeIn="startingScreen" />
</s:Panel>
 
</s:Application>

Conclusion and Warnings

There are a couple of notes and warnings about this method. By using two states and checking the login parameters you aren’t just depending on the embed code. That means if someone browses right to the SWF file they won’t be able to access the application because it won’t move to the next state unless it gets those parameters. That’s also part of the problem in this very simple application.

In the Flex code that changes the state I just check to see if the flashvar logged_in is set to 1. If you were to download a local version of the PHP file as well as the SWF and change that embed code you’d have access to the application. In a more robust example you would want to add a couple of hooks into the database. One way to do that would be to store the session id and the username in the database in the login.php file. Then when your Flex application loaded you could make a call to another PHP page and pass the session id and username parameters to a function which would compare it to the session and username that were stored during login to make sure it matches up.

You might also want to implement a token system with a shared secret which is a good way to authenticate against external APIs, the kind that you would create in PHP and consume in a Flex application using AMF or REST.

So keep in mind that this isn’t ready for production. But hopefully it gets you started in the right direction when creating a PHP/Flex application that is going to use an HTML login form. The fewer Flex/Flash login forms there are the better.

Great webinar on using ZendAMF with Flash Builder 4

Ok when I say great I may be a little biased because I’m the one who presented it, but nonetheless I think it came out great. The main reason for this is that all of the demos and features worked smoothly without any hiccups. In this one hour session I cover the basics of using the new data features in Flash Builder 4 to install and utilize the ZendAMF library for PHP. The examples show how easy it is now to retrieve and display database content without writing even a single line of code. Go on over and watch it and let me know what you thought of it.

Lee

Configuring Eclipse PDT and Flash Builder 4 Plug-in for PHP/Flex development

In this tutorial I will explain how to configure development environment to work with PHP and Flex projects in one tool. In order to do that I will use Eclipse PDT 2.1 (PHP Eclipse plugin), Flash Builder 4 Plug-in Beta 2 and latest Eclipse IDE for Java EE Developers package which is eclipse-jee-galileo-SR1-macosx-carbon (of course […]

Webinar: using PHP and Flash for developing Rich Internet Applications

On December 2nd, together with Roy Ganor from Zend Company, I will host an e-seminar about PHP and Flash Platform. We will show you how you can create a Rich Internet Application using the Flex framework, Illustrator, Flash Catalyst, and Flash Builder 4. Then we will show you how to connect the Flex application to […]

PHP and Flex Webinars

Last week I visited Zend headquarter and I have an interesting talk over there. One effect of this meeting is this: we will start to do webinars together with Zend.
If you want to find more about Zend Studio and other products related to PHP from the Zend Company, or about the integration between the Flash […]

ColdFusion versus PHP – Uploading a File

I spent part of my vacation digging into PHP. I’d like to be much savvier with PHP because we’ve seen a big chunk of Flex adoption from the PHP community and I’d like to be able to talk to those developers more intelligently. Unfortunately my server-side programming chops are very, very rusty. I started out as a ColdFusion developer and I’ve been able to play with some of the new stuff in ColdFusion 9 but I haven’t built a real CF app in a long time. So I thought I’d do a bit of a comparison and I’ve started doing simple things in PHP and then replicating them in ColdFusion. The first one is file uploading.

Disclaimer: I’m assuming there are things I’m doing wrong. File uploading is fairly basic, but part of the reason I want to blog the basic stuff is so people can let me know where I’m messing up and what I could do better. So flame on in the comments.

The Code Comparison

PHP – file_upload.php

<body>
<?php
ini_set('display_errors',1);
error_reporting(E_ALL | E_STRICT);
 
if(isset($_POST['submitted']))
{
if( move_uploaded_file($_FILES['myfile']['tmp_name'], "{$_FILES['myfile']['name']}") )
{
print '<p>It verked!</p>';
} else {
print '<p>Problemo!</p>';
}
print_r($_FILES);
}
?>
<form action="upload_file.php" enctype="multipart/form-data" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
<p><input type="file" name="myfile" /></p>
<p><input type="submit" name="submit" value="Upload" /></p>
<input type="hidden" name="submitted" value="true" />
</form>
</body>

ColdFusion – file_upload.cfm

<cfifisDefined("form.submitted">
<cfset currentPath = getCurrentTemplatePath()>
<cfset currentDirectory = getDirectoryFromPath(currentPath)>
<cffile action="upload" nameconflict="overwrite" filefield="form.myfile" destination="#currentDirectory#/coldfusion.gpx"/>
<cfif cffile.filewassaved eq true>
<p>It verked!</p>
<cfdump var="#cffile#"/>
<cfelse>
<p>Problemo!</p>
</cfif>
</cfif>
<body>
<formaction="upload_file.cfm" enctype="multipart/form-data" method="POST">
<p><inputtype="file" name="myfile" /></p>
<p><inputtype="submit" name="submit" value="Upload" /></p>
<inputtype="hidden" name="submitted" value="true" />
</form>
</body>

Thoughts

I thought it was interesting how PHP and ColdFusion differ in the actual upload mechanism. Both of them just upload the file to a temporary location but then how the programmer deals with it is different. With PHP, you “move” the file to a location of your choice with the move_uploaded_file method. With ColdFusion you use cffile but call the upload attribute instead of the move attribute. That’s why you don’t put # signs around the form.myfile attribute because the upload function in cffile uses the POST info and that filefield attribute to to the moving/copying behind the scenes. Not sure which one I like better.

A few other bits. One, ColdFusion seems to give way, way more information about the file you’ve uploaded. I don’t know if there is a way to get that kind of detail from PHP, but with ColdFusion I get a bunch of attributes like filewassaved, fileexisted, filewasappended, serverfileext, serverfilename etc. Some of that I can parse from the PHP information, like the file name and file extension, but others, like if it was overwritten, or if the file already existed, don’t seem possible to get with PHP. Two, it is really, really annoying to use a relative file path with ColdFusion. The move_uploaded_file function uses a relative path so it’s easy to upload it to the same directory. With ColdFusion, it’s a pain which is why I had to set a couple of extra variables. Also, PHP seems to love to check that you’re below the max file size. You have to set one in your php.ini file and then send it again as a hidden form field. That seems completely redundant and I can’t figure out why they do that.

Like I said above, this is supposed to be a pretty basic example because I want to know if I’m doing something stupid. If so, or if you have any additional info on my thoughts above, let me know.

Why ColdFusion is worth its money

I’m currently installing this new dedicated RackSpaceCloud server. While I have fallen in love ColdFusion in the last year or so, I am still a CF n00b and not ready to completely switch. So my new server needs both ColdFusion (for new projects) and PHP (mainly for my WordPress blog).
After I installed Apache, MySql and PHP, […]