Welcome back for part 2 of building a login box using Flash Builder 4, PHP, and mySQL. In this tutorial we will connect the application to the database using FB4′s built-in data-centric development tools using PHP. What we are looking to accomplish is:
1. Create a User in the database using the registration form
2. Connect the login form to the database to check credentials before allowing login
3. Provide custom alerts for the application to communicate with the user
To get started, the first thing you’ll need to do is get the app to communicate with the MySQL database using FB4′s built in data-centric development features. By entering a few basic paramters, FB4 will generate the middle-tier (PHP) and Actionscript code for get, create, delete, and edit to make this communication possible. However, the one we’ll focus on in this tutorial is create. FB4 has many cool features built right in, which make data connection a breeze. If you have not had the opportunity to get familiar with the DCD features of Flash Builder 4, I encourage you to read my entry titled Data Centric Development with Flash Builder 4 – http://blog.anaara.com/archives/295.
Creating the Database
Lets get started creating a new database for the application by logging into your local server (eg. MAMP) or your hosting provider’s server control panel. Assuming that you have phpMyAdmin available to use and a database administration interface, login and create a new database. Click on the Query tab and copy and paste the SQL statement shown below into the query box. Once you click “Go” you will have created a table called “users” in your database and have two records.
CREATE TABLE `users` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`user_type` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `users`
--
INSERT INTO `users` VALUES(1, 'testUser', 'testuser@email.com', '123456', 'user');
INSERT INTO `users` VALUES(2, 'testAdmin', 'testadmin@email.com', '098765', 'admin');
Now, go back to Flash Builder, select the Data/Services tab, and click “Connect to Data/Services”. Choose “PHP” and click “next”. Now choose the link labeled “click here to generate a sample”. It will then prompt you to install ZEND AMF if you have not already done so.
Once Zend has installed successfully you will tell FB4 how to connect with your database. This information will be used to generate the PHP code. After you enter the information, hit “Next”, and then “OK” on the Security Warning alert box.
Note: if you are using MAMP, go to the MAMP startup page to get your settings.
Once you have completed these steps, the PHP page that was generated by FB4 will be brought up in your default PHP or text editor.
Everything that you need to be able to connect to the database for the registration page has been completed for you now by Flash Builder, but you still have some work to do. Switch over to design view and select the “register” state if you are not there already. Once you are there, click on the “Data/Service” Tab and follow the steps below.
1. Highlight createUsers(item:Users):int
2. Click the “Generate Form…” button. This button is located at the far right of the “Data/Services” tab.
3. When the “Generate Form” window opens, uncheck the “Form for return type” check box and click “Next”
4. In the properties column click the arrow to expand the item
5. What you will see is a list of what FB4 is going to create for you in the generated “Create” form. For this example, you are not interested in “id” because it is set to auto-increment in the database, and “user_type” because you are going to have that auto inserted by flex later. So, go ahead and uncheck those two boxes.
6. Click “Finish”
You now have a choice here: 1) You can delete the form that you created in the first section as well as the “Save” button and drag the generated form into the Panel (which is probably the easiest), or 2) you can use that information to make what you originally created on the canvas work and then delete the generated form and button. The choice is up to you, but in this tutorial, I will do it the second way because it allows us to better inspect what is being created by FB4.
From here you are going to switch over to source view so that you can make the next set of changes.
Editing the Create Form
The goal here is to combine TextInput field properties using the “id” and “text” properties of the generated code and the includeIn property of what you originally created. As far as the button goes, you’ll want to keep the id and click event from the generated button and add it to our button. Also, when you make the change, also change the button id and click event to something more meaningful such as id="saveBtn" and click="saveBtn_clickHandler(event)".
The combination of the two should look something like this:
<s:Label x="10" y="31" text="Username:" includeIn="register"/>
<s:TextInput x="110" y="24" id="usernameTextInput2" text="{users.username}" includeIn="register"/>
<s:Label x="10" y="61" text="Email:" includeIn="register"/>
<s:TextInput x="110" y="54" id="emailTextInput2" text="{users.email}" includeIn="register"/>
<s:Label x="10" y="91" text="Password:" displayAsPassword="true" includeIn="register"/>
<s:TextInput x="110" y="84" id="passwordTextInput2" text="{users.password}" includeIn="register"/>
<s:Button x="10" y="118" label="Save" id="saveBtn" click="saveBtn_clickHandler(event)" includeIn="register"/>
<s:Button x="168" y="118" label="<< Login" click="currentState='loggedOut'" includeIn="register"/>
Now we need to add additional code to the saveBtn_clickhandler that will commit the new record to the database. To do this you need to add createUsersResult.token = usersService.commit(); to the end of the function.
User Alert
Users like to know what is going on rather than guessing, so it is your job as the developer to tell them that their record was added to the database successfully or not. To do this, you will listen for confirmation from the server side, and then show a confirmation message via an Alert box before directing them to the login page. As you may have noticed, FB4 has already added import mx.controls.Alert;, the import statement for Alerts, otherwise you would have to call it manually.
It is now time to place a result event in the call responder associated with create, which for us is <s:CallResponder id="createUsersResult"/>. To do this you change it to <s:CallResponder id="createUsersResult" result="createUsersResult_resultHandler(event)"/>.
What’s cool here is that when you start to type “result” in the CallResponder tag, FB4′s autocomplete will not only find “result” but will also create the result handler for you if you click enter again after it shows you the option for “Generate Result Handler”. After doing so you will see a new function was created that is ready for you to fill in the function’s body. This is where you will tell it to show the confirmation and forward the user to the loggedOut state.
Change From:
protected function createUsersResult_resultHandler(event:ResultEvent):void
{
// TODO Auto-generated method stub
}
Change To:
protected function createUsersResult_resultHandler(event:ResultEvent):void
{
mx.controls.Alert.show('Thank you for registering. You may login now!');
currentState = "loggedOut";
}
Before we wrap up this functionality, there is one last task to complete. You need to specify one additional piece of information to what is being sent to the server when the user clicks “Save” that the user doesn’t get to control, and that is user_type. For that you need to take another look at the saveBtn_clickHandler function and define the user_type. This is done by adding users2.user_type = "user"; Place this line of code directly below where the password is defined. The completed function will look like:
protected function saveBtn_clickHandler(event:MouseEvent):void
{
var users2:Users = new Users();
users2.username = usernameTextInput2.text;
users2.email = emailTextInput2.text;
users2.password = passwordTextInput2.text;
users2.user_type = "user";
createUsersResult.token = usersService.createUsers(users2);
createUsersResult.token = usersService.commit();
currentState = 'loggedOut';
}
It’s time now to test it out, so go ahead and run the application and create a new user. Then go and look in your database and make sure the data you entered was added correctly, and that the user_type is showing as “user”.

Logging In
Now that you are able to create an account, you will create the ability to use your new account to login. Although you have not actually written any PHP code yet, all that is about to change. You have to tell PHP to ask MySQL to check the credentials being sent and give the thumbs up or thumbs down, and also return the user_type. Knowing the user_type will allow you to direct the person logging in to the proper state depending on if they are an admin or user.
First thing is to save the php file somewhere where the services can be called. On my local machine, the path is Applications/MAMP/htdocs/example12-debug.
Open up your PHP editor and create a new file called login.php. Then paste the following code into that file and save it.
login.php
<?php
define( "DATABASE_SERVER", "localhost" );
define( "DATABASE_USERNAME", "root" );
define( "DATABASE_PASSWORD", "root" );
define( "DATABASE_NAME", "example12" );
//connect to the database
$mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD) or die(mysql_error());
//select the database
mysql_select_db( DATABASE_NAME );
//These are the variables that Flex is passing to PHP
$username = mysql_real_escape_string($_POST["username"]);
$password = mysql_real_escape_string($_POST["password"]);
$logincookie = mysql_real_escape_string($_POST["logincookie"]);
//Check the credentials
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_fetch_array(mysql_query($query));
//Output the returned query in XML: If returned false output 0 else output the users id
$output = "<loginsuccess>";
if(!$result)
{
$output .= "0";
}else{
$output .= $result['id'];
}
$output .= "</loginsuccess>";
//Output the User Type
$usrtyp .= "<usertype>";
$usrtyp .= $result['user_type'];
$usrtyp .= "</usertype>";
//output all the XML
print ($output);
print ($usrtyp);
?>
Now with the PHP in place, you can write the client side code that will pass the variables, call the necessary services, and receive the results that are sent back from the server. The steps for this are as follows:
1. Create two new variables to handle the results that will be received back from the server.
private var userid:int;
private var usertype:String;
2. Write a new function which will be called by the HTTPService telling Flex what to do with the results it receives.
private function checkLogin(event:ResultEvent):void
{
userid = event.result.loginsuccess;
usertype = event.result.usertype;
if (userid != 0)
{
currentState = usertype;
}
else
{
mx.controls.Alert.show('Invalid username/password');
}
}
What this says is: If the server returns a user id that is not 0, then go ahead and set the currentState to what the server returns as the usertype, otherwise show an alert to the user stating “Invalid username/password.”
Note: This works because we have conveniently set all users who create an account to “user” for the user_type, and when we created the database we set the admin user_type to “admin”.
3. We need to write the HTTP Service request. This will call your service and also set the variables which we will be passing to the server.
<s:HTTPService id="login_user" result="checkLogin(event)" showBusyCursor="true" method="POST" url="login.php" useProxy="false">
<s:request xmlns="">
<username>
{username.text}
</username>
<password>
{password.text}
</password>
</s:request>
</s:HTTPService>
There are a couple of important things going on here. First, in the opening tag you can see the id of “login_user”, which is how the service will be called by the click event. The result handler is set with result="checkLogin(event)". You also have to declare the type of service call you’re making, and you are also specifying the location of the file. Secondly, the code directly below that is what passes the username and password values from the TextInput fields, which has the ids of username and password respectively.
4. Last but not least, we need to tell the “Login” button to do something different than what it is doing now. Currently, the click event directs us to the “user” state, but now we need it to call the HTTPService to kick start the login process.
Change From:
<s:Button x="10" y="72" label="Login" click="currentState='user'" includeIn="loggedOut"/>
Change To:
<s:Button x="10" y="72" label="Login" click="login_user.send();" includeIn="loggedOut"/>

And that is it. You should now be able to run and test the application in three ways.
1. Login as user – Username: testUser / Password: 123456
2. Login as admin – Username: testAdmin / Password: 098765
3. Login as you – Choose the username and password which you created previously
4. Get declined – choose a username and password different from above and different from the one you created previously
You should see that all is in good working order. At this point your application should look similar to the following code:
<?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" xmlns:valueObjects="valueObjects.*" xmlns:usersservice="services.usersservice.*">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
private var userid:int;
private var usertype:String;
protected function saveBtn_clickHandler(event:MouseEvent):void
{
var users2:Users = new Users();
users2.username = usernameTextInput2.text;
users2.email = emailTextInput2.text;
users2.password = passwordTextInput2.text;
users2.user_type = "user";
createUsersResult.token = usersService.createUsers(users2);
createUsersResult.token = usersService.commit();
currentState = 'loggedOut';
}
private function checkLogin(event:ResultEvent):void
{
userid = event.result.loginsuccess;
usertype = event.result.usertype;
if (userid != 0)
{
currentState = usertype;
}
else
{
mx.controls.Alert.show('Invalid username/password');
}
}
protected function createUsersResult_resultHandler(event:ResultEvent):void
{
mx.controls.Alert.show('Thank you for registering. You may login now!');
currentState = "loggedOut";
}
]]>
</fx:Script>
<s:states>
<s:State name="loggedOut"/>
<s:State name="forgotPW"/>
<s:State name="register"/>
<s:State name="user"/>
<s:State name="admin"/>
</s:states>
<fx:Declarations>
<s:HTTPService id="login_user" result="checkLogin(event)" showBusyCursor="true" method="POST"
url="login.php" useProxy="false">
<s:request xmlns="">
<username>
{username.text}
</username>
<password>
{password.text}
</password>
</s:request>
</s:HTTPService>
<valueObjects:Users id="users"/>
<usersservice:UsersService id="usersService" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
<s:CallResponder id="createUsersResult" result="createUsersResult_resultHandler(event)"/>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Panel width="250" height="200" title="Flex 4 Login Box" horizontalCenter="0" verticalCenter="0">
<s:Label x="10" y="18" text="Username" includeIn="loggedOut"/>
<s:TextInput x="110" y="10" id="username" includeIn="loggedOut"/>
<s:Label x="12" y="47" text="Password" includeIn="loggedOut"/>
<s:TextInput x="110" y="40" id="password" displayAsPassword="true" includeIn="loggedOut"/>
<s:Button x="10" y="72" label="Login" click="login_user.send();" includeIn="loggedOut"/>
<s:Button x="120" y="72" label="Forgot Login Info?" click="currentState='forgotPW'" includeIn="loggedOut"/>
<s:CheckBox x="10" y="101" label="Remember Me" includeIn="loggedOut"/>
<s:Label x="195" y="103" text="Sign Up" click="currentState='register'" includeIn="loggedOut"/>
<s:Label x="10" y="46" text="Email:" includeIn="forgotPW"/>
<s:TextInput x="110" y="39" id="email_to" includeIn="forgotPW"/>
<s:Button x="10" y="72" label="Get Login Info" includeIn="forgotPW"/>
<s:Button x="168" y="72" label="<< Login" click="currentState='loggedOut'" includeIn="forgotPW"/>
<s:Label x="10" y="31" text="Username:" includeIn="register"/>
<s:TextInput x="110" y="24" id="usernameTextInput2" text="{users.username}" includeIn="register"/>
<s:Label x="10" y="61" text="Email:" includeIn="register"/>
<s:TextInput x="110" y="54" id="emailTextInput2" text="{users.email}" includeIn="register"/>
<s:Label x="10" y="91" text="Password:" includeIn="register"/>
<s:TextInput x="110" y="84" id="passwordTextInput2" text="{users.password}" displayAsPassword="true" includeIn="register"/>
<s:Button x="10" y="118" label="Save" id="saveBtn" click="saveBtn_clickHandler(event)" includeIn="register"/>
<s:Button x="168" y="118" label="<< Login" click="currentState='loggedOut'" includeIn="register"/>
<s:Label x="10" y="10" text="Welcome User" includeIn="user"/>
<s:Button x="10" y="30" label="Log Out" click="currentState='loggedOut'" includeIn="user"/>
<s:Label x="10" y="10" text="Welcome Admin" includeIn="admin"/>
<s:Button x="10" y="30" label="Admin Log Out" click="currentState='loggedOut'" includeIn="admin"/>
</s:Panel>
</s:Application>
TIPS:
If you would like to make sure the correct variables are being passed back from the server to flex use the trace statement. For example, change this part of your checkLogin function:
Change From:
userid = event.result.loginsuccess;
usertype = event.result.usertype;
Change To:
userid = event.result.loginsuccess;
trace (userid);
usertype = event.result.usertype;
trace (usertype);
Now when you run your application in debug mode, and look in the FB4 console, you can see what is being returned to you from the server.