user level

Beginning

Required products

Flex Builder 3 (Download trial)

Sample files

flex_php_samples.zip (37 KB)

Note: This article was written for Flex 3 and Flex Builder 3. For information on how to develop Flex applications with Flash Builder 4.5 and PHP, please refer to this article.
 
As a web developer you may be wondering, "How do I start using Flex?" Adobe Flex is a very powerful set of tools but "...with great power comes great responsibility."
 
This article introduces you to Flex through basic examples and comparisons with HTML and PHP that you are already familiar with. Each section includes a stand-alone, working example that you can review. I'll begin with the basics like layout and then move on to more advanced topics such as form submission. The goal of this guide is to show you how easy it is to get started using Flex to build Rich Internet Applications.
 

 
Running the Flex/PHP code examples

The sample files contain a Flex Builder 3 archive project that includes all of the examples discussed in this article. You can import this project directly into Flex Builder or Eclipse (after installing the Flex Builder plug-in) by selecting File > Import > Flex Project and navigating to the file.
 
Open the project "src" directory to see the MXML files. Each of these MXML files, which are also called applications, can be run in a web browser. Right-click the file in the Flex Navigator (or the Package Explorer in Eclipse) and choose the option to "Run Application". MXML files differ from HTML files in that MXML files are compiled into a SWF file, which is then run from within an HTML page referencing the SWF file.
 
Flex Builder 3 automatically compiles the MXML code into a SWF file every time you save the file or the first time you choose "Run Application" from the Flex Builder menu. When you run the application, Flex Builder also automatically opens the application in the default browser on your system.
 
To specify the default application, right-click a file name and select the option to "Set as Default Application" from the context menu. The blue dot signifies the default application to run.
 
Note: The Flex Builder 3 project contains a folder of PHP files, which must be deployed to a PHP web application server (see the following instructions) in order to run the examples. Once the server is setup, described below, Flex Builder copies this folder to the web server when the project is built.
 
 
Deploying Flex examples on your local workstation web server
Follow the steps below to publish the PHP files to your local web server so that you can view them:
 
  1. If you do not already have a PHP-enabled web server installed, install XAMPP (for Windows) or MAMP (for Macintosh OS X).
  2. After installing the appropriate software linked above, start your local web server.
  3. In Flex Builder 3, choose Project > Properties. The Flex Builder 3 Project Properties window appears.
  4. Select the Flex Build Path tab. In the output folder, choose a directory on your localhost web server.
    1. On Windows, the path is:
      C:\XAMPP\xampp\htdocs or C:\XAMPP\xampp\htdocs\myproject
    2. On Mac, the path is:
      /Applications/MAMP/htdocs or /Applications/MAMP/projects/test
  5. In the Output folder URL field, enter the URL to the output folder.
    1. On Windows, enter: http://localhost/ or http://localhost/myproject
    2. On Mac, enter: http://localhost:8888 or http://localhost:8888/projects/test
After setting up the local web server, you can test your projects in Flex Builder and they will launch in the browser and run from the server (http://localhost) rather than the local file system (file://path/to/project/bin-debug/myproject.html).
 

 
Creating the user interface

Flex includes a set of tags designed to help you layout the user interface in projects created in MXML. Similar to HTML (which uses tags to set the sizing and positioning of elements on the page), MXML contains tags that define the way the SWF file will display. In HTML, the <div> tag is typically used to group block-elements and format them with styles.
 
Note: The W3C defines the <div> tag as a division or section in a document.
 
When you develop in MXML, you use the Canvas tag <mx:Canvas> to specify a container. A container defines a rectangular region that can be filled with child containers and controls. The Canvas tag is the only container in MXML (besides the Application itself) that allows you to explicitly specify the location of its children using pixel values.
 
You can set the x, y, top, left, right, bottom, baseline, horizontalCenter or verticalCenter properties for each of the children inside a container. The top, left, right, bottom, baseline, horizontalCenter and verticalCenter are special properties (and are also considered styles) that constrain a component to a specific number of pixels from the top, bottom, left, right or center of its container. When you apply the baseline property to multiple components, the horizontal text baselines are all aligned with the first component you selected. When working with Flex components that do not have text baseline (such as the HBox component), the bottom edge is considered the baseline.
 
If you are following along with the sample files available for download on the first page of this article, you can review the example provided in the Flex Builder 3 project by selecting the file name ConstraintBasedLayout.mxml and selecting the option to "Run Application".
 
The following MXML code provides an example of using the <mx:Canvas> tag to define a container and specify the pixels values to set the placement of the application elements on the canvas:
 
 
ConstraintBasedLayout.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css"/> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Constraint based Layout" styleName="headerStyle" id="label1"/> <mx:Label x="10" y="78" text="Components constrained to the top, left, right, bottom, verticalCenter and horizontalCenter properties"/> <mx:Canvas left="10" right="10" top="104" bottom="10" backgroundColor="#000000" backgroundAlpha="0.1" borderStyle="solid" borderColor="#000000" alpha="0.2"> <mx:Text text="Top Left&#xd;" left="10" top="10"/> <mx:Text text="Bottom Left" left="10" bottom="10"/> <mx:Text text="Bottom Center" bottom="10" horizontalCenter="0"/> <mx:Text text="Center" horizontalCenter="0" verticalCenter="0"/> <mx:Text text="Bottom Right" right="10" bottom="10"/> <mx:Text text="Center Right" verticalCenter="0" right="10"/> <mx:Text text="Center Left " left="10" verticalCenter="0"/> <mx:Text text="Top Center" horizontalCenter="0" top="10"/> <mx:Text text="Top Right" right="10" top="10"/> </mx:Canvas> </mx:Application>
By default, the Canvas container (created with the Canvas tag <mx:Canvas>) will expand to fit its content unless the width and height of the container have been set. If you specify the width and height of a container, any contents that extend past the defined size is clipped and scrollbars are displayed. You can prevent a container from clipping its contents by setting the clipContent property to false. And you can prevent containers from applying layout settings to a specific component by setting the specific component's includeInLayout property to false.
 
In addition to the Canvas container, you can also use the Horizontal Box and Vertical Box (HBox and VBox) containers to layout user interface elements. Both will layout their content vertically or horizontally in a single column or a single row, respectively. Setting the x, y, top, left, right, bottom, baseline, verticalCenter or horizontalCenter of a child element does not affect its position (although you could place the HBox or VBox containers into a Canvas container, if needed). Each child of these containers are stacked from top to bottom and left to right with an even amount of space between. Set the horizontalGap or verticalGap properties if you wish to add space in between each item. You can also use the included Spacer component to make adjustments to the space; set the height or width to a positive or negative value to add or subtract the gap.
 
There are many other included layout controls including Grid containers, Form containers and List controls. The Grid is similar to an HTML table and the Form container is similar to a double column VBox. The Repeater component compliments the Grid, VBox or HBox containers in that it will automatically create rows or columns depending on the data you provide. It behaves the same way as a List or DataGrid when you pass data into it.
 
Access the sample files and select the file name BoxBasedLayout.mxml to run the application. The following example illustrates how to create layouts using containers:
 
 
BoxBasedLayout.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff" > <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.core.UIComponent; ]]> </mx:Script> <mx:Style source="styles/styles.css"/> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Box Based Layout" styleName="headerStyle" id="label1"/> <mx:ArrayCollection id="arrayCollection1"> <mx:Array> <mx:Object name="Item 1" /> <mx:Object name="Item 2" /> <mx:Object name="Item 3 with some really long text to show multiline rows of data" /> <mx:Object name="Item 4" /> <mx:Object name="Item 5" /> <mx:Object name="Item 6" /> <mx:Object name="Item 7" /> <mx:Object name="Item 8" /> </mx:Array> </mx:ArrayCollection> <mx:ArrayCollection id="arrayCollection2"> <mx:Array> <mx:Object name="Item 1" /> <mx:Object name="Item 2" /> <mx:Object name="Item 3" /> <mx:Object name="Item 4" /> <mx:Object name="Item 5" /> <mx:Object name="Item 6" /> <mx:Object name="Item 7" /> <mx:Object name="Item 8" /> <mx:Object name="Item 9" /> <mx:Object name="Item 10" /> <mx:Object name="Item 11" /> <mx:Object name="Item 12" /> </mx:Array> </mx:ArrayCollection> <mx:Label x="10" y="78" text="Components are positioned vertically or horizontally within the container"/> <mx:Label x="232" y="114" text="Horizontal Box" fontWeight="bold"/> <mx:HBox backgroundColor="#ECECEC" borderColor="#E0E0E0" borderStyle="solid" x="232" y="140" width="200"> <mx:Text text="Item 1" /> <mx:Text text="Item 2" /> <mx:Text text="Item 3" /> <mx:Text text="Item 4" /> </mx:HBox> <mx:Label x="232" y="184" text="Grid" fontWeight="bold"/> <mx:Grid backgroundColor="#ECECEC" borderColor="#E0E0E0" borderStyle="solid" x="232" y="210" > <mx:GridRow backgroundColor="#DCDCDC"> <mx:GridItem> <mx:Text text="" /> </mx:GridItem> <mx:GridItem> <mx:Text text="Column 1" fontWeight="bold"/> </mx:GridItem> <mx:GridItem> <mx:Text text="Column 2" fontWeight="bold"/> </mx:GridItem> <mx:GridItem> <mx:Text text="Column 3" fontWeight="bold"/> </mx:GridItem> </mx:GridRow> <mx:GridRow> <mx:GridItem> <mx:Text text="Row 1" fontWeight="bold"/> </mx:GridItem> <mx:GridItem> <mx:Text><mx:htmlText> <![CDATA[SOME TEXT<br/>SOME TEXT<br/>SOME TEXT]]> </mx:htmlText></mx:Text> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> </mx:GridRow> <mx:GridRow> <mx:GridItem> <mx:Text text="Row 2" fontWeight="bold"/> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> </mx:GridRow> <mx:GridRow> <mx:GridItem> <mx:Text text="Row 3" fontWeight="bold"/> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> <mx:GridItem> <mx:Text text="Text" /> </mx:GridItem> <mx:GridItem> <mx:Text><mx:htmlText> <![CDATA[SOME TEXT<br/>SOME TEXT<br/>SOME TEXT]]> </mx:htmlText></mx:Text> </mx:GridItem> </mx:GridRow> </mx:Grid> <mx:Label x="10" y="114" text="Vertical Box" fontWeight="bold"/> <mx:VBox backgroundColor="#ECECEC" borderColor="#E0E0E0" borderStyle="solid" x="10" y="140" width="200"> <mx:Text text="Item 1" /> <mx:Text text="Item 2" /> <mx:Text width="190"><mx:htmlText> <![CDATA[SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT]]> </mx:htmlText></mx:Text> <mx:Text text="Item 4" /> <mx:Text text="Item 5" /> <mx:Text text="Item 6"/> <mx:Text text="Item 7" /> <mx:Text text="Item 8" /> </mx:VBox> <mx:Label x="508" y="114" text="Repeater in VBox" fontWeight="bold"/> <mx:VBox backgroundColor="#ECECEC" borderColor="#E0E0E0" borderStyle="solid" x="508" y="140" width="200"> <mx:Repeater id="repeater1" dataProvider="{arrayCollection1}"> <mx:Canvas width="100%"> <mx:Text text="{repeater1.currentItem.name}" x="24" width="140"/> <mx:Image x="0" y="0" source="images/image1.gif"/> </mx:Canvas> </mx:Repeater> </mx:VBox> <mx:Label x="716" y="114" text="Repeater in VBox (height = 200)" fontWeight="bold"/> <mx:VBox backgroundColor="#ECECEC" borderColor="#E0E0E0" borderStyle="solid" x="716" y="140" width="200" height="200"> <mx:Repeater id="repeater2" dataProvider="{arrayCollection2}"> <mx:Canvas width="100%" > <mx:Text text="{repeater2.currentItem.name}" x="24" width="140" color="#212121" fontWeight="normal" y="-3" click= "{Alert.show(UIComponent(event.currentTarget). getRepeaterItem().name,'You Clicked')}" buttonMode="true" useHandCursor="true" mouseChildren="false"/> <mx:Text text="Posted January 1st, 2009" x="24" width="140" color="#4D4D4D" fontWeight="normal" y="10" fontSize="9"/> <mx:Image x="0" y="0" source="images/image1.gif" clickname,'You Clicked')}" buttonMode="true" useHandCursor="true" mouseChildren="false"/> </mx:Canvas> </mx:Repeater> </mx:VBox> </mx:Application>
Although Flex includes a built-in theme, you may wish to use MXML to adjust the look of your containers. You can make changes by using styles, and you can link to an external CSS style sheet to affect the way the components are displayed. Flex Builder includes a Properties panel that includes common styles that can be set. Access the advanced CSS Design View to select a specific component to add additional styles or skins.
 
Set styles when you need to format text or change the color of a component. Use skins to specify an image (or set of images) that define a component's appearance. When you set images to use as skins for a component, you can apply a Scale 9 grid to the image. This feature allows you to stretch and resize your container vertically or horizontally and maintain the original ratio of rounded corners and preserve the edges of the image. If you've previously sliced and exported an image into an HTML table, you will appreciate this timesaving feature.
 
Access the sample files and select the file name StylingAndSkinning.mxml to run the application. The following example illustrates how to use a CSS style sheet to adjust the look and feel of containers:
 
 
StylingAndSkinning.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Styling and Skinning" styleName="headerStyle" id="label1"/> <mx:Canvas x="10" y="96" width="255" height="280" styleName="ScaleNineSkin"> <mx:Label x="10" y="52" text="Result"/> <mx:TextArea x="10" y="69" width="234" height="188" id="textarea1"/> <mx:TextInput id="search" x="10" y="19"/> <mx:Button x="178" y="19" label="Submit" /> </mx:Canvas> <mx:Label x="10" y="70" text="Canvas with an image skin"/> </mx:Application>
Read more about working with containers, styles and skins in the online documentation:
 

 
Submitting a form using the GET method to PHP

In HTML, to submit a form using the GET method, use the following syntax:
 
<form name="input" action="mypage.php" method="GET"> Username: <input type="text" name="user"/> <input type="submit" value="Submit"/> </form>
The code example above submits the form to the URL in the form's action attribute, and essentially redirects to the linked PHP script.
 
To run this example, select the file name SubmitUsingGet.mxml and run the application in the sample Flex project.
 
To submit a form in Flex using the GET method, use the following code:
 
 
SubmitUsingGet.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Submit form using get method" styleName="headerStyle" id="label1"/> <mx:String id="phpFile"> http://localhost:8888/php/show_request.php </mx:String> <mx:HTTPService id="form1" url="{phpFile}" method="GET" resultFormat="text" result="{textarea1.text = String(event.result)}"> <mx:request> <username>{username.text}</username> </mx:request> </mx:HTTPService> <mx:TextInput id="username" x="10" y="99"/> <mx:Button x="178" y="99" label="Submit" click="form1.send()"/> <mx:Label x="10" y="129" text="Result"/> <mx:Label x="10" y="73" text="Submit form to PHP"/> <mx:TextArea x="10" y="146" width="395" height="188" id="textarea1"/> <mx:Button x="252" y="99" label="Check if PHP file exists" click="{navigateToURL(new URLRequest(phpFile));}"/> </mx:Application>
Then you can use the following sample PHP page to return the form information submitted to the PHP page:
 
 
show_request.php
<?php # Send a response back to the client print "You submitted the following form information:\n"; foreach ($_REQUEST as $k => $v) { print " $k = $v\n"; } ?>
This example uses the HTTPService class. See the following excerpt from the Adobe Flex 3 Language Reference documentation to learn more about this example:
 
You use the <mx:HTTPService> tag to represent an HTTPService object in an MXML file. When you call the HTTPService object's send() method, it makes an HTTP request to the specified URL, and an HTTP response is returned. Optionally, you can pass parameters to the specified URL. When you do not go through the server-based proxy service, you can use only HTTP GET or POST methods. However, when you set the useProxy property to true and you use the server-based proxy service, you can also use the HTTP HEAD, OPTIONS, TRACE, and DELETE methods.
 
You can use a Flex HTTPService component in conjunction with PHP and a SQL database management system to display the results of a database query in a Flex application and to insert data into a database. You can call a PHP page with either a GET or POST method to perform a database query. You can then format the query result data in an XML structure and return the XML structure to the Flex application in the HTTP response. When the result has been returned to the Flex application, you can set it to display in one or more user interface controls.
 
You can also specify the information to send to the request object on the server. The request object is a property of the HTTPService class. Inside the request, specify individual parameters to send to the server. In this case, use the data binding expression shorthand notation to specify a reference to the text input: username. Flex provides three ways to specify data binding: the curly braces ({}) syntax in MXML, the <mx:Binding> tag in MXML, and the BindingUtils methods in ActionScript.
 
See the following excerpt from the Adobe Flex 3 Online Help regarding binding data:
 
You can bind a single source property to more than one destination property by using the curly braces ({}) syntax, the <mx:Binding> tag, or the BindingUtils methods in ActionScript. Using the curly braces syntax is the simplest way to pass data between objects in an application. When you use this syntax, you put curly braces ({}) around a binding source as the value of a destination property.
 
You can use ActionScript 3 expressions in curly braces as well. Remember, you are not limited to sending data from form elements that exist inside a form tag.
 
In this example, the form submits to a PHP page that iterates through the form values and sends them back to the client. The HTTPService class can receive an HTTP response without reloading the page. The resultFormat contains the value that indicates how you want to deserialize the result returned by the HTTP call. Within the HTTPService tag, you can set the resultFormat data type to text. By default, resultFormat returns an object. By specifying event listener functions in the result and fault events, you can handle the data returned in the response. This example displays the response from the server in a textarea.
 
Read more about working with forms and data binding in the online documentation:
 

 
Submitting a form using the POST method to PHP

When you submit a form using the POST method, it is essentially the same process as submitting a form using the GET method, except you change the method attribute value to POST instead of GET.
 
If you are following along with the downloadable sample files, run the file named SubmitUsingPost.mxml to view the example application.
 
When you want to submit a form using the post method in Flex, use the following code:
 
 
SubmitUsingPost.mxml:
In the example above, the method has been changed to the POST method. Event listener functions are added inside an ActionScript 3.0 script block to handle the result and fault events. When you get a response or result from the server, the result function specified in the result event is executed. If the call fails—because the URL is incorrect—then the function specified in the fault event is executed.
 
The response from the server is sent in the event.result property inside the result function. By default, the event.result is an object. Usually, you'll need to convert the object to the type of data you specify in the resultFormat using a method such as String. To specify the type of data that the server should return, set the resultFormat in your HTTPService tag. This property can be an object, array, XML, E4X, flashvars, or text depending on the result type specified in the resultFormat attribute. This example sets this attribute to text in order to treat the response from the server as a string.
 
You can access the response data outside the function using the HTTPService lastResult property—or, in other words, using the syntax: myService.lastResult. The lastResult property is the same as the result property but it is not set until after the result function has finished executing. The lastResult property can be very convenient because it will always contain the result from the most recent service call. Components can be bound to this value and can be set to automatically update to display the most recent value.
 
Note: ActionScript 3.0 is very similar in syntax to JavaScript. Both languages are based on the same ECMA specification. Declaring event listeners, as shown in the code example above, provides more flexibility. Using the sample PHP page from the previous example, you can display the information you submitted to the PHP page.
 
Read more about ActionScript 3.0 and working with forms in the online documentation:
 
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Submit form using post method" styleName="headerStyle" id="label1"/> <mx:String id="phpFile">http://localhost:8888/php/show_request.php</mx:String> <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; public function handleResult(event:ResultEvent):void { textarea1.text = "Response from HTTPService call:\n " + String(event.result); } public function handleFault(event:FaultEvent):void { textarea1.text = "Fault Response from HTTPService call:\n " + event.fault.toString(); } ]]> </mx:Script> <!-- Service Call --> <mx:HTTPService id="form1" url="{phpFile}" method="POST" result="handleResult(event)" fault="handleFault(event)" resultFormat="text"> <mx:request> <username>{username.text}</username> </mx:request> </mx:HTTPService> <!-- Layout --> <mx:Label x="10" y="129" text="Result"/> <mx:TextArea x="10" y="146" width="395" height="188" id="textarea1"/> <mx:TextInput id="username" x="10" y="99"/> <mx:Button x="178" y="99" label="Submit" click="form1.send()"/> <mx:Button x="252" y="99" label="Check if PHP file exists" click="{navigateToURL(new URLRequest(phpFile));}"/> <mx:Label x="10" y="73" text="Submit form to PHP"/> </mx:Application> show_request.php: <?php // send a response back to the client print "You submitted the following form information:\n"; foreach ($_REQUEST as $k => $v) { print " $k = $v\n"; } ?>

 
Populating a list with XML from the server

In most cases, you'll create a form that submits to a server and returns XML data. The HTTPService class can receive and cast the response into many different data types including object, array, XML, E4X, flashvars, and text data types. If you specify the return type as E4X, you can take advantage of the advanced sorting, filtering, and reference features E4X offers for XML data. Read the following excerpt from the Adobe Flex online documentation:
 
The ECMAScript for XML specification defines a set of classes and functionality for working with XML data. These classes and functionality are known collectively as E4X. ActionScript 3.0 includes the following E4X classes: XML, XMLList, QName, and Namespace.
 
The methods, properties, and operators of the E4X classes are designed with the following goals:
 
Simplicity: Where possible, E4X makes it easier to write and understand code for working with XML data.
 
Consistency: The methods and reasoning behind E4X are internally consistent and consistent with other parts of ActionScript.
 
Familiarity: You manipulate XML data with well-known operators, such as the dot (.) operator.
 
To follow along with the exercise provided in the sample files, run the file named PopulateListWithXML.mxml.
 
The code example below converts the response from the submitted form to the server into the E4X data type. This application places the results in a TextArea, and then binds it to a List component:
 
 
PopulateListWithXML.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css"/> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Populate List with XML from PHP" styleName="headerStyle"/> <mx:String id="phpFile">http://localhost:8888/php/show_xml.php</mx:String> <mx:HTTPService id="form1" url="{phpFile}" method="POST" resultFormat="e4x" result="{textarea1.text = String(event.result)}"> <mx:request> <firstname>{firstname.text}</firstname> <lastname>{lastname.text}</lastname> </mx:request> </mx:HTTPService> <mx:XMLListCollection id="listCollection" source="{form1.lastResult..row}"/> <mx:Binding source="{listCollection}" destination="list1.dataProvider"/> <mx:Binding source="list1.selectedItem.@label" destination="label1.text"/> <mx:TextInput id="firstname" x="10" y="98" text="John"/> <mx:TextInput id="lastname" x="10" y="128" text="Doe"/> <mx:Button x="178" y="128" label="Submit" click="form1.send()"/> <mx:TextArea x="10" y="193" width="234" height="188" id="textarea1"/> <mx:Label x="274" y="172" text="List Component" /> <mx:Label x="274" y="389" id="label1"/> <mx:Label x="10" y="70" text="Submit form and return XML"/> <mx:Label x="10" y="172" text="Results"/> <mx:List x="274" y="193" id="list1" width="208" height="188" labelField="@label"/> <mx:Button x="329" y="128" label="Check if php file exists" click="{navigateToURL(new URLRequest(phpFile));}"/> </mx:Application>
 
show_xml.php:
<?php $name = $_REQUEST['firstname'].' '.$_REQUEST['lastname']; $dom = new DOMdocument('1.0', 'iso-8859-1'); # Create DataGrid XML DOM Document $dom->formatOutput = true; # Gemerate nice output $rows = $dom->appendChild($dom->createElement('rows')); # Create DataGrid root XML element $rows->appendChild($row = $dom->createElement('row')); # Create first row $row->appendChild(new DOMAttr("label", $name)); # Add the "label" attribute to the first row $rows->appendChild($row = $dom->createElement('row')); # Create second row $row->appendChild(new DOMAttr("label", 'user 2')); # Add the "label" attribute to the seecond row $rows->appendChild($row = $dom->createElement('row')); # Create third row $row->appendChild(new DOMAttr("label", 'user 2')); # Add the "label" attribute to the third row echo $dom->saveXML(); # Output the XML document ?>
In the example above, the resultFormat in the HTTPService class is set to EFX to change the result data type to XML with E4X support. Then the binding tag is used to link or bind the XML to the List component. The code uses the E4X syntax in the binding tag to filter the XML in order to access the desired nodes.
 
Note: The labelField property of the List component allows you to define where the row label comes from. When you use XML you need to specify the label field using E4X syntax. Notice the "@" symbol in front of the attribute name. This specifies that "label" is an attribute of the node.
 
Read more about working with XML and E4X in the Adobe online documentation:
 

 
Navigating to another URL or targeting a frame

In HTML, the user navigates from page to page. HTML uses a document paradigm. One document is loaded and links on that document point to other documents. In Flex, you build one application that changes states—rather than a page that navigates to another page (see the next section: Changing states in Flex ). Both approaches have their advantages but there are times when you may want to navigate away from the current page or load a frame with a new page.
 
Use the following code to navigate to another URL in HTML:
 
<a href="mypage2.php">Go to Page 2</a>
In Flex, use the navigateToURL function to navigate to a URL. This function loads a new URL in the specified frame or window. Read the following excerpt from the Flex documentation:
 
The navigateToURL() function loads a document from a specific URL into a window or frame or passes variables to another application at a defined URL. You can use this method to call JavaScript functions in the HTML page that encloses a Flex application.
 
To accomplish this, create a URLRequest object first, and then use the object to specify the URL to navigate to. Here's another excerpt from the documentation:
 
The URLRequest class captures all of the information in a single HTTP request. This object defines the URL target, variables, method (POST or GET), window, and headers for the request.
 
Run the file named NavigateToURL.mxml to see the example in the sample files. The following MXML code illustrates how to navigate to a URL in Flex:
 
 
NavigateToURL.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css"/> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Navigate to a different URL" styleName="headerStyle" id="label1"/> <mx:Label x="10" y="78" text="Open in a new window"/> <mx:Button x="10" y="104" label="Go to Google" click="navigateToURL(new URLRequest('http://www.google.com'))"/> <mx:Label x="203" y="78" text="Open in current window"/> <mx:Button x="203" y="104" label="Go to Google" click="navigateToURL(new URLRequest('http://www.google.com'),'_self')"/> <mx:Label x="10" y="156" text="Open in a named window or frame"/> <mx:Button x="10" y="182" label="Go to Google" click="open('http://www.google.com','window1')"/> <mx:Button x="10" y="212" label="Go to Yahoo" click="open('http://www.yahoo.com','window1')"/> <mx:Script> <![CDATA[ public function open(url:String, windowId:String="window1"):void { var width:uint = 600; var height:uint = 400; var top:uint = (Application.application.stage.fullScreenHeight - height) / 2 - 25; // move it up a bit var left:uint = (Application.application.stage.fullScreenWidth - width) / 2; ExternalInterface.call("eval", "myWin = window.open('" + url + "', '" + windowId + "', 'toolbar=1,scrollbars=0,location=1,statusbar=0,menubar=0,resizable=0,width=" + width + ",height=" + height + ",left=" + left + ",top=" + top + "');myWin.focus()"); } ]]> </mx:Script> </mx:Application> <label> Show Hidden Element <input type="checkbox" name="checkbox" value="checkbox" onclick="document.getElementById('element').style.display= (this.checked) ? 'block' : 'none'"/> </label> <div id="element" style="display:none;border:1px solid red;"> I am now visible </div>
If you wish to target a specific frame or window, specify its name in the second parameter of the navigateToURL method.
 
Read more about navigating to a URL in the Adobe Flex online documentation:
 

 
Changing states in Flex

Changing states does not mean moving from Minnesota to Florida. In HTML, you can show or hide certain elements on a page. And you can also change an object's state from visible to invisible.
 
In Flex, there is a similar behavior that is much more powerful. When you change to a new state in Flex you can add or remove components, set properties, change the behavior of a button, trigger effects, trigger transitions, and much more. The Flex documentation describes this overall behavior as "changing states." Read the following excerpt from the documentation:
 
You can use Adobe Flex Builder 3 to create applications that change their appearance depending on the task that the user is performing. For example, the base state of the application could be the home page and include a logo, a sidebar, and some welcome content. When the user clicks a button in the sidebar, the application dynamically changes its appearance (its state), replacing the main content area with a purchase order form but leaving the logo and sidebar in place.
 
In Flex, you can add this kind of interactivity with view states and transitions. A view state is one of several views that you define for an application or a custom component. A transition is one or more effects grouped together to play when a view state changes. The purpose of a transition is to smooth the visual change from one state to the next.
 
This example shows how to change the state of the Canvas component. In HTML, use the code below to show or hide an element on the page:
 
<label> Show Hidden Element <input type="checkbox" name="checkbox" value="checkbox" onclick="document.getElementById('element'). style.display= (this.checked) ? 'block' : 'none'"/> </label> <div id="element" style="display:none;border:1px solid red;"> I am now visible </div>
Follow along with the sample files by running the file named ChangingStates.mxml. The code example below illustrates how to show or hide a state in Flex:
 
 
ChangingStates.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff" currentState="basic_search"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Label x="10" y="10" text="Changing States" styleName="headerStyle" id="label1"/> <mx:states> <mx:State name="basic_search"> <mx:AddChild position="lastChild"> <mx:CheckBox id="checkbox1" x="10" y="59" label="Change states" labelPlacement="left" click="{currentState = (checkbox1.selected) ? 'advanced_search' : 'basic_search';}"/> </mx:AddChild> <mx:AddChild position="lastChild"> <mx:Label id="searchLabel0" x="10" y="104" text="Basic Search"/> </mx:AddChild> <mx:AddChild position="lastChild"> <mx:HBox x="10" y="130"> <mx:TextInput id="textinput1"/> <mx:Button id="button1" label="Search" /> </mx:HBox> </mx:AddChild> </mx:State> <mx:State name="advanced_search" basedOn="basic_search"> <mx:AddChild relativeTo="{button1}" position="before"> <mx:ComboBox selectedIndex="0"> <mx:dataProvider>['All Categories','Books','Movies','Music','Software']</mx:dataProvider> </mx:ComboBox> </mx:AddChild> </mx:State> </mx:states> </mx:Application>
In the example above, the state of the Canvas container changes when the user selects the "Show Different State" option. Change the basic search form to an advanced search form by adding a ComboBox control and moving the search button over. When you make these changes, you can also change the click event of the button so that it calls the advanced search function instead of the basic search function.
 
The previous example also uses the ViewStack container for comparison. The checkbox displays a second state in the ViewStack component when it is checked. When it is deselected, it displays the original state. Each child of the ViewStack container is a container component. Read the following excerpt from the documentation:
 
In Adobe Flex, layout containers provide a hierarchical structure to arrange and configure the components, such as Button and ComboBox controls, of a Flex application.
 
A layout container defines a rectangular region of the Adobe Flash Player drawing surface and controls the sizing and positioning of the child controls and child containers defined within it. For example, a Form layout container sizes and positions its children in a layout similar to an HTML form.
 
Inside each container, you can display different views or states to the user. The main difference between a ViewStack component and defining states in your application is that a ViewStack component will switch to show a set of different components, while states will let you manipulate or remove the components you already have, as well as allowing you to add new components.
 
Note: Containers with multiple views, such as the ViewStack and Accordion containers, do not immediately create all of their descendants. They only create the descendants that are visible in the initial view. Flex defers the instantiation of descendants that are not initially visible until the user navigates to a view that contains them.
 
You can use the container's creationPolicy property to create all controls in all views of the navigator container. Choosing this setting causes a delay in larger application's startup time but results in quicker response time when first switching to the view at runtime. When using states, you can use the creationPolicy attribute of the addChild tag to control when the child component is created.
 
The States API is very powerful and has the capability to accomplish many more things than we've described here. Research further to learn more about what you can achieve when working with the States API.
 
Read more about changing states in the Adobe online documentation:
 

 
Downloading a file

The FileReference class includes functionality you can use to upload and download files. The upload and download behavior is no different than in HTML. In HTML, download a file by using the following code:
 
<a href="http://www.test.com/myfile.zip" >Download</a>
To see this example in action, run the file named FileDownload.mxml. Use the following code to download a file in Flex:
 
 
FileDownload.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Downloading a File" styleName="headerStyle" id="label1"/> <mx:Button x="10" y="75" label="Download HTML Component" click="{download()}"/> <mx:Script> <![CDATA[ public function download():void { // Pass in url to file or PHP proxy and // create a new file reference instance. var request:URLRequest = new URLRequest("http://www.drumbeatinsight.com/examples/html/HTMLComponent1.0.0.zip"); var fileRef:FileReference = new FileReference(); fileRef.download(request); } ]]> </mx:Script> </mx:Application>
Note: Filter the files that you receive on the server before using this example to prevent someone from uploading a script. An example of this process is available in the Adobe Flex 3 documentation: Working with file upload and download.
 
Read more about downloading files in the Adobe online documentation:
 

 
Uploading a file to PHP

The FileReference class also offers the ability to handle uploads. This class provides many advantages over traditional HTML file uploads—including a single dialog box for multiple file uploads, progress information, file upload complete events, file upload filter types, and more. In HTML, use the following code to upload a file:
 
<form method="post" enctype="multipart/form-data" action="upload.php"> File: <input type="file" name="filename"/> <input type="submit" value="Upload"/> </form>
Run the file named FileUpload.mxml in the sample project. Here's the code to use to upload a file in Flex:
 
 
FileUpload.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Uploading a File" styleName="headerStyle" id="label1"/> <!-- THIS WILL NOT WORK UNLESS YOU ENTER THE CORRECT PATH TO THE PHP FILE ON YOUR SERVER --> <mx:Script> <![CDATA[ // ENTER THE PATH TO THE FILE UPLOAD SCRIPT ON YOUR SERVER // Check the bin-debug folder // You may have to run clean on your project to get it to copy out the PHP files to the server public var uploadFile:String = "http://localhost:8888/php/file_upload.php"; ]]> </mx:Script> <mx:Button x="10" y="70" label="Upload" click="{upload()}"/> <mx:Button x="83" y="70" label="Check if PHP file exists" click="{test()}"/> <mx:Script> <![CDATA[ import flash.net.navigateToURL; import flash.events.DataEvent; // We declare the file reference here so it is not destroyed by memory garbage collection. public var fileRef:FileReference = new FileReference(); // a class that is similar to a HTML form public var request:URLRequest; // Following opens a browser window for the user to select a file to upload public function upload():void { // Listen for the upload events // http://livedocs.adobe.com/flex/3/html/17_Networking_and_communications_7.html fileRef.addEventListener(Event.SELECT, selectHandler); fileRef.addEventListener(Event.OPEN, openHandler); fileRef.addEventListener(ProgressEvent.PROGRESS, progressHandler); fileRef.addEventListener(Event.COMPLETE, completeHandler); fileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadCompleteHandler); fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, httpSecurityErrorHandler); fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpErrorHandler); fileRef.addEventListener(IOErrorEvent.IO_ERROR, httpIOErrorHandler); // browse for the file to upload // when user selects a file the select handler is called try { var success:Boolean = fileRef.browse(); } catch (error:Error) { trace("Unable to browse for files."); textarea1.text = "Unable to browse for files."; } } // Following checks that the upload PHP file is where we think it is public function test():void { request = new URLRequest(uploadFile); navigateToURL(request,"_blank"); } // When a file is selected, we upload the file to the PHP file upload script on the server public function selectHandler(event:Event):void { request = new URLRequest(uploadFile); try { // upload file fileRef.upload(request); textarea1.text = "Uploading " + fileRef.name + "..."; } catch (error:Error) { // vague trace("Unable to upload file."); textarea1.text += "\nUnable to upload file."; } } // Following dispatched during file open. public function openHandler(event:Event):void { trace("File opened"); textarea1.text += "\nFile opened"; } // Following dispatched during file upload public function progressHandler(event:ProgressEvent):void { trace("File upload in progress (" + event.bytesLoaded + " of " + event.bytesTotal + ")"); textarea1.text += "\nFile upload in progress (" + event.bytesLoaded + " of " + event.bytesTotal + ")"; } // Following dispatched when the file has been given to the server script // this event does not receive a response from the server // use DataEvent.UPLOAD_COMPLETE_DATA event as shown in uploadCompleteHandler public function completeHandler(event:Event):void { trace("File uploaded"); textarea1.text += "\nFile uploaded"; } // Following dispatched when a file upload has completed // this event can contain a response from the server as opposed to the Event.COMPLETE event // the PHP upload file can send back information if we want it to // the event.data and event.text properties would contain a response if any public function uploadCompleteHandler(event:DataEvent):void { trace("Information about upload: \n" + String(event.text)); textarea1.text += "\nInformation about upload \n" + event.text as String; } // Following dispatched when an http error occurs // 404 is can't find file // test the file exists public function httpErrorHandler(event:HTTPStatusEvent):void { trace("HTTP error occured " + event.status); textarea1.text += "\nHTTP error occured - " + event.status; } // Following dispatched when an http io error occurs // Error #2038: File I/O Error. - can't find the PHP file // DO THE FOLLOWING: // - check that the file name is spelled correctly in the uploadFile variable // - check that the path to the file is correct (click test file exists button) // - make sure you are running a PHP server locally (google search for MAMP or XAMPP) // - make sure you are publishing to your PHP server // - make sure you are pointing to the correct path in your local server (preferences > document root) // - manually check the file is on your server public function httpIOErrorHandler(event:IOErrorEvent):void { trace("HTTP IO error occured - " + event.text); textarea1.text += "\nHTTP IO error occured - " + event.text; } // Following dispatched when an http io error occurs // Error #2049: Security sandbox violation means // your ‘.swf' and PHP file are on different servers or directories // make sure the PHP file is in the same or a subdirectory // or add a cross domain security file to the same directory where the PHP file is // check / for the latest documentation on cross domain policy files public function httpSecurityErrorHandler(event:SecurityErrorEvent):void { trace("HTTP Security error occured - " + event.text); textarea1.text += "\nHTTP Security error occured - " + event.text; } ]]> </mx:Script> <mx:TextArea x="10" y="100" width="90%" height="200" id="textarea1"/> </mx:Application> file_upload.php: <?php // You send messages back to the client and then // move the file from PHP's temporary upload directory to your local directory // Filedata is the default name used in uploading echo "\nReceiving upload...\n"; echo "temporary file name = " . $_FILES['Filedata']['tmp_name']."\n"; echo "file name = " . $_FILES['Filedata']['name']."\n"; echo "file size = " . $_FILES['Filedata']['size']."\n"; echo "attempting to move file...\n"; move_uploaded_file($_FILES['Filedata']['tmp_name'], "./".$_FILES['Filedata']['name']); echo "file moved\n"; ?>
Note: Be sure to filter the files that you receive on the server before using this example to prevent someone from uploading a script. Check out the example provided in the Adobe Flex online documentation: Working with file upload and download.
 
Read more about uploading files in the Adobe online documentation:
 

 
Login example application

It is common practice to build applications that require users to authenticate their credentials on the server in order to see certain information. Typically, a login form is used to restrict access to secure data. After a user logs in, they are able to access and see additional information.
 
This example highlights how to build a simple login application. When the application launches, the user can only see the home page. Once they have logged in, they are able to see an additional view and can access additional data from the server. The application is also set to timeout if it detects a lack of keyboard or mouse activity for more than 10 seconds. When this happens, the user is automatically logged out and the application changes to the visitor state. The Flex framework is designed to preserve the session data in memory, so that if the user logs back in they will not lose any data entered. Data entered into the application is held in memory until the application is closed. This results in a better experience for the user.
 
To follow along with the sample files, run LoginApplication.mxml. The code below provides an example of how to create a simple login application:
 
 
LoginApplication.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css" /> <mx:HRule y="37" left="10" right="10"/> <mx:Text x="10" y="10" text="Login Application" styleName="headerStyle" id="label1"/> <mx:Script> <![CDATA[ // import the classes we are going to use import mx.controls.Alert; import mx.events.FlexEvent; import mx.managers.SystemManager; import mx.rpc.events.FaultEvent; import mx.events.ItemClickEvent; import mx.collections.ArrayCollection; import mx.rpc.events.ResultEvent; // Store the user access level after user logs in private var userAccess:String = ""; // Define roles to compare against private var roles:String = "user"; // These are the menus that we use to show the user. // Bindable lets us bind to this variable // ArrayCollections are a very powerful Array with additional features we can use later [Bindable] private var guestMenu:ArrayCollection = new ArrayCollection(["home"]); [Bindable] private var userMenu:ArrayCollection = new ArrayCollection(["home","user"]); // timeout after twenty seconds public var timeout:Number = 20000; private var timeoutTotal:Number = 0; private var timeoutLastCall:Number; public var sessionExpired:Boolean = false; public var enableTimeout:Boolean = true; // we could convert this into a reusable class // we are not going to for simplicity private function timeoutHandler(event:FlexEvent):void { // get current time var curTime:int = getTimer(); var timeDiff:int = 0; if (isNaN(timeoutLastCall)) { timeoutLastCall = curTime; } timeDiff = curTime - timeoutLastCall; timeoutLastCall = curTime; // If time has passed since the idle event we assume user is interacting // reset time total - otherwise increment total idle time if (timeDiff > 1000) { timeoutTotal = 0; } else { // Update time: // The status field will not be updated unless the application is idle. // Time is only display a countdown for learning purposes timeoutTotal += 100; status.text = "Timeout in " + String(Number((timeout - timeoutTotal)/1000).toFixed(0)) + " seconds"; } // If the total time of inactivity passes our timeout // and the session already hasn't expired then logout user if (timeoutTotal > timeout && !sessionExpired) { // logout user // or set flag sessionExpired = true; status.text = "timeout threshold has been reached"; sessionTimeoutHandler(); } } // When the application times out due to inactivity, we then call this function private function sessionTimeoutHandler():void { logout(); var message:String = "Session Expired due to inactivity!\nPlease log back in to resume"; Alert.show(message, "Session Expired", Alert.OK); // remove idle listener var sysMan:SystemManager = Application.application.systemManager; sysMan.removeEventListener(FlexEvent.IDLE, timeoutHandler); } // This is the function that receives a response from the server after clicking submit // event.result contains the string response from the server // We check if the user has access to any of the roles private function handleLogin(event:ResultEvent):void { userAccess = event.result as String; trace("handleLogin result data = "+userAccess); if (userAccess.indexOf(roles)>-1) { // login success // hide failed login message, set login form to success state, show user menu loginFailedText.visible = false; loginStack.selectedChild = loginSuccess; linkBar.dataProvider = userMenu; sessionExpired = false; viewStack.selectedChild = viewStack.parentApplication[String(userMenu.getItemAt(1))]; var sysMan:SystemManager = Application.application.systemManager; if (enableTimeout) { // Dispatched every 100 milliseconds when there has been no keyboard or mouse activity for 1 second. sysMan.addEventListener(FlexEvent.IDLE, timeoutHandler); } } else { // show failed login message, show guest menu loginFailedText.visible = true; linkBar.dataProvider = guestMenu; } } // This function is run when a user clicks a menu item. // If we wanted to, we could make this more robust here. // Check if the session has expired on the server, etc. // If it fails we can move the user back to the guest view or alert them to log in again private function handleLinkBar(event:ItemClickEvent):void { viewStack.selectedChild = viewStack.parentApplication[String(event.label)]; } // Following handles when user manually destroys the session private function handleLogout(event:ResultEvent):void { textarea1.text = "You have manually destroyed the session. Try to get data from the server."; } // Following handles logging out for other functions private function logout():void { loginStack.selectedChild = loginForm; loginFailedText.visible = false; linkBar.dataProvider = guestMenu; viewStack.selectedChild = viewStack.parentApplication[guestMenu[0]]; username.text = ""; password.text = ""; } // Following handles when something goes wrong with our service call private function handleFault(event:FaultEvent):void { // for stream error 2032 see http://www.judahfrangipane.com/blog/?p=87 trace("fault = "+event.message); loginStack.selectedChild = loginForm; errorText.visible = true; errorText.text = "Could not connect to the server. Check the url. \nFault " + event.fault; linkBar.dataProvider = guestMenu; viewStack.selectedChild = viewStack.parentApplication[guestMenu[0]]; } ]]> </mx:Script> <!-- COMMUNICATION --> <mx:String id="phpFileLogin">http://localhost:8888/php/login.php</mx:String> <mx:String id="phpFileLogout">http://localhost:8888/php/logout.php</mx:String> <mx:String id="phpFileData">http://localhost:8888/php/secure_data.php</mx:String> <mx:HTTPService id="loginService" url="{phpFileLogin}" method="POST" resultFormat="text" result="{handleLogin(event)}" fault="{handleFault(event)}"> <mx:request> <username>{username.text}</username> <password>{password.text}</password> </mx:request> </mx:HTTPService> <mx:HTTPService id="logoutService" url="{phpFileLogout}" resultFormat="text" result="{handleLogout(event)}" fault="{handleFault(event)}"/> <mx:HTTPService id="getDataService" url="{phpFileData}" resultFormat="text" result="{textarea1.text = String(event.result);}" fault="{handleFault(event)}"/> <!-- LAYOUT --> <mx:Label id="loginFailedText" text="Login failed!" fontWeight="bold" color="#000000" right="10" y="10" visible="false"/> <mx:ViewStack id="loginStack" y="61" right="10" height="30" width="400" paddingLeft="5"> <mx:HBox id="loginForm" label="Login Form" verticalAlign="middle"> <mx:Label text="Username"/> <mx:TextInput id="username" width="80" borderStyle="solid" text="user"/> <mx:Label text="Password"/> <mx:TextInput id="password" width="80" displayAsPassword="true" borderStyle="solid" enter="{loginService.send()}" text="password"/> <mx:Button label="Submit" click="{loginService.send()}"/> </mx:HBox> <mx:HBox id="loginSuccess" label="Login Success" verticalAlign="middle" horizontalAlign="right"> <mx:Label text="Welcome user, you are logged in!" id="welcomeText"/> <mx:Button label="Logout" click="{logout()}"/> </mx:HBox> </mx:ViewStack> <mx:ViewStack id="viewStack" right="10" left="10" top="100" bottom="20"> <mx:Canvas id="home" label="home" width="100%" height="100%" backgroundColor="#f6f6f6"> <mx:Label x="10" y="10" text="Guest View" fontWeight="bold"/> <mx:Label x="10" y="36" text="This view is visible to everyone"/> <mx:Text visible="false" left="10" right="10" x="10" y="62" text="Label" color="#ff0000" fontWeight="bold" id="errorText"/> </mx:Canvas> <mx:Canvas id="user" label="user" width="100%" height="100%" backgroundColor="#f6f6f6"> <mx:Label x="10" y="10" text="User View" fontWeight="bold"/> <mx:Label x="10" y="36" text="This view is visible only to logged in users. "/> <mx:Button x="10" y="62" label="Get Authenticated Data" id="getUserData" click="getDataService.send();"/> <mx:Button x="180" y="62" label="Destroy Session" id="destroySession" click="logoutService.send()"/> <mx:TextArea x="10" y="92" width="312" height="150" id="textarea1"/> <mx:Text x="10" y="250" text="Get data that is only available if you are part of the &quot;user&quot; group. Destroy the session and test it again to see authenticated data is no longer available." width="295"/> <mx:Text y="10" text="If you do not move the mouse or keyboard for 1 second then the idle event starts. We use this event to timeout the application (client side) when it has been idle too long. The timeout is currently set to 20 seconds for this example. You could also start a timer starting from the last call you made to the server. This will allow you to sync the time the client expires with the time server session expires." width="307" right="10"/> </mx:Canvas> </mx:ViewStack> <mx:LinkBar id="linkBar" x="10" y="63" dataProvider="{guestMenu}" itemClick="handleLinkBar(event)" backgroundColor="#ffffff" backgroundAlpha="0.41"> </mx:LinkBar> <mx:Label y="21" id="status" right="20" fontWeight="bold" color="#E40000"/> </mx:Application> login.php: <?php // Send a response back to the client //print "\n You submitted the following form information:\n"; foreach ($_REQUEST as $k => $v) { //print "\n $k = $v"; } if( $_REQUEST["username"]=="user" && $_REQUEST["password"]=="password") { //echo "Login successful"; session_start(); $_SESSION['group'] = 'user'; echo $_SESSION['group']; }else{ echo "failed"; } ?> secure_data.php: <?php session_start(); if ($_SESSION['group']=="user") { print "<?xml version='1.0' encoding='ISO-8859-1' ?>"; print "<rows>"; print "<row>"; print "<firstname>john</firstname>"; print "<lastname>smith</lastname>"; print "</row>"; print "<row>"; print "<firstname>jane</firstname>"; print "<lastname>smith</lastname>"; print "</row>"; print "</rows>"; } else { echo "Session expired..."; } ?> logout.php: <?php session_start(); @session_destroy(); $_SESSION['group'] = ''; echo "success"; ?>
In the example above, the code creates two ViewStack components. The first ViewStack component contains the login form. When the user logs in, they are presented with the logged in view. The other ViewStack component contains the application content. The first view is the home page view. Every user can access this page. The second view is the user view. When the user has logged in successfully, a second navigational menu appears and the user view appears. Authenticated users can switch back and forth between views.
 
The second view is a form that retrieves data from the server. When a user clicks the Get Authenticated Data button, a service call is sent to the server. If the user has a successfully logged in session on the server they will receive sample data. If the session does not exist on the server, a message is sent back asking the user to log in again.
 
There is one more thing included with this application: a client-side timeout mechanism. Once the user logs in, the event listener listens for the Application IDLE event. If the application has been idle for longer than the specified timeout value (this example is set to 10 seconds), the application logs the user out, moves the user back to the visitor state, and displays a message indicating that the user is logged out. If the user logs back in, they will see all the form data because the form data is not destroyed when the user switches views (states). Depending on the type of application you build, you may want to clear the form data if it becomes irrelevant. When you develop using Flex these kinds of choices are up to you.
 
Note: As you review the code for this example, notice that the script block is located at the top. This is a best practice because as you add components to the Design view, Flex Builder adds the component definitions at the end of the MXML file. In MXML, the order in which you add components is the order in which they are stacked in the z-index coordinate space. For example, if you add two images in your MXML code, the image tag towards the bottom of the file is added after (and on top of) the first image.
 
There is more going on in this example than in the previous examples. This section of the article has covered the main aspects of this topic, but be sure to read the additional comments in the code.
 
Read more about authenticating users in the Adobe Flex online documentation:
 

 
Populating a DataGrid with XML from PHP

As you develop any application using Flex, one of the common tasks involves populating a DataGrid with XML data. This example shows how to submit data to the server and display the returned XML in a DataGrid.
 
If you are following along with the sample files, right-click on the PopulatingDataGridWithXML.mxml file and choose the option to run the application. The following code is used to populate the DataGrid with XML data:
 
 
PopulatingDataGridWithXML.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#ffffff"> <mx:Style source="styles/styles.css"/> <mx:HRule x="10" y="37" width="90%"/> <mx:Text x="10" y="10" text="Populating a DataGrid with XML from PHP" styleName="headerStyle" id="label1"/> <!-- Script --> <!-- Our result handler functions get any value returned from the server --> <mx:Script> <![CDATA[ import flash.net.navigateToURL; import mx.collections.ArrayCollection; // we import the event classes for strong typing import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; [Bindable] private var phpFile:String = "http://localhost:8888/php/datagrid_xml.php"; // This function handles the response from our call to the server public function handleResultXML(event:ResultEvent):void { // The event.result object is our xml root lastResultValue.text = String(event.result); // We get the row nodes of our result object and // the data of the dataprovider populates the component myDataGrid.dataProvider = event.result.row; } // This function is called when we get an error from the server // Error #2032: Stream Error means the file // DO THE FOLLOWING: // - check that the file name is spelled correctly // - check that the path to the file is correct (click test file exists button) // - make sure you are running a PHP server locally (google search for MAMP or XAMPP) // - make sure you are publishing to your PHP server // - make sure you are pointing to the correct path in your local server (preferences > document root) // - manually check the file is on your server public function handleFault(event:FaultEvent):void { lastResultValue.text = "Fault: " + event.fault.faultDetail; } // checks that the PHP file is where we think it is public function test():void { var request:URLRequest = new URLRequest(phpFile); navigateToURL(request, "_blank"); } ]]> </mx:Script> <!-- Data Communications --> <!-- The url is the page we post to --> <!-- In the request object we add our name and value pairs --> <!-- The curly brackets surrounding "username.text" get the value of username.text --> <!-- Note: The curly brackets are also used for databinding where supported --> <!-- Note: We set the resultFormat to e4x to automatically convert our return string to an XML object with e4x support --> <mx:HTTPService id="myServiceXML" url="{phpFile}" method="POST" result="handleResultXML(event)" fault="handleFault(event)" useProxy="false" resultFormat="e4x"/> <!-- Layout --> <mx:Button id="submit0" x="10" y="70" label="Get XML" click="myServiceXML.send()"/> <mx:Label x="10" y="225" text="Result"/> <mx:DataGrid id="myDataGrid" x="10" y="111" width="374" height="106"> <mx:columns> <mx:DataGridColumn headerText="First Name" dataField="firstname"/> <mx:DataGridColumn headerText="Last Name" dataField="lastname"/> </mx:columns> </mx:DataGrid> <mx:TextArea x="10" y="241" width="374" height="150" id="lastResultValue"/> <mx:Button x="231" y="70" label="Check if PHP file exists" click="{test()}"/> </mx:Application> datagrid_xml.php: <?php $dom = new DOMdocument('1.0', 'iso-8859-1'); # Create DataGrid XML DOM Document $dom->formatOutput = true; # Gemerate nice output $rows = $dom->appendChild($dom->createElement('rows')); # Create DataGrid root XML element $rows->appendChild($row = $dom->createElement('row')); # Create first row (John Smith) $row->appendChild($dom->createElement('firstname', 'John')); $row->appendChild($dom->createElement('lastname', 'Smith')); $rows->appendChild($row = $dom->createElement('row')); # Create second row (Jane Smith) $row->appendChild($dom->createElement('firstname', 'Jane')); $row->appendChild($dom->createElement('lastname', 'Smith')); echo $dom->saveXML(); # Output the XML ?>
Read more about working with DataGrids in the Adobe Flex online documentation:
 

 
Taking your projects to the next level

Flex provides many mechanisms that offer many other features and benefits for communicating with PHP beyond using the HTTPService class. Read the following excerpt from the documentation:
 
Flex provides several solutions for data delivery to the client. It delivers data through runtime services that invoke methods on PHP classes, sends proxy requests to web services or HTTP servers.
 
Using the WebService component enables you to use a SOAP-based approach, but it does not always yield the best performance. Also, the additional XML with the SOAP encoding requires more overhead than AMF does.
 
Action Message Format — AMF 3 is an Adobe proprietary protocol for object remoting. It is much faster than HTTP service calls because the message is compressed natively. The data is also serialized so you can work directly with objects. AMF is part of the Remote Procedure Call group of services. To quote Patrick Mineault:
 
RPC (Remote Procedure Call) is a way to communicate data between a client and a server. You call a method on a local object with various parameters, set a callback, and receive a result. You don't have to worry about how you're going to send and receive the data. The server and the client, say PHP and Flash, agree on a common way of describing method calls and complex data. The implementation details are abstracted away so that it looks as though you're calling a local method.
 
To work with AMF and PHP you can use either AMFPHP or WebORB for PHP.
 
 
AMFPHP
AMFPHP is an RPC toolkit for PHP. It allows seamless communication between PHP and the following technologies:
 
  • Flash and Flex with Remoting
  • JavaScript and AJAX with JSON
  • XML clients with XML-RPC
 
WebORB for PHP
Midnight Coders' WebORB for PHP is a platform enabling development, deployment, and runtime execution of Rich Internet Applications. The product facilitates connectivity between rich clients created with Flex, Flash, or AJAX and server-side applications developed with .NET, Java, Ruby on Rails, PHP, or XML web services:
 
  • Open-source alternative to AMFPHP
  • Dual licensing: GPL and commercial licenses available
  • Implements AMF0, AMF3, and Flex Data Services (Flex RPC)
  • Full implementation of the Flex Data Management Services functionality will be available in a commercial edition
 
PHP and Zend Framework + Zend AMF
Extending the art and spirit of PHP, Zend Framework (Zend AMF) is based on simplicity, object-oriented best practices, corporate-friendly licensing and a rigorously tested agile code base. The Zend Framework is focused on building more secure, reliable and modern Web 2.0 applications and web services, and consuming widely available APIs from leading vendors like Google, Amazon, Yahoo!, and Flickr, as well as API providers and cataloguers like StrikeIron and ProgrammableWeb.
 
Check out the Zend AMF Programmer's Reference Guide.
 
For more on the Zend Framework, see the article: Working with Flex and PHP in Eclipse.
 

 
Where to go from here

Flex has many more features that are beyond the scope of this article. Flex was written from the ground up for developers by developers who have worked in the industry for many years and are actively listening to the Flex online community to make it better. As you discover new timesaving features in Flex, you'll realize these benefits and maximize your productivity while decreasing development time.
 
Visit the following resources to get started and research further: