php与flex宝典

(英文原文: [http://www.adobe.com/devnet/flex/articles/php_getstarted.html Flex quick start guide for PHP developers (updated for Flex 3)] ) <br/>
原作者:Judah Frangipane 翻译者:Maya

作为一个PHP和HTML开发者,你可能会想“对于Flex,我该如何起步?”Adobe的Flex是个很强壮的工具。但是“能力越强,责任越重。”

本文着重于介绍Flex,并为HTML和PHP开发者提供示例。HTML例子会告诉你HTML和MXML代码之前的差别。每一个部分都有独立的,可运行的例子供参考。例子中使用到PHP的地方都会有PHP代码。我会由浅入手,逐步深入,使用基本的代码帮你快速起步。本指南的目的就是要告诉你用Flex开发创建富互联网应用是件多么简单的事。

== <strong>准备</strong> ==
为了更好得了解本教程, 您需要使用到以下软件和文件:
<ul>
<li>Flex Builder 3<br/>
[http://www.adobe.com/go/tryflex Try]  &nbsp;&nbsp;&nbsp;  [http://www.adobe.com/go/buyflexbuilder Buy]
</li>
<li>Getting started with Flex 3 - Chapter 5: Working with the Server (optional)<br/>
[http://www.adobe.com/devnet/flex/pdfs/getting_started_with_Flex3.pdf Download] <span style="color:gray">(PDF, 1.44M)</span>
</li>
<li>Sample files:<br/>
[http://download.macromedia.com/pub/developer/flex_php_samples.zip flex_php_samples.zip] <span style="color:gray">(ZIP, 40K) </span>
</li>
</ul>

<br/>

=='''运行FLEX或PHP代码范例'''==
示例文件中有一个Flex Builder3可以打开的项目,其中包括了本文所涉及到的所有范例。你可以通过选择File〉Import〉Flex Project,找到文件后直接导入到Flex Builder或Eclipse(含Flex Builder插件)。你还需要把它放到web服务器上,这样php代码才能被执行。下面我将手把手地教你设置服务器。
打开项目的src路径查看MXML文件。每一个MXML都是一个可在浏览器里跑的应用。右击Flex导航中的文件(在Eclipse中是包视图)并选择“Run Application”。MXML文件不同于HTML文件,它们会被编译成一个swf文件运行在HTML页面中。
在您保存文件或第一次通过Flex Builder菜单选择“Run Application”时,Flex Builder3会自动把MXML编译为swf。启动应用时,Flex Builder也会自动在系统默认浏览器中打开应用。

右击文件名,选择“Set as Default Application”设置默认应用。蓝点表示默认应用启动了。

<span style="color:gray">注意:Flex Builder3项目中有一个都是PHP文件的文件夹,它们必须要放在web服务器上,应用才能跑得起来(请看以下说明)。Flex Builder 3里的PHP文件使你能更好地查看正在执行的代码,本文之后会提到。</span>

把Flex部署在本地web服务器

跟着以下步骤发布PHP文件,并部署到web服务器。然后你就可以看到应用了。
<ul>
<li>如果你还没有装可运行PHP的服务器,请安装[http://www.apachefriends.org/en/xampp.html XAMPP](用于Windows) 或者[http://www.mamp.info/en/index.php MAMP] (用于Macintosh OS X)。</li>
<li>安装完上面恰当的应用链接后,就可以启动服务器了。</li>
<li>在Flex Builder3中,选择Projects-Properties,出现Flex Builder3项目属性窗口。
<ul>
<li>在windows中,路径是:<br/>
C:/XAMPP/xampp/htdocs or C:/XAMPP/xampp/htdocs/myproject</li>
<li>在MAC中,路径是<br/>
C:/XAMPP/xampp/htdocs or C:/XAMPP/xampp/htdocs/myproject</li>
</ul><li>
<li>在输出文件的URL字段上,填上输出文件夹的地址。
<ul>
<li>Windows中,http://localhost/ 或者 http://localhost/myproject</li>
<li>MAC中,http://localhost:8888 或者http://localhost:8888/projects/test</li></ul>
</li>
</ul>
设置完web服务器之后,你就可以在flex builder中测试你的项目。他们会运行在服务器上(http://localhost), 而不是本地文件里(file://path/to/project/bin-debug/myproject.html)。

<br/>

== <strong>创建用户界面</strong> ==
Flex包括了一系列的设计标签,帮助你对MXML进行布局。
和HTML类似(使用标签设置页面上元素的位置和尺寸)。MXML包含的标签定义了SWF文件的显示方式。在HTML里,&lt;div&gt;标签常用于块元素,通过样式来进行格式化。

<span style="color:gray">注意:[http://www.w3.org/ W3C]把&lt;div&gt;标签定义为页面里的一个分割区或一个布局块。</span>

开发MXML时,使用Canvas标签<mx:Canvas>来指定一个容器。容器定义了一个矩形区域,里面可以继续填充容器和控件。在MXML里面(除了应用本身)Canvas标签是唯一允许你可以根据像素来指定子元素位置的容器。

你可以设置容器中子元素的x, y, top, left, right, bottom, baseline, horizontalCenter或verticalCenter属性。x, y, top, left, right, bottom, baseline, horizontalCenter和verticalCenter是特殊的属性(也可以看作样式),它们强制了子项在基于父容器的基础上,根据上,左,右,下,距中心的像素进行布局。当你给多个组件使用baseline属性,水平文字的基线取决于你选择的第一个组件。如果没有为Flex组件设置基线(比如HBox组件)那底边就是默认的基线。

如果你下载了第一页的代码范例,可以在Flex Builder 3中打开项目,选择并运行ConstraintBasedLayout.mxml。

下面的MXML代码将告诉你,如何使用<mx:Canvas>标签定义容器并通过指定象素值给canvas上的元素定位。

<strong>ConstraintBasedLayout.mxml</strong>
 <?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" 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>
默认情况下,Canvas容器(由Canvas标签<mx:Canvas>创建)的大小取决于其内容的尺寸,除非为它设置宽高。在你指定了容器宽高的情况下,如果其内容超出了范围,那么就会出现滚动条。你可以通过设置clipContent属性为false来阻止容器对其内部尺寸的限制。你也可以设置includeInLayout属性为false来阻止组件对容器布局的空间要求。

在Canvas容器中,你也可以使用水平布局盒和垂直布局盒(HBox和VBox)容器对用户界面元素布局。两者各自会对自身内部元素进行单列的水平布局和单行的垂直布局。设置元素的x, y, top, left, right, bottom, baseline, verticalCenter 或horizontalCenter不会起任何作用(当然有必要的话,你可以把HBox或VBox放在Canvas容器中)。这类容器中的每一个子元素,包括中间的space都会从上至下或从左至右排列。如果你想为子项间增加间隔,你可以为容器设置horizontalGap或verticalGap属性。你也可以用Spacer组件来调节间隔;设置高度和宽度正负值来增加或减少间隔大小。

还有很多其他布局容器,包括Grid容器,Form容器和List容器。Grid和HTML里面的table很像,Form则类似于两栏VBox。有了Grid, VBox或HBox容器,Repeater组件才得以实现根据提供的数据自动创建行或列。效果和你把数据绑定给List或DataGrid一样。

打开代码范例中的BoxBasedLayout.mxml文件,并运行应用。它会告诉你如何创建布局容器。

<strong>BoxBasedLayout.mxml</strong>
 <?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 SOME TEXT 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 SOME TEXT 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>
尽管Flex有内建的主体样式,但你可能仍然希望通过MXML来改变容器风格。你可以通过使用样式,添加外部CSS样式链接表,达到组件显示效果。Flex Builder有个Properties面板,包括了一系列可设置的属性。打开高级CSS设计视图选中一个特定的组件为它增加样式和皮肤。

当你需要格式化文字或修改组件的颜色就可以设置样式。用一张(或多张)图片作为皮肤为组件设置外观。当你设置组件皮肤时,你可以对图片进行九宫网格拉伸。这个功能可以使你在保持圆角和边缘不变化的情况下水平或垂直拉伸容器。如果你以前一直需要对图片进行切片然后导出HTML table,你就会对此功能非常满意。

在示例文件中运行StylingAndSkinning.mxml文件,你会了解到如何用css样式调整容器的外观。

<strong>StylingAndSkinning.mxml</strong>
 <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>

你也可以通过网上文档,了解更多关于容器,样式和皮肤的资料:
<ul><li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/html/help.html?content=layouts_03.html Canvas layout container]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/articles/skins_styles.html Designing Flex 3 skins and styles using Flex Builder 3]</li>
</ul>

<br/>

== <strong>使用GET方式,在php中实现表单提交</strong> ==
在html里,用以下语法实现GET方式:
 <form name="input" action="mypage.php" method="GET">
    Username:
    <input type="text" name="user"/>
    <input type="submit" value="Submit"/>
 </form>

上述代码把表单传到action属性值所指的URL中,本质上就是去访问链接中的PHP脚本。

要运行这个例子,选择SubmitUsingGet.mxml,然后在Flex例子项目中启动应用。
用GET方法,提交一张Flex表单,可以借鉴以下代码:<br/>
'''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>
接着你可以用下面的PHP页面来呈现发送的表单信息。
 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";
   }
 ?>

例子中使用了[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html HTTPService]类。看[http://livedocs.adobe.com/flex/3/langref/ Adobe Flex 3语言参考文档]里是什么怎么说的吧:
使用<mx:HTTPService>标签来表示MXML文件里的HTTPService对象。当你使用HTTPService对象的send方法时,它就给指定的URL发送了个HTTP请求。里面的参数可以根据需要来使用。如果你不用基于服务器的服务代理,那你只需要用HTTP的GET或POST方法。但如果你设置useProxy为true,并且还是使用基于服务器的服务代理,你也可以使用HTTP HEAD, OPTIONS, TRACE和DELETE方法。

你可以使用HTTPService组件连接PHP和SQL数据库管理系统,并呈现Flex应用里对数据库的请求或进行数据库插入等操作。你可以用GET或POST方式对PHP页面发送一个数据库请求。然后格式化返回的XML结构中的数据。当结果被返回给Flex应用时,你就可以通过界面把它呈现出来了。

你也可以指定信息,发送给服务器用来处理请求的对象。所要请求的对象是HTTPService里的一个属性。请求中,要指定发送给服务器的参数。这里就可以为text input字段username设置简单的数据绑定表达式标签。Flex提供了三种方法实现数据绑定。MXML里的花括号({})句法,MXML里的<mx:Binding>标签,和ActionScript里的BindingUtils方法。

请参考[http://livedocs.adobe.com/flex/3/html/databinding_1.html Adobe Flex3网上帮助]中的节选来了解数据绑定:
你可以使用花括号({})句法,<mx:Binding>标签或ActionScript中的BindingUtils方法为一个source属性绑定多个destination属性。使用花括号({})句法时,你只要把在充当目标属性值得source属性值的两侧套上它即可。

你也可以在ActionScript 3的表达式里面使用花括号。记住,数据可以不用局限于表单标签里的元素。

在这个例子中,表单提交给PHP,然后PHP通过表单数据罗列出数据,再返还给客户端。HTTPService类无需重载页面就可以接受一个HTTP反馈。resultFormat包含了通过HTTP请求返回的根据你要求进行格式化了的数据。用HTTPService标签,你就可以把resultFormat数据类型设为text。默认情况下,resultFormat返回一个Object对象。 通过给结果和错误事件增加特定的事件侦听器,你就可以响应请求返回的结果了。这个例子中,服务器返回的数据全都在textarea现实。

了解等多关于表单和数据绑定的网上资料:
<ul>
<li>[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html Adobe Flex 3 Language Reference: HTTPService class]</li>
<li>[http://www.adobe.com/devnet/flex/quickstart/using_data_binding Adobe Developer Connection: Flex Quick Start: Handling data, Using data binding]</li>
</ul>

<br/>

== '''使用POST方式,在php中实现表单提交''' ==
除了需要把方法属性值GET改为POST,使用POST方法提交表单的过程和使用GET方法提交是一样的。

下载示例文件,运行SubmitUsingPost.mxml文件查看应用。

如果你想在FLEX里使用POST方法提交表单,可以试试如下代码:

'''SubmitUsingPost.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 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";
   }
 ?>
上诉示例中,方法改为了POST。Actionscript3.0脚本块中增加了处理结果和错误的事件处理机制。当你从服务器得到结果或反馈时,result处理事件中所指定的方法就被执行了。如果请求失败——由于请求地址不正确——fault处理事件中所指定的方法就会被执行。

服务器的反馈传递给result处理事件中的event.result属性。默认情况下,event.result是一个object。通常,你需要再通过ResultFormat,把数据转化为指定的数据类型,比如string。在HTTPService标签中设置ResultFormat,来指明服务器需要返回的数据类型。ResultFormat属性值中所描述的数据类型可以是object, array, XML, E4X, flashvars或 text。例子中ResultFormat设为test,目的是让服务器返回的数据是string类型。

你可以使用HTTPService的lastResult属性,而不需要使用方法来获取返回值,或者换句话说即使用语法:myService.lastResult。lastResult属性和result属性是一样的。但它只有在result事件处理方法完成之后才有值。lastResult很容易使用,它总是包含着最新的数据。因此可以绑定给组件来显示最新的值。

<span style="color:gray">注意:Actionscript3.0的语法和JavaScript很像。两者都是基于ECMA标准的。就如范例代码中所示,事件监听器的声明也很方便。使用上一个例子里的PHP代码示例,可以显示出你所提交到PHP的表单。</span>

了解等多关于Actionscript3.0和表单操作的网上资料:
<ul><li>Adobe Flex 3 Language Reference:[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html HTTPService class]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Flex Quick Start: Handling data, Using data binding]</li>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/Part6_ProgAS_1.html Programming ActionScript 3.0] and [http://livedocs.adobe.com/flex/3/html/01_Introduction_1.html#123073 Introduction to ActionScript 3.0]</li>
</ul>

<br/>

== '''使用GET方法向Google提交表单''' ==
在一切可控的情况下,开发项目是比较容易的。在你的开发环境中,所创建的表单会提交给PHP文件并取回一串XML。这一章节,我们将告诉你如何把表单提交给google。

打开下载的[http://download.macromedia.com/pub/developer/flex_php_samples.zip 示例文档],运行名为SubmitFormToGoogle.mxml的文件。把Flex表单提交给Google,可以参考以下代码:

'''SubmitFormToGoogle.mxml''':
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
     layout="absolute" backgroundColor="#f6f6f6"
       backgroundGradientColors="[#f6f6f6, #bbbbbb]">
   <mx:Label x="10" y="10" text="Submit search to Google"
     fontSize="20" fontWeight="bold"/>
   <mx:HRule x="10" y="49" width="80%"/>
  
   <mx:HTTPService id="form1" url="http://www.google.com/search"
     method="GET" resultFormat="text"   result="{textarea1.text =
       String(event.result)}">
     <mx:request>
        <q>{search.text}</q>
     </mx:request>
   </mx:HTTPService>
   <mx:Label x="10" y="101" text="Result"/>
   <mx:TextArea x="10" y="118" width="234" height="188" id="textarea1"/>
   <mx:TextInput id="search" x="10"   y="71"/>
   <mx:Button x="178" y="71" label="Submit" click="form1.send()"/>
 </mx:Application>

在上面的例子中,表单通过GET方式提交。HTTPService类用来无刷新的实现接收HTTP反馈。Google search返回的结果显示在textarea中。你也可以用List或DataGrid组件来显示数据。

<span style="color:gray">注意:虽然这段代码能在本地工作,但上传到服务器上之后,会因为跨域访问而导致安全错误。为了能够访问远程站点(这里是Google),你需要增加一个cross-domain策略文件来实现SWF的跨域请求。cross-domain策略文件是一个在远程服务器根目录下的XML文件,其中所指定的域中的SWF都可以访问它的内容。如果服务器上没有这个文件(或者它里面没有指定你的SWF所在域)那你的应用就访问不到它的内容。一种解决方法是很多开发者使用的,在站点上建一个代理页面。——当然还有很多其他有效的方法从另一台服务器上获取数据(已列在本文的最后)。</span>

虽然返回的内容中有来自Google搜索的结果,你也可以试图把这结果转化为XML,但转换很可能会失败。因为大部分的XHTML页面使用的不是标准的XML。如果你想从Google上获得标准的XML搜索结果,就最好使用Google自己的API。

对于大部分的项目,当你想和远程服务器通信,使用文章之后谈到的策略访问域外的服务器是很常见的。[http://www.adobe.com/devnet/flex/articles/php_getstarted_13.html 让你的项目更进上一个层次]时,可以尝试使用下面列出的其他方法。

更多关于使用PHP代理页面的文章:[http://xmlrpcflash.mattism.com/proxy_info.php PHP Proxy for Flash Cross-Domain Security problems.]

通过网上文档,了解更多关于和远程服务器通信的资料:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/data_access_2.html#193905 Using HTTPService components: Working with PHP and SQL data]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Flex Quick Start: Handling data, Using data binding]</li>
<li>Working with Google services: [http://code.google.com/more/#products-apis-gdata Google Code Data APIs]</li>
<li>Adobe Developer Connection: [http://livedocs.adobe.com/flex/3/html/help.html?content=deployingoverview_12.html Cross Policy file changes in Flash Player 9 and 10]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/system/Security.html Security class]</li>
</ul>

<br/>

=='''把服务端的XML数据移植给list'''==
通常,你会创建一个表单发送到服务器,然后返回XML数据。HTTPService类会接收并抛出各种不同的数据类型,主要包括:object, array, XML, E4X, flashvars, 和text数据类型。如果类型是E4X,你就可以利用E4X提供给XML的等功能进行分类,过滤等相关操作。详情参看以下来自Adobe Flex网上文档的节选:

ECMAScript为XML规范定义了一系列的类和方法来处理XML数据。这些类是E4X的子集,ActionScript 3.0囊括了以下几个E4X类:XML, XMLList, QName, 和Namespace。

方法,属性和E4X类的操作遵循以下原则:
简单:只要是处理XML, 书写和理解E4X一向是很容易的。
一致:和ActionScript其他部分保持一致。
易学:使用熟知的表达式,诸如点语法。

跟着示例文档,运行PopulateListWithXML.mxml文件。

下面的范例代码会教你如何把发送表单给服务器再从服务器返回后的数据转化为E4X类型。这个应用中,结果会显示在TextArea中,然后把它绑定给List组件:

'''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
 ?>
上面的代码范例中,HTTPService类中的resultFormat用于让返回的数据根据E4X转化成XML。绑定标签用于把XML绑定到List组件上。绑定标签中的代码使用了E4X语法,对XML进行过滤,从而获取期望的节点。

<span style="color:gray">注意:你可以通过List组件里的labelField属性定义这行标签里显示的内容。当你使用XML时,你需要使用E4X语法描述标签字段,注意属性名前的"@"符号,它的意思是"label"字段是节点的一个属性。</span>

通过Adobe网上文档,了解更多关于XML和E4X的资料:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/help.html?content=13_Working_with_XML_01.html Working with XML]</li>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/13_Working_with_XML_03.html#119488 The E4X approach to XML processing]</li>
<li>Visual Components, [http://examples.adobe.com/flex3/componentexplorer/explorer.html General Controls, Lists: Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/List.html List class]</li>
<li>Adobe Developer Connection: Flex Quick Start: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Handling data, Using data binding]</li>
</ul>

<br/>

=='''URL页面跳转'''==

在HTML中,实现页面跳转,HTML使用document模板,加载的页面上会有一个指向另一个页面的链接。在Flex中,你可以在同一个应用中修改状态——而不是跳转到另一个网页(请看下一个章节:[http://www.adobe.com/devnet/flex/articles/php_getstarted_08.html 在Flex中切换状态])。两种方式都有他们各自的优势但是有时候你可能会希望在在一个新页面中打开。

在HTML页面中,使用如下代码实现页面跳转:
 <a href="mypage2.php">Go to Page 2</a>

在Flex中,使用[http://livedocs.adobe.com/labs/air/1/aslr/flash/net/package.html#navigateToURL() navigateToURL]方法进行跳转。这个方法会在一个指定的frame或窗口中加载URL。请参阅以下Flex文档节选:navigateToURL()方法会把一个指定的URL加载到某个窗口或frame,或者把变量传递给那个指定的URL。你可以使用这个方法来调用包含此Flex应用的HTML中的JavaScript。为了实现它,首先需要先创建一个URLRequest对象。下面是Flex文档中的另一段节选:

URLRequest类会捕获所有单个HTTP请求。这个请求里定义了一个URL的target,变量,方式(POST或GET),窗口,和请求的Headers信息。

查看[http://download.macromedia.com/pub/developer/flex_php_samples.zip 示例文件],运行NavigateToURL.mxml,以下MXML代码描述了在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"
        οnclick="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>
如果你想转到特定的frame或窗口。就要指定navigateToURL方法中第二个参数的名字。
通过Adobe网上文档,了解更多关于页面跳转的资料:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/labs/air/1/aslr/flash/net/package.html#navigateToURL() navigateToURL function]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html URLRequest class]</li>
</ul>

<br/>

=='''在Flex中切换状态'''==
切换状态(换洲)的意思不是指从明尼苏达到弗罗里达。在HTML里,你可以通过显示或隐藏页面上的特定元素实现。也可以在可视和不可视中切换状态。

在Flex中也有类似的但更强大的功能。当你想切换到一个新的状态,你可以通过添加或删除一个组件,设置属性,修改按钮行为,触发事件和触发的过渡效果等来实现。诸如Flex文档所说,全部的行为都可以“改变状态”。请看文档节选:

你可以使用Adobe Flex Builder 3来创建可根据用户不同行为和要求切换样子的应用。比如说:应用的基本状态是主页,logo,一些选项工具和问候语。当用户按了某一个选项,应用就动态变成了另一个样子(状态)。把主页的内容替换成一个订单,留下了logo和选项。

在Flex中,你可以通过view states和transitions增加切换时的交互。一个view state是包含在application或普通组件中几个view里面的一个。transition则是一个或一组用于view state间切换的效果,它可以让状态切换间的过渡变得平滑。

下面的例子会告诉你如何为Canvas组件切换状态。在HTML中,可以用以下代码显示或隐藏页面上的元素:
 <label>
   Show Hidden Element
   <input type="checkbox" name="checkbox" value="checkbox"
    οnclick="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>

运行示例文件中的ChangingStates.mxml。下面的代码描述了如何在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>

上面的例子中,当用户勾上“显示不同状态”选择框时,原来的表单变为高级搜索表单,在查找按钮上方新增加了个下拉框控件。之后,你还可以修改按钮的click事件。它就会请求advanced_search状态下的方法而不是基本状态下的方法。

上一个例子中,作为对照,也用到了ViewStack容器。当勾选框勾上时,显示的是ViewStack中的第二种状态,反之则是原来的状态。ViewStack容器中的每一个子项都是一个容器组件。请参阅如下文档节选:

在Adobe Flex中,Flex应用中的布局容器提供了一个层次架构来对其中的组件进行安排和配置,诸如Button和ComboBox控件。布局容器定义了一个矩形区,Adobe Flash Player可以在此绘画,控制此区域中子项的尺寸、位置和样子。比如一个表单容器中子项的尺寸和位置,类似于HTML表单。

在每一个容器里,你可以为用户呈现不同的视图和状态。在你的应用中,使用ViewStack和定义states的主要区别是:ViewStack组件会去呈现一套不同的组件,而states则可以让你自由操纵和移除已有的组件,或者增加新的组件。

<span style="color:gray">注意:有多种视图的容器,诸如ViewStack和Accordion容器,不会马上创建他们的所有的子项。它只去创建初始化的时候需要呈现的那一部分。Flex会直到导航里的视图需要呈现的时候才会加载他们。</span>

你可以设置容器的creationPolicy属性,创建出导航容器中所有可视组件。这一个设置可能会在运行时导致应用加载时的速度变慢,但是之后的切换都很快。对于states,你也可以使用给addChild标签设置creationPolicy属性来决定何时创建子组件。

States的API是很强壮的,它可以实现的东西比我们这里描述的多得多的多。你可以用States的API进行更多的探索。

通过Adobe网上文档,了解更多关于状态切换的内容:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/using_states_1.html Using View States]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/ViewStack.html ViewStack class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/Accordion.html Accordion class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/Alert.html Alert class]</li>
<li>Adobe Developer Connection: Flex Quick Start: [http://www.adobe.com/devnet/flex/quickstart/creating_states Creating states]</li>
<li>Visual Components, Containers, ViewStack: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Visual Components, General Controls, Alert: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Navigators, Accordion: [http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html Adobe Style Explorer]</li>
<li>Navigators, TabNavigator: [http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html Adobe Style Explorer]</li>
</ul>

<br/>

== '''下载文件''' ==
FileReference类实现了让你上传或下载文件的功能。上传和下载的行为和在HTML里没有什么区别。HTML中,使用以下代码下载文件:
 <a href="http://www.test.com/myfile.zip" >Download</a>

打开示例文件,运行FileDownload.mxml,在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>

<span style="color:gray">注意:在使用这个范例前,先过滤一下服务器上接收到的文件,以防有恶意脚本。</span>在Adobe Flex 3文档中就有一个这样的例子:[http://livedocs.adobe.com/flex/3/html/17_Networking_and_communications_7.html Working with file upload and download.]

通过Adobe网上文档,了解更多关于文件下载:
<ul>
<li>[http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html Adobe Flex 3 Language Reference: FileReference class]</li>
<li>[http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html Adobe Flex 3 Language Reference: URLRequest class]</li>
</ul>

<br/>

== '''上传文件给PHP''' ==
FileReference类也可以处理上传。这个类比传统的HTML文件上传提供了更多的优势——包括多个文件上传时的独立对话框,上传

进度,完成事件,上传类型等等。HTML中,使用如下代码进行上传:

 <form method="post" enctype="multipart/form-data" action="upload.php">
   File:
   <input type="file" name="filename"/>
   <input type="submit" value="Upload"/>
 </form>

运行示例文件中的FileUpload.mxm,以下是关于在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";
 ?>
<span style="color:gray">注意:在使用这个范例前,先确保已经过滤过服务器上接收到的文件乐,以防有恶意脚本。</span>查看Adobe Flex 3网上文档提供的示例:[http://livedocs.adobe.com/flex/3/html/help.html?content=17_Networking_and_communications_7.html Working with file upload and download].

通过Adobe网上文档,了解更多关于文件上传:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html FileReference class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html URLRequest class]</li>
</ul>

<br/>

(英文原文: [http://www.adobe.com/devnet/flex/articles/php_getstarted.html Flex quick start guide for PHP developers (updated for Flex 3)] ) <br/>
原作者:Judah Frangipane 翻译者:Maya

作为一个PHP和HTML开发者,你可能会想“对于Flex,我该如何起步?”Adobe的Flex是个很强壮的工具。但是“能力越强,责任越重。”

本文着重于介绍Flex,并为HTML和PHP开发者提供示例。HTML例子会告诉你HTML和MXML代码之前的差别。每一个部分都有独立的,可运行的例子供参考。例子中使用到PHP的地方都会有PHP代码。我会由浅入手,逐步深入,使用基本的代码帮你快速起步。本指南的目的就是要告诉你用Flex开发创建富互联网应用是件多么简单的事。

 登陆应用范例

这是个实际的应用,用户可以根据服务器验证个人信息,然后查看某些信息。通常,对于登陆表单的数据,安全性是很严格的,只有用户登陆之后,才能看到额外的信息。

这个例子突出的地方就是告诉你如何建立一个简单的登陆应用。当打开应用时,用户只能看到主页。一旦他们登陆,他们则能看到很多额外的视图并能从服务器获得额外的信息。如果鼠标或键盘在10分钟之内都没有相应,应用则做超时处理。发生之后,用户会自动等登出,应用也会变为给visitor看的状态。Flex框架被设计成可以保存session信息,也就是说只要他们再次登陆后,数据仍然保存在那里除非关闭应用。这对于用户来说是个很好的体验。

运行示例文建中的LoginApplication.mxml。下面的例子创建了一个简单的登陆应用。

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>
 
  <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)}"/>
  <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 "
            user" 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";
?>

上面的例子中,代码由两个ViewStack组件创建。第一个ViewStack组件包含了登陆表单。用户登陆的时候,会在登陆视图中显示。另一个 ViewStack组件包含了整个应用的内容。第一个视图用于主页,任何人都可以看。第二个视图是用户视图。只有用户成功登陆了,第二个导航菜单才会出现,用户视图随之出现。通过验证的用户可以在两个视图之间切换。

第二个视图上有一个表单,其数据来自服务器。当用户点击Get Authenticated Data按钮,就向服务器发出了一个请求。如果服务器上没有session,就会返回一条要求用户重新登陆的消息。

除此之外,在这个应用里还有一个内容:客户端超时机制。一旦用户登入,应用中的空闲事件就会被监听。如果应用空闲了超过设定的超时时间(例子中是10分钟),应用就会替用户登出,如果用户重新登陆了,他们仍然能看到表单数据,因为当用户切换状态的时候,它们没有被破坏。这取决于你构建的应用,可能你会想要清楚所有不相关的数据。你用Flex开发的话,这就取决于你了。

注意:看完示例代码后,你会发现脚本块在上方。这是个很好的习惯,因为在设计视图中增加组件的时候,Flex Builder会把组件定义在MXML文件的最后面。在MXML中,添加组件的顺序和根据z-index堆栈起来的顺序一致。举个例来说,如果你在 MXML代码里增加了两张图片,最近添加的一张image的标签在上一张的下方。

这个例子比之前的更进了一步。文章的这个部分涵盖了话题的主要方面,确保你同样阅读了代码中的注释。

通过Adobe Flex网上文档,了解更多用户验证:

    * Adobe Flex 3 Language Reference: LinkBar class
    * Visual Components, ButtonControls, LinkBar: Adobe Flex 3 Component Explorer
    * Buttons and LinkBar: Adobe Style Explorer
    * Adobe Flex 3 Language Reference: Canvas class
    * Visual Components, Containers, Canvas: Adobe Flex 3 Component Explorer
    * Adobe Flex 3 Language Reference: Alert class
    * Visual Components, General Controls, Alert: Adobe Flex 3 Component Explorer
    * Adobe Flex 3 Language Reference: HBox class
    * Visual Components, Containers, HBox: Adobe Flex 3 Component Explorer
    * Adobe Flex 3 Language Reference: ViewStack class
    * Visual Components, Containers, ViewStack: Adobe Flex 3 Component Explorer
    * Adobe Flex 3 Language Reference: ArrayCollection class
    * Adobe Flex 3 Language Reference: SystemManager class



== <strong>创建用户界面</strong> ==
Flex包括了一系列的设计标签,帮助你对MXML进行布局。
和HTML类似(使用标签设置页面上元素的位置和尺寸)。MXML包含的标签定义了SWF文件的显示方式。在HTML里,&lt;div&gt;标签常用于块元素,通过样式来进行格式化。

<span style="color:gray">注意:[http://www.w3.org/ W3C]把&lt;div&gt;标签定义为页面里的一个分割区或一个布局块。</span>

开发MXML时,使用Canvas标签<mx:Canvas>来指定一个容器。容器定义了一个矩形区域,里面可以继续填充容器和控件。在MXML里面(除了应用本身)Canvas标签是唯一允许你可以根据像素来指定子元素位置的容器。

你可以设置容器中子元素的x, y, top, left, right, bottom, baseline, horizontalCenter或verticalCenter属性。x, y, top, left, right, bottom, baseline, horizontalCenter和verticalCenter是特殊的属性(也可以看作样式),它们强制了子项在基于父容器的基础上,根据上,左,右,下,距中心的像素进行布局。当你给多个组件使用baseline属性,水平文字的基线取决于你选择的第一个组件。如果没有为Flex组件设置基线(比如HBox组件)那底边就是默认的基线。

如果你下载了第一页的代码范例,可以在Flex Builder 3中打开项目,选择并运行ConstraintBasedLayout.mxml。

下面的MXML代码将告诉你,如何使用<mx:Canvas>标签定义容器并通过指定象素值给canvas上的元素定位。

<strong>ConstraintBasedLayout.mxml</strong>
 <?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" 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>
默认情况下,Canvas容器(由Canvas标签<mx:Canvas>创建)的大小取决于其内容的尺寸,除非为它设置宽高。在你指定了容器宽高的情况下,如果其内容超出了范围,那么就会出现滚动条。你可以通过设置clipContent属性为false来阻止容器对其内部尺寸的限制。你也可以设置includeInLayout属性为false来阻止组件对容器布局的空间要求。

在Canvas容器中,你也可以使用水平布局盒和垂直布局盒(HBox和VBox)容器对用户界面元素布局。两者各自会对自身内部元素进行单列的水平布局和单行的垂直布局。设置元素的x, y, top, left, right, bottom, baseline, verticalCenter 或horizontalCenter不会起任何作用(当然有必要的话,你可以把HBox或VBox放在Canvas容器中)。这类容器中的每一个子元素,包括中间的space都会从上至下或从左至右排列。如果你想为子项间增加间隔,你可以为容器设置horizontalGap或verticalGap属性。你也可以用Spacer组件来调节间隔;设置高度和宽度正负值来增加或减少间隔大小。

还有很多其他布局容器,包括Grid容器,Form容器和List容器。Grid和HTML里面的table很像,Form则类似于两栏VBox。有了Grid, VBox或HBox容器,Repeater组件才得以实现根据提供的数据自动创建行或列。效果和你把数据绑定给List或DataGrid一样。

打开代码范例中的BoxBasedLayout.mxml文件,并运行应用。它会告诉你如何创建布局容器。

<strong>BoxBasedLayout.mxml</strong>
 <?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 SOME TEXT 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 SOME TEXT 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>
尽管Flex有内建的主体样式,但你可能仍然希望通过MXML来改变容器风格。你可以通过使用样式,添加外部CSS样式链接表,达到组件显示效果。Flex Builder有个Properties面板,包括了一系列可设置的属性。打开高级CSS设计视图选中一个特定的组件为它增加样式和皮肤。

当你需要格式化文字或修改组件的颜色就可以设置样式。用一张(或多张)图片作为皮肤为组件设置外观。当你设置组件皮肤时,你可以对图片进行九宫网格拉伸。这个功能可以使你在保持圆角和边缘不变化的情况下水平或垂直拉伸容器。如果你以前一直需要对图片进行切片然后导出HTML table,你就会对此功能非常满意。

在示例文件中运行StylingAndSkinning.mxml文件,你会了解到如何用css样式调整容器的外观。

<strong>StylingAndSkinning.mxml</strong>
 <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>

你也可以通过网上文档,了解更多关于容器,样式和皮肤的资料:
<ul><li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/html/help.html?content=layouts_03.html Canvas layout container]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/articles/skins_styles.html Designing Flex 3 skins and styles using Flex Builder 3]</li>
</ul>

<br/>

== <strong>使用GET方式,在php中实现表单提交</strong> ==
在html里,用以下语法实现GET方式:
 <form name="input" action="mypage.php" method="GET">
    Username:
    <input type="text" name="user"/>
    <input type="submit" value="Submit"/>
 </form>

上述代码把表单传到action属性值所指的URL中,本质上就是去访问链接中的PHP脚本。

要运行这个例子,选择SubmitUsingGet.mxml,然后在Flex例子项目中启动应用。
用GET方法,提交一张Flex表单,可以借鉴以下代码:<br/>
'''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>
接着你可以用下面的PHP页面来呈现发送的表单信息。
 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";
   }
 ?>

例子中使用了[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html HTTPService]类。看[http://livedocs.adobe.com/flex/3/langref/ Adobe Flex 3语言参考文档]里是什么怎么说的吧:
使用<mx:HTTPService>标签来表示MXML文件里的HTTPService对象。当你使用HTTPService对象的send方法时,它就给指定的URL发送了个HTTP请求。里面的参数可以根据需要来使用。如果你不用基于服务器的服务代理,那你只需要用HTTP的GET或POST方法。但如果你设置useProxy为true,并且还是使用基于服务器的服务代理,你也可以使用HTTP HEAD, OPTIONS, TRACE和DELETE方法。

你可以使用HTTPService组件连接PHP和SQL数据库管理系统,并呈现Flex应用里对数据库的请求或进行数据库插入等操作。你可以用GET或POST方式对PHP页面发送一个数据库请求。然后格式化返回的XML结构中的数据。当结果被返回给Flex应用时,你就可以通过界面把它呈现出来了。

你也可以指定信息,发送给服务器用来处理请求的对象。所要请求的对象是HTTPService里的一个属性。请求中,要指定发送给服务器的参数。这里就可以为text input字段username设置简单的数据绑定表达式标签。Flex提供了三种方法实现数据绑定。MXML里的花括号({})句法,MXML里的<mx:Binding>标签,和ActionScript里的BindingUtils方法。

请参考[http://livedocs.adobe.com/flex/3/html/databinding_1.html Adobe Flex3网上帮助]中的节选来了解数据绑定:
你可以使用花括号({})句法,<mx:Binding>标签或ActionScript中的BindingUtils方法为一个source属性绑定多个destination属性。使用花括号({})句法时,你只要把在充当目标属性值得source属性值的两侧套上它即可。

你也可以在ActionScript 3的表达式里面使用花括号。记住,数据可以不用局限于表单标签里的元素。

在这个例子中,表单提交给PHP,然后PHP通过表单数据罗列出数据,再返还给客户端。HTTPService类无需重载页面就可以接受一个HTTP反馈。resultFormat包含了通过HTTP请求返回的根据你要求进行格式化了的数据。用HTTPService标签,你就可以把resultFormat数据类型设为text。默认情况下,resultFormat返回一个Object对象。 通过给结果和错误事件增加特定的事件侦听器,你就可以响应请求返回的结果了。这个例子中,服务器返回的数据全都在textarea现实。

了解等多关于表单和数据绑定的网上资料:
<ul>
<li>[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html Adobe Flex 3 Language Reference: HTTPService class]</li>
<li>[http://www.adobe.com/devnet/flex/quickstart/using_data_binding Adobe Developer Connection: Flex Quick Start: Handling data, Using data binding]</li>
</ul>

<br/>

== '''使用POST方式,在php中实现表单提交''' ==
除了需要把方法属性值GET改为POST,使用POST方法提交表单的过程和使用GET方法提交是一样的。

下载示例文件,运行SubmitUsingPost.mxml文件查看应用。

如果你想在FLEX里使用POST方法提交表单,可以试试如下代码:

'''SubmitUsingPost.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 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";
   }
 ?>
上诉示例中,方法改为了POST。Actionscript3.0脚本块中增加了处理结果和错误的事件处理机制。当你从服务器得到结果或反馈时,result处理事件中所指定的方法就被执行了。如果请求失败——由于请求地址不正确——fault处理事件中所指定的方法就会被执行。

服务器的反馈传递给result处理事件中的event.result属性。默认情况下,event.result是一个object。通常,你需要再通过ResultFormat,把数据转化为指定的数据类型,比如string。在HTTPService标签中设置ResultFormat,来指明服务器需要返回的数据类型。ResultFormat属性值中所描述的数据类型可以是object, array, XML, E4X, flashvars或 text。例子中ResultFormat设为test,目的是让服务器返回的数据是string类型。

你可以使用HTTPService的lastResult属性,而不需要使用方法来获取返回值,或者换句话说即使用语法:myService.lastResult。lastResult属性和result属性是一样的。但它只有在result事件处理方法完成之后才有值。lastResult很容易使用,它总是包含着最新的数据。因此可以绑定给组件来显示最新的值。

<span style="color:gray">注意:Actionscript3.0的语法和JavaScript很像。两者都是基于ECMA标准的。就如范例代码中所示,事件监听器的声明也很方便。使用上一个例子里的PHP代码示例,可以显示出你所提交到PHP的表单。</span>

了解等多关于Actionscript3.0和表单操作的网上资料:
<ul><li>Adobe Flex 3 Language Reference:[http://livedocs.adobe.com/flex/3/langref/mx/rpc/http/mxml/HTTPService.html HTTPService class]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Flex Quick Start: Handling data, Using data binding]</li>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/Part6_ProgAS_1.html Programming ActionScript 3.0] and [http://livedocs.adobe.com/flex/3/html/01_Introduction_1.html#123073 Introduction to ActionScript 3.0]</li>
</ul>

<br/>

== '''使用GET方法向Google提交表单''' ==
在一切可控的情况下,开发项目是比较容易的。在你的开发环境中,所创建的表单会提交给PHP文件并取回一串XML。这一章节,我们将告诉你如何把表单提交给google。

打开下载的[http://download.macromedia.com/pub/developer/flex_php_samples.zip 示例文档],运行名为SubmitFormToGoogle.mxml的文件。把Flex表单提交给Google,可以参考以下代码:

'''SubmitFormToGoogle.mxml''':
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
     layout="absolute" backgroundColor="#f6f6f6"
       backgroundGradientColors="[#f6f6f6, #bbbbbb]">
   <mx:Label x="10" y="10" text="Submit search to Google"
     fontSize="20" fontWeight="bold"/>
   <mx:HRule x="10" y="49" width="80%"/>
  
   <mx:HTTPService id="form1" url="http://www.google.com/search"
     method="GET" resultFormat="text"   result="{textarea1.text =
       String(event.result)}">
     <mx:request>
        <q>{search.text}</q>
     </mx:request>
   </mx:HTTPService>
   <mx:Label x="10" y="101" text="Result"/>
   <mx:TextArea x="10" y="118" width="234" height="188" id="textarea1"/>
   <mx:TextInput id="search" x="10"   y="71"/>
   <mx:Button x="178" y="71" label="Submit" click="form1.send()"/>
 </mx:Application>

在上面的例子中,表单通过GET方式提交。HTTPService类用来无刷新的实现接收HTTP反馈。Google search返回的结果显示在textarea中。你也可以用List或DataGrid组件来显示数据。

<span style="color:gray">注意:虽然这段代码能在本地工作,但上传到服务器上之后,会因为跨域访问而导致安全错误。为了能够访问远程站点(这里是Google),你需要增加一个cross-domain策略文件来实现SWF的跨域请求。cross-domain策略文件是一个在远程服务器根目录下的XML文件,其中所指定的域中的SWF都可以访问它的内容。如果服务器上没有这个文件(或者它里面没有指定你的SWF所在域)那你的应用就访问不到它的内容。一种解决方法是很多开发者使用的,在站点上建一个代理页面。——当然还有很多其他有效的方法从另一台服务器上获取数据(已列在本文的最后)。</span>

虽然返回的内容中有来自Google搜索的结果,你也可以试图把这结果转化为XML,但转换很可能会失败。因为大部分的XHTML页面使用的不是标准的XML。如果你想从Google上获得标准的XML搜索结果,就最好使用Google自己的API。

对于大部分的项目,当你想和远程服务器通信,使用文章之后谈到的策略访问域外的服务器是很常见的。[http://www.adobe.com/devnet/flex/articles/php_getstarted_13.html 让你的项目更进上一个层次]时,可以尝试使用下面列出的其他方法。

更多关于使用PHP代理页面的文章:[http://xmlrpcflash.mattism.com/proxy_info.php PHP Proxy for Flash Cross-Domain Security problems.]

通过网上文档,了解更多关于和远程服务器通信的资料:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/data_access_2.html#193905 Using HTTPService components: Working with PHP and SQL data]</li>
<li>Adobe Developer Connection: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Flex Quick Start: Handling data, Using data binding]</li>
<li>Working with Google services: [http://code.google.com/more/#products-apis-gdata Google Code Data APIs]</li>
<li>Adobe Developer Connection: [http://livedocs.adobe.com/flex/3/html/help.html?content=deployingoverview_12.html Cross Policy file changes in Flash Player 9 and 10]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/system/Security.html Security class]</li>
</ul>

<br/>

=='''把服务端的XML数据移植给list'''==
通常,你会创建一个表单发送到服务器,然后返回XML数据。HTTPService类会接收并抛出各种不同的数据类型,主要包括:object, array, XML, E4X, flashvars, 和text数据类型。如果类型是E4X,你就可以利用E4X提供给XML的等功能进行分类,过滤等相关操作。详情参看以下来自Adobe Flex网上文档的节选:

ECMAScript为XML规范定义了一系列的类和方法来处理XML数据。这些类是E4X的子集,ActionScript 3.0囊括了以下几个E4X类:XML, XMLList, QName, 和Namespace。

方法,属性和E4X类的操作遵循以下原则:
简单:只要是处理XML, 书写和理解E4X一向是很容易的。
一致:和ActionScript其他部分保持一致。
易学:使用熟知的表达式,诸如点语法。

跟着示例文档,运行PopulateListWithXML.mxml文件。

下面的范例代码会教你如何把发送表单给服务器再从服务器返回后的数据转化为E4X类型。这个应用中,结果会显示在TextArea中,然后把它绑定给List组件:

'''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
 ?>
上面的代码范例中,HTTPService类中的resultFormat用于让返回的数据根据E4X转化成XML。绑定标签用于把XML绑定到List组件上。绑定标签中的代码使用了E4X语法,对XML进行过滤,从而获取期望的节点。

<span style="color:gray">注意:你可以通过List组件里的labelField属性定义这行标签里显示的内容。当你使用XML时,你需要使用E4X语法描述标签字段,注意属性名前的"@"符号,它的意思是"label"字段是节点的一个属性。</span>

通过Adobe网上文档,了解更多关于XML和E4X的资料:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/help.html?content=13_Working_with_XML_01.html Working with XML]</li>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/13_Working_with_XML_03.html#119488 The E4X approach to XML processing]</li>
<li>Visual Components, [http://examples.adobe.com/flex3/componentexplorer/explorer.html General Controls, Lists: Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/List.html List class]</li>
<li>Adobe Developer Connection: Flex Quick Start: [http://www.adobe.com/devnet/flex/quickstart/using_data_binding Handling data, Using data binding]</li>
</ul>

<br/>

=='''URL页面跳转'''==

在HTML中,实现页面跳转,HTML使用document模板,加载的页面上会有一个指向另一个页面的链接。在Flex中,你可以在同一个应用中修改状态——而不是跳转到另一个网页(请看下一个章节:[http://www.adobe.com/devnet/flex/articles/php_getstarted_08.html 在Flex中切换状态])。两种方式都有他们各自的优势但是有时候你可能会希望在在一个新页面中打开。

在HTML页面中,使用如下代码实现页面跳转:
 <a href="mypage2.php">Go to Page 2</a>

在Flex中,使用[http://livedocs.adobe.com/labs/air/1/aslr/flash/net/package.html#navigateToURL() navigateToURL]方法进行跳转。这个方法会在一个指定的frame或窗口中加载URL。请参阅以下Flex文档节选:navigateToURL()方法会把一个指定的URL加载到某个窗口或frame,或者把变量传递给那个指定的URL。你可以使用这个方法来调用包含此Flex应用的HTML中的JavaScript。为了实现它,首先需要先创建一个URLRequest对象。下面是Flex文档中的另一段节选:

URLRequest类会捕获所有单个HTTP请求。这个请求里定义了一个URL的target,变量,方式(POST或GET),窗口,和请求的Headers信息。

查看[http://download.macromedia.com/pub/developer/flex_php_samples.zip 示例文件],运行NavigateToURL.mxml,以下MXML代码描述了在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"
        οnclick="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>
如果你想转到特定的frame或窗口。就要指定navigateToURL方法中第二个参数的名字。
通过Adobe网上文档,了解更多关于页面跳转的资料:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/labs/air/1/aslr/flash/net/package.html#navigateToURL() navigateToURL function]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html URLRequest class]</li>
</ul>

<br/>

=='''在Flex中切换状态'''==
切换状态(换洲)的意思不是指从明尼苏达到弗罗里达。在HTML里,你可以通过显示或隐藏页面上的特定元素实现。也可以在可视和不可视中切换状态。

在Flex中也有类似的但更强大的功能。当你想切换到一个新的状态,你可以通过添加或删除一个组件,设置属性,修改按钮行为,触发事件和触发的过渡效果等来实现。诸如Flex文档所说,全部的行为都可以“改变状态”。请看文档节选:

你可以使用Adobe Flex Builder 3来创建可根据用户不同行为和要求切换样子的应用。比如说:应用的基本状态是主页,logo,一些选项工具和问候语。当用户按了某一个选项,应用就动态变成了另一个样子(状态)。把主页的内容替换成一个订单,留下了logo和选项。

在Flex中,你可以通过view states和transitions增加切换时的交互。一个view state是包含在application或普通组件中几个view里面的一个。transition则是一个或一组用于view state间切换的效果,它可以让状态切换间的过渡变得平滑。

下面的例子会告诉你如何为Canvas组件切换状态。在HTML中,可以用以下代码显示或隐藏页面上的元素:
 <label>
   Show Hidden Element
   <input type="checkbox" name="checkbox" value="checkbox"
    οnclick="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>

运行示例文件中的ChangingStates.mxml。下面的代码描述了如何在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>

上面的例子中,当用户勾上“显示不同状态”选择框时,原来的表单变为高级搜索表单,在查找按钮上方新增加了个下拉框控件。之后,你还可以修改按钮的click事件。它就会请求advanced_search状态下的方法而不是基本状态下的方法。

上一个例子中,作为对照,也用到了ViewStack容器。当勾选框勾上时,显示的是ViewStack中的第二种状态,反之则是原来的状态。ViewStack容器中的每一个子项都是一个容器组件。请参阅如下文档节选:

在Adobe Flex中,Flex应用中的布局容器提供了一个层次架构来对其中的组件进行安排和配置,诸如Button和ComboBox控件。布局容器定义了一个矩形区,Adobe Flash Player可以在此绘画,控制此区域中子项的尺寸、位置和样子。比如一个表单容器中子项的尺寸和位置,类似于HTML表单。

在每一个容器里,你可以为用户呈现不同的视图和状态。在你的应用中,使用ViewStack和定义states的主要区别是:ViewStack组件会去呈现一套不同的组件,而states则可以让你自由操纵和移除已有的组件,或者增加新的组件。

<span style="color:gray">注意:有多种视图的容器,诸如ViewStack和Accordion容器,不会马上创建他们的所有的子项。它只去创建初始化的时候需要呈现的那一部分。Flex会直到导航里的视图需要呈现的时候才会加载他们。</span>

你可以设置容器的creationPolicy属性,创建出导航容器中所有可视组件。这一个设置可能会在运行时导致应用加载时的速度变慢,但是之后的切换都很快。对于states,你也可以使用给addChild标签设置creationPolicy属性来决定何时创建子组件。

States的API是很强壮的,它可以实现的东西比我们这里描述的多得多的多。你可以用States的API进行更多的探索。

通过Adobe网上文档,了解更多关于状态切换的内容:
<ul>
<li>Adobe Flex 3 Help: [http://livedocs.adobe.com/flex/3/html/using_states_1.html Using View States]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/ViewStack.html ViewStack class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/Accordion.html Accordion class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/Alert.html Alert class]</li>
<li>Adobe Developer Connection: Flex Quick Start: [http://www.adobe.com/devnet/flex/quickstart/creating_states Creating states]</li>
<li>Visual Components, Containers, ViewStack: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Visual Components, General Controls, Alert: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Navigators, Accordion: [http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html Adobe Style Explorer]</li>
<li>Navigators, TabNavigator: [http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html Adobe Style Explorer]</li>
</ul>

<br/>

== '''下载文件''' ==
FileReference类实现了让你上传或下载文件的功能。上传和下载的行为和在HTML里没有什么区别。HTML中,使用以下代码下载文件:
 <a href="http://www.test.com/myfile.zip" >Download</a>

打开示例文件,运行FileDownload.mxml,在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>

<span style="color:gray">注意:在使用这个范例前,先过滤一下服务器上接收到的文件,以防有恶意脚本。</span>在Adobe Flex 3文档中就有一个这样的例子:[http://livedocs.adobe.com/flex/3/html/17_Networking_and_communications_7.html Working with file upload and download.]

通过Adobe网上文档,了解更多关于文件下载:
<ul>
<li>[http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html Adobe Flex 3 Language Reference: FileReference class]</li>
<li>[http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html Adobe Flex 3 Language Reference: URLRequest class]</li>
</ul>

<br/>

== '''上传文件给PHP''' ==
FileReference类也可以处理上传。这个类比传统的HTML文件上传提供了更多的优势——包括多个文件上传时的独立对话框,上传

进度,完成事件,上传类型等等。HTML中,使用如下代码进行上传:

 <form method="post" enctype="multipart/form-data" action="upload.php">
   File:
   <input type="file" name="filename"/>
   <input type="submit" value="Upload"/>
 </form>

运行示例文件中的FileUpload.mxm,以下是关于在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";
 ?>
<span style="color:gray">注意:在使用这个范例前,先确保已经过滤过服务器上接收到的文件乐,以防有恶意脚本。</span>查看Adobe Flex 3网上文档提供的示例:[http://livedocs.adobe.com/flex/3/html/help.html?content=17_Networking_and_communications_7.html Working with file upload and download].

通过Adobe网上文档,了解更多关于文件上传:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html FileReference class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html URLRequest class]</li>
</ul>

<br/>

== '''登陆应用范例''' ==
这是个实际的应用,用户可以根据服务器验证个人信息,然后查看某些信息。通常,对于登陆表单的数据,安全性是很严格的,只有用户登陆之后,才能看到额外的信息。

这个例子突出的地方就是告诉你如何建立一个简单的登陆应用。当打开应用时,用户只能看到主页。一旦他们登陆,他们则能看到很多额外的视图并能从服务器获得额外的信息。如果鼠标或键盘在10分钟之内都没有相应,应用则做超时处理。发生之后,用户会自动等登出,应用也会变为给visitor看的状态。Flex框架被设计成可以保存session信息,也就是说只要他们再次登陆后,数据仍然保存在那里除非关闭应用。这对于用户来说是个很好的体验。

运行示例文建中的LoginApplication.mxml。下面的例子创建了一个简单的登陆应用。

'''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";
 ?>
上面的例子中,代码由两个ViewStack组件创建。第一个ViewStack组件包含了登陆表单。用户登陆的时候,会在登陆视图中显示。另一个ViewStack组件包含了整个应用的内容。第一个视图用于主页,任何人都可以看。第二个视图是用户视图。只有用户成功登陆了,第二个导航菜单才会出现,用户视图随之出现。通过验证的用户可以在两个视图之间切换。

第二个视图上有一个表单,其数据来自服务器。当用户点击Get Authenticated Data按钮,就向服务器发出了一个请求。如果服务器上没有session,就会返回一条要求用户重新登陆的消息。

除此之外,在这个应用里还有一个内容:客户端超时机制。一旦用户登入,应用中的空闲事件就会被监听。如果应用空闲了超过设定的超时时间(例子中是10分钟),应用就会替用户登出,如果用户重新登陆了,他们仍然能看到表单数据,因为当用户切换状态的时候,它们没有被破坏。这取决于你构建的应用,可能你会想要清楚所有不相关的数据。你用Flex开发的话,这就取决于你了。

<span style="color:gray">注意:看完示例代码后,你会发现脚本块在上方。这是个很好的习惯,因为在设计视图中增加组件的时候,Flex Builder会把组件定义在MXML文件的最后面。在MXML中,添加组件的顺序和根据z-index堆栈起来的顺序一致。举个例来说,如果你在MXML代码里增加了两张图片,最近添加的一张image的标签在上一张的下方。</span>

这个例子比之前的更进了一步。文章的这个部分涵盖了话题的主要方面,确保你同样阅读了代码中的注释。

通过Adobe Flex网上文档,了解更多用户验证:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/LinkBar.html LinkBar class]</li>
<li>Visual Components, ButtonControls, LinkBar: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer] </li>
<li>Buttons and LinkBar: [http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html Adobe Style Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/Canvas.html Canvas class]</li>
<li>Visual Components, Containers, Canvas: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/Alert.html Alert class]</li>
<li>Visual Components, General Controls, Alert: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/HBox.html HBox class]</li>
<li>Visual Components, Containers, HBox: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/containers/ViewStack.html ViewStack class]</li>
<li>Visual Components, Containers, ViewStack: [http://examples.adobe.com/flex3/componentexplorer/explorer.html Adobe Flex 3 Component Explorer]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/collections/ArrayCollection.html ArrayCollection class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/managers/SystemManager.html SystemManager class]</li>
</ul>

<br/>

== '''把从PHP读来的数据移植给DataGrid''' ==
既然用Flex开发过应用了,那么把XML数据显示在DataGrid上就很平常了。这个例子会告诉你如何把数据提交到服务器,然后把返回的XML显示在DataGrid中。

如果你下载了示例文档,请右击PopulatingDataGridWithXML.mxml文件并选择run the application。以下的代码用于把XML数据显示给DataGrid。

'''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
 ?>

通过Adobe Flex网上文档,了解更多关于DataGrid的操作:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/DataGrid.html DataGrid class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/collections/ArrayCollection.html ArrayCollection class]</li>
</ul>

<br/>

== '''进一步提升你的项目''' ==

<br/>
Flex提供了很多具有大量其他特点和优势的途径来和php沟通,而不单单只有HTTPService类。请看以下官方文档节选:

Flex提供了数种客户端接收数据的解决方案。它通过“RuntimeServices”请求PHP类里的方法来提供数据,并把代理请求发送给web services或HTTP server。

WebService的组件使您可以使用构建基于SOAP的协议。但这不是最好的。SOAP编码中的XML所需的开销远大于AMF。

[http://www.adobe.com/devnet/flex/articles/php_getstarted_13.html Action Message Format — AMF 3]是Adobe独家的远程对象:比HTTP服务请求快很多,因为它是经过压缩了的。序列化的数据也便于你直接使用。AMF是远程过程调用服务里的一种,引用Patrick Mineault的话来说:

RPC(远程过程调用)是让客户端和服务器端交互的一种方法。你可以调用含有参数的本地方法,设置回调事件,并接收数据。你不用担心要怎么发送和接收数据,服务端和客户端,即PHP和Flash,会使用一种共识的通用方法描述调用方法和复杂数据。实现细节经过抽象化后,会使你觉得像在调用本地方法一样。

连接AMF和PHP,你可以使用[http://sourceforge.net/projects/amfphp AMFPHP]或者[http://www.themidnightcoders.com/weborb/php WebORB]。

=== AMFPHP ===
[http://sourceforge.net/projects/amfphp AMFPHP]是个用于PHP的RPC工具包。 它实现了PHP和以下技术的无缝交流。

使用Remoting的Flash和Flex
使用JSON的JavaScript和AJAX
使用XML-RPC的XML委托

=== WebORB for PHP ===
[http://www.themidnightcoders.com/weborb/php Midnight Coders' WebORB for PHP]是开发,部署,运行RIA的平台。它简化了用Flex, Flash或AJAX等创建的富客户端和用.NET, Java, Ruby on Rails, PHP或XML web services创建的服务端之间的连接。

*AMFPHP的开源
*双证: 拥有GPL和商业许可证
*实现了AMF0, AMF3和Flex数据服务(Flex RPC)
*商业版中完全实现了Flex数据管理服务的功能

=== PHP和Zend框架 + Zend AMF ===
沿袭了PHP的艺术和精神, [http://framework.zend.com/ Zend框架]([http://framework.zend.com/download/amf Zend AMF])的优点在于简洁、面向对象最佳实践、友好的版权协议和严格测试的代码库。另外,Zend致力于创建更加安全,可靠和现代的WEB2.0项目及Web服务,并提供了很多用于访问API的类库,你可以很方便地访问Google、 Amazon、 Yahoo!、Flickr,还有[http://www.strikeiron.com/ StrikeIron]和[http://www.programmableweb.com/ ProgrammableWeb]等网站提供的服务。


检出[http://framework.zend.com/manual/en/zend.amf.html Zend AMF相关编码指导]

了解更多关于Zend框架,请参阅: [http://www.adobe.com/devnet/flex/articles/flex_php.html 在Eclipse中使用Flex和PHP]

<br/>

== '''想了解更多''' ==
除了本文提到的,Flex还有更多的功能。为了更好得使用Flex,几十年奋斗在这行业的开发者主动响应Flex网上社区的号召,把这些写下来提供给其他开发者。如果你在这里发现了省时的Flex新功能,那你就会意识到它的优点,并最大化的减少开发时间和成本。
 
访问以下内容了解更多:

*[http://www.apachefriends.org/en/xampp.html XAMPP]: Easy to install Apache distribution containing MySQL, PHP and Perl
*[http://www.mamp.info/en/mamp.html MAMP]: Install Apache, PHP and MySQL for Mac OS×with a few clicks!
*[http://livedocs.adobe.com/flex/3/langref/index.html Adobe Flex 3 Language Reference]: The Flex framework API
*[http://livedocs.adobe.com/flex/3/html/help.html Adobe Flex 3 Help]: The official Adobe Flex online documentation
*[http://www.adobe.com/cfusion/webforums/forum/index.cfm?forumid=60 Adobe Flex Support Forums]: Community support and inspiration
*[http://tech.groups.yahoo.com/group/flexcoders FlexCoders]: Find answers to coding issues and post questions to the Flex community
*[http://www.themidnightcoders.com/products/weborb-for-php/overview.html WebORB for PHP]: Runtime environment that connects Flex and Flash with PHP
*[http://sourceforge.net/projects/amfphp AMFPHP]: Provides seamless data exchange between PHP and Flash Player
*[http://framework.zend.com/wiki/display/ZFPROP/Zend_Amf+-+Wade+Arnold Zend AMF]: A framework that supports Flash Player 9 and above
*[http://flex.org Flex.org]: A community portal with resources for new and experienced Flex users
*[http://www.riapedia.com Mike Potter's RIApedia]: A helpful blog about building RIAs with Flex
*[http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform Adobe Feature Request/Bug Report Form]: Send feedback to the Adobe Wishlist
*[http://tv.adobe.com/#vi+f1472v1042 Connect to your database using the PHP data wizard]
*[http://tv.adobe.com/#vi+f1472v1034 Debugging Flex and PHP projects]

<br/>

== '''关于作者''' ==
Judah Frangipane是位用户体验和设计开发者,他从1996年开始就进入了web行业。他曾经在Roxio,Parsons和T8DESIGNS工作过。现在他是个自由顾问。自从从Flash MX和Flex 2诞生就和Flash相伴至今,做过很多商业方面的Flex项目,现在他的项目是针对网络专业人和设计师的,使他们能够自由设计和创造而不需要写任何代码。不工作的时候,Judah喜欢远足,滑雪享受人生。

Pete Mackie是为软件开发者和报刊发行人。头十年服务于一家大公司,然后创办了他自己的公司,Seaquest软件,30年前是很强大的一家公司。最近他作为一名志愿者致力于Eclipse IDE项目的开发。并且为刚起步的小公司构建基于PHP的网站。Pete在参加EclipseCon2006大会的时候偶遇了Adobe的摊位。在驻足琢磨Adobe在开源分会上享做什么的时候,突然意识到Flex可以作为RIA应用,然后他飞奔回家,安装了Flex Builder 2 beta版,就此就迷上了Flex软件开发。

== '''把从PHP读来的数据移植给DataGrid''' ==
既然用Flex开发过应用了,那么把XML数据显示在DataGrid上就很平常了。这个例子会告诉你如何把数据提交到服务器,然后把返回的XML显示在DataGrid中。

如果你下载了示例文档,请右击PopulatingDataGridWithXML.mxml文件并选择run the application。以下的代码用于把XML数据显示给DataGrid。

'''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
 ?>

通过Adobe Flex网上文档,了解更多关于DataGrid的操作:
<ul>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/controls/DataGrid.html DataGrid class]</li>
<li>Adobe Flex 3 Language Reference: [http://livedocs.adobe.com/flex/3/langref/mx/collections/ArrayCollection.html ArrayCollection class]</li>
</ul>

<br/>

== '''进一步提升你的项目''' ==

<br/>
Flex提供了很多具有大量其他特点和优势的途径来和php沟通,而不单单只有HTTPService类。请看以下官方文档节选:

Flex提供了数种客户端接收数据的解决方案。它通过“RuntimeServices”请求PHP类里的方法来提供数据,并把代理请求发送给web services或HTTP server。

WebService的组件使您可以使用构建基于SOAP的协议。但这不是最好的。SOAP编码中的XML所需的开销远大于AMF。

[http://www.adobe.com/devnet/flex/articles/php_getstarted_13.html Action Message Format — AMF 3]是Adobe独家的远程对象:比HTTP服务请求快很多,因为它是经过压缩了的。序列化的数据也便于你直接使用。AMF是远程过程调用服务里的一种,引用Patrick Mineault的话来说:

RPC(远程过程调用)是让客户端和服务器端交互的一种方法。你可以调用含有参数的本地方法,设置回调事件,并接收数据。你不用担心要怎么发送和接收数据,服务端和客户端,即PHP和Flash,会使用一种共识的通用方法描述调用方法和复杂数据。实现细节经过抽象化后,会使你觉得像在调用本地方法一样。

连接AMF和PHP,你可以使用[http://sourceforge.net/projects/amfphp AMFPHP]或者[http://www.themidnightcoders.com/weborb/php WebORB]。

=== AMFPHP ===
[http://sourceforge.net/projects/amfphp AMFPHP]是个用于PHP的RPC工具包。 它实现了PHP和以下技术的无缝交流。

使用Remoting的Flash和Flex
使用JSON的JavaScript和AJAX
使用XML-RPC的XML委托

=== WebORB for PHP ===
[http://www.themidnightcoders.com/weborb/php Midnight Coders' WebORB for PHP]是开发,部署,运行RIA的平台。它简化了用Flex, Flash或AJAX等创建的富客户端和用.NET, Java, Ruby on Rails, PHP或XML web services创建的服务端之间的连接。

*AMFPHP的开源
*双证: 拥有GPL和商业许可证
*实现了AMF0, AMF3和Flex数据服务(Flex RPC)
*商业版中完全实现了Flex数据管理服务的功能

=== PHP和Zend框架 + Zend AMF ===
沿袭了PHP的艺术和精神, [http://framework.zend.com/ Zend框架]([http://framework.zend.com/download/amf Zend AMF])的优点在于简洁、面向对象最佳实践、友好的版权协议和严格测试的代码库。另外,Zend致力于创建更加安全,可靠和现代的WEB2.0项目及Web服务,并提供了很多用于访问API的类库,你可以很方便地访问Google、 Amazon、 Yahoo!、Flickr,还有[http://www.strikeiron.com/ StrikeIron]和[http://www.programmableweb.com/ ProgrammableWeb]等网站提供的服务。


检出[http://framework.zend.com/manual/en/zend.amf.html Zend AMF相关编码指导]

了解更多关于Zend框架,请参阅: [http://www.adobe.com/devnet/flex/articles/flex_php.html 在Eclipse中使用Flex和PHP]

<br/>

== '''想了解更多''' ==
除了本文提到的,Flex还有更多的功能。为了更好得使用Flex,几十年奋斗在这行业的开发者主动响应Flex网上社区的号召,把这些写下来提供给其他开发者。如果你在这里发现了省时的Flex新功能,那你就会意识到它的优点,并最大化的减少开发时间和成本。
 
访问以下内容了解更多:

*[http://www.apachefriends.org/en/xampp.html XAMPP]: Easy to install Apache distribution containing MySQL, PHP and Perl
*[http://www.mamp.info/en/mamp.html MAMP]: Install Apache, PHP and MySQL for Mac OS×with a few clicks!
*[http://livedocs.adobe.com/flex/3/langref/index.html Adobe Flex 3 Language Reference]: The Flex framework API
*[http://livedocs.adobe.com/flex/3/html/help.html Adobe Flex 3 Help]: The official Adobe Flex online documentation
*[http://www.adobe.com/cfusion/webforums/forum/index.cfm?forumid=60 Adobe Flex Support Forums]: Community support and inspiration
*[http://tech.groups.yahoo.com/group/flexcoders FlexCoders]: Find answers to coding issues and post questions to the Flex community
*[http://www.themidnightcoders.com/products/weborb-for-php/overview.html WebORB for PHP]: Runtime environment that connects Flex and Flash with PHP
*[http://sourceforge.net/projects/amfphp AMFPHP]: Provides seamless data exchange between PHP and Flash Player
*[http://framework.zend.com/wiki/display/ZFPROP/Zend_Amf+-+Wade+Arnold Zend AMF]: A framework that supports Flash Player 9 and above
*[http://flex.org Flex.org]: A community portal with resources for new and experienced Flex users
*[http://www.riapedia.com Mike Potter's RIApedia]: A helpful blog about building RIAs with Flex
*[http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform Adobe Feature Request/Bug Report Form]: Send feedback to the Adobe Wishlist
*[http://tv.adobe.com/#vi+f1472v1042 Connect to your database using the PHP data wizard]
*[http://tv.adobe.com/#vi+f1472v1034 Debugging Flex and PHP projects]

<br/>

== '''关于作者''' ==
Judah Frangipane是位用户体验和设计开发者,他从1996年开始就进入了web行业。他曾经在Roxio,Parsons和T8DESIGNS工作过。现在他是个自由顾问。自从从Flash MX和Flex 2诞生就和Flash相伴至今,做过很多商业方面的Flex项目,现在他的项目是针对网络专业人和设计师的,使他们能够自由设计和创造而不需要写任何代码。不工作的时候,Judah喜欢远足,滑雪享受人生。

Pete Mackie是为软件开发者和报刊发行人。头十年服务于一家大公司,然后创办了他自己的公司,Seaquest软件,30年前是很强大的一家公司。最近他作为一名志愿者致力于Eclipse IDE项目的开发。并且为刚起步的小公司构建基于PHP的网站。Pete在参加EclipseCon2006大会的时候偶遇了Adobe的摊位。在驻足琢磨Adobe在开源分会上享做什么的时候,突然意识到Flex可以作为RIA应用,然后他飞奔回家,安装了Flex Builder 2 beta版,就此就迷上了Flex软件开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值