付江ID:java060515
240375次访问,排名259好友22人,关注者200
关注软件开发和互联网业界
java060515的文章
原创 26 篇
翻译 37 篇
转载 42 篇
评论 404 篇
付江的公告
最近评论
spkl1:spkl.net<br/>
济南炫客网络工作室
spkl1:spkl.net<br/>
济南炫客网络工作室
spkl1:spkl.net<br/>
济南炫客网络工作室
spkl1:spkl.net<br/>
济南炫客网络工作室
copydogcn:学习一下哦.不错
文章分类
    收藏
      相册
      存档
      软件项目交易
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      转载 Flex中的MySQL管理收藏

      新一篇: 利用Adobe AIR创建桌面对话应用程序 | 旧一篇: NetBeans Web开发中设置页面导航

       
      学习使用RIA Framework Flex创建MySQL管理UI
      PHPMyAdmin的出现震撼了业界,这毫无疑问。它当然是基于PHP的最佳应用程序,因为它将MySQL管理界面由命令行的形式改为了web浏览器的形式。不过,虽然它的功能很强大,但使用并不太方便,界面也不够美观。因此,我尝试通过Rich Internet Application框架设计更理想的MySQL前台管理程序。
      要达成此目标本可选用Ajax。但我不想处理客户端的不兼容问题。当然,Silverlight也是不错的选择,但它仍不够成熟。之所以选择Adobe Flex,是因为它拥有富用户接口工具集和方便的web服务集成功能,而且它生成的Flash应用程序能够以相同方式在任何操作系统中运行。
      我学习了很多有关创建应用程序方面的知识:如何为PHP程序创建安全的SQL web服务;如何通过Flex访问web服务;如何将web服务返回的数据输入数据网格中并显示。在本文中,我将引领读者从前台到后台,逐步创建MySQL管理程序。读者从中可了解一些有用的信息,以创建自己的Rich Internet应用程序。
      创建后台程序
      Flex应用程序擅长与web服务通讯,以发出请求及提交数据。因此,首先需要创建一个非常简单的PHP脚本,它将以XML格式返回数据库列表、表或表中的数据。
      清单 1. req.php
      <?php
      require_once("MDB2.php");
      $sql = 'SHOW DATABASES';
      if ( $_REQUEST['mode'] == 'getTables' )
      $sql = 'SHOW TABLES';
      if ( $_REQUEST['mode'] == 'getData' )
      $sql = 'SELECT * FROM '.$_REQUEST['table'];
      $dsn = 'mysql://root@localhost/'.$_REQUEST['db'];
      $mdb2 =& MDB2::factory($dsn);
      if (PEAR::isError($mdb2)) { die($mdb2->getMessage()); }
      $dom = new DomDocument();
      $dom->formatOutput = true;
      $root = $dom->createElement( "records" );
      $dom->appendChild( $root );
      $res =& $mdb2->query( $sql );
      if (PEAR::isError($mdb2)) { die($mdb2->getMessage()); }
      while ($row = $res->fetchRow(MDB2_FETCHMODE_ASSOC))
      {
      $rec = $dom->createElement( "record" );
      $root->appendChild( $rec );
      foreach( array_keys( $row ) as $key ) {
      $key_elem = $dom->createElement( $key );
      $rec->appendChild( $key_elem );
      $key_elem->appendChild( $dom->createTextNode( $row[$key] ) );
      }
      }
      $res->free();
      $mdb2->disconnect();
      header( "Content-type: text/xml" );
      echo $dom->saveXML();
      ?>
      该脚本的第一项工作就是利用MDB2库连接数据库。如果没有安装MDB2库,则可使用PEAR安装该库,如下所示:
      % pear install MDB2
      %
      如果PEAR无法正常运行,可访问http://pear.php.net/mdb2,然后下载源代码并将其解包到PHPinclude路径下。MDB2是通用的数据库适配器层,它已取代了广为使用的PEAR DB库。
      脚本的第二项工作就是创建XML DOM Document对象,该对象将用来创建要输出的XML树。从此处开始,它将运行查询,并在XML树中添加rowcolumn作为XML标签。最后,该脚本将关闭所有连接,并将XML保存到PHP输出流中。
      选用XML DOM对象的原因是,它可避免任何与数据、不对称标签等有关的编码问题以及各种可能使XML产生混乱的因素。我可以将调试XML数据流的时间节省下来做其他许多更有意义的工作。您一定也会这样做。
      将该脚本安装到本地机器上的可运行目录下,然后使用curl命令向服务器发出请求。
      % curl "http://localhost/sql/req.php"
      <?xml version="1.0"?>
      <records>
      <record>
      <database>addresses</database>
      </record>
      <record>
      <database>ajaxdb</database>
      </record>
      ...
      %
      在本例中,我并未指定数据库或模式,这会要求脚本返回可用数据库的清单。假如web服务脚本有权执行该任务,则在curl语句后面就会显示执行的结果。在本例中,将以标签的形式显示不同数据库的列表。
      该脚本返回的所有数据都带有<records>标签,它包含一组<record>标签。每个<record>标签的名称和内容取决于已执行的SQL语句。在本例中,只返回单列命名数据库。
      除了使用curl命令,还可将URL输入浏览器中,然后在加载页面后选择“View Source(查看源文件)”。
      在下例中,将连接articles数据库并获取它的表格列表。结果如下:
      % curl ".../req.php?mode=getTables&db=articles"
      <?xml version="1.0"?>
      <records>
      <record>
      <tables_in_articles>article</tables_in_articles>
      </record>
      </records>
      %
      articles数据库中只有一个名为article的表格,这并不奇怪。要运行经典的select * from article查询以获取所有记录,可使用以下URL
      % curl ".../req.php?mode=getData&db=articles&table=article"
      <?xml version="1.0"?>
      <records>
      <record>
      <id>1</id>
      <title>Apple releases iPhone</title>
      <content>Apple Computer is going to release the iPhone...</content>
      </record>
      <record>
      <id>2</id>
      <title>Google release Gears</title>
      <content>Google, Inc. of Mountain View California has...</content>
      </record>
      </records>
      %
      表格中有两条记录:第一条显示Apple公司将发布超炫的IPhone;第二条显示Google公司将发布同样很炫、但用途完全不同的Gears系统。
      在本地机器上安装了极为强大且灵活的后台程序后,就可以着手为其创建Flex前台程序了。
      创建用户界面
      我想以层的形式创建Flex应用程序,首先是用户界面,然后在框架中添加代码以实现互动性。首先,若尚未安装Flex SDK则先安装。Flex SDK是免费软件,Flex Builder 2 IDE也有免费试用版。可从http://www.flex.org/download下载Flex SDKFlex SDK是免费的,Flex 3 SDK也将成为开源软件。Flex Builder是一种基于Eclipse的开发环境,通过拖放控件即可创建界面,但本例不必使用该工具。我非常喜欢使用标签,因此通常采用代码视图并直接修改MXML
      我想在界面顶部放置几个控件并在底部放置一个数据网格,以显示表中的数据。顶部的控件就是两个下拉列表,可在其中选择数据库和表。
      该窗体的MXML如清单2所示。
      清单 2. flexmysql1.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
      <mx:VBox horizontalAlign="left">
      <mx:HBox>
      <mx:Label text="Database:" />
      <mx:ComboBox id="selectedDatabase" width="381" height="21">
      </mx:ComboBox>
      </mx:HBox>
      <mx:HBox>
      <mx:Label text="Table:" />
      <mx:ComboBox id="selectedTable" width="381" height="21">
      </mx:ComboBox>
      </mx:HBox>
      <mx:DataGrid id="dg1" width="452">
      </mx:DataGrid>
      </mx:VBox>
      </mx:Application>
      Flex Builder 2中编译及运行这段代码时,结果如图1所示。
      1.界面布局
      相当整洁,对吧?渐变背景很漂亮,控件也很美观。我只做了极少量的工作。当然,图形设计师也可添加一些修饰,以使其更加美观,例如过渡效果和图像。而我还是喜欢整洁的界面,并要确保它在每台客户机上都具有一致的外观和表现,而Ajax应用程序要做到这一点并不容易。
      获取数据库清单
      补充Flex应用程序代码的第一步就是,当应用程序加载后在窗体顶部显示数据库的组合框。相关代码如清单3所示。
      清单 3. flexmysql2.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
      initialize="onInitialize()">
      <mx:Script>
      <![CDATA[
      import mx.collections.ArrayCollection;
      private static const SERVICE_BASE:String = "http://localhost/sql/req.php";
      public function onInitialize():void
      {
      myservice.url = SERVICE_BASE;
      myservice.send( null );
      } public function onResult(event:Event):void
      {
      selectedDatabase.dataProvider = myservice.lastResult..database.*;
      }
      ]]>
      </mx:Script>
      <mx:HTTPService id="myservice" result="onResult(event)" resultFormat="e4x">
      </mx:HTTPService>
      <mx:VBox horizontalAlign="left">
      <mx:HBox>
      <mx:Label text="Database:" />
      <mx:ComboBox id="selectedDatabase" width="381" height="21">
      </mx:ComboBox>
      </mx:HBox>
      <mx:HBox>
      <mx:Label text="Table:" />
      <mx:ComboBox id="selectedTable" width="381" height="21">
      </mx:ComboBox>
      </mx:HBox>
      <mx:DataGrid id="dg1" width="452">
      </mx:DataGrid>
      </mx:VBox>
      </mx:Application>
      我省略了与前例类似的部分代码,以缩短代码段长度。差别重点在于<mx:HTTPService>标签,它将创建HTTP Service Flex对象,而后者将与服务器进行通讯。该服务对象由onInitialize方法调用,而后者在Flex应用程序启动时调用。onInitialize方法先设置服务的URL,然后开始发出请求。请求完成后,就调用onResult方法。onResult方法将组合框的dataProvider设为web服务器的返回结果。
      该方法最有价值的部分如下:
      myservice.lastResult..database.*
      看看这个语句。如果之前不了解E4X的作用,我可以稍加解释。myservice.lastResult变量实际上是一个XML文档。‘..’句法等价于XPath ‘//’句法。它表示“将具有此名字的任何一个标签给我”,在本例中就是“将任何一个数据库标签给我”。星号表示数据库标签的任何子标签。由于数据库标签只有一个子标签,即数据库名称的文字部分,因此这段代码就表示“将XML文档中每个数据库的名称给我”。这个功能真的很好用!
      正是由于ActionScript的这种E4X扩展,Flex才能够方便地与XML数据源进行通讯。据我所知,还没有其他语言能够如此方便地查询XML文档。因此利用强大的E4X,就可以在浏览器中运行该应用程序,并得到如图2所示的结果。
      2.填充数据库名称的数据库组合框
      单击该组合框时,将弹出下拉列表,并显示机器中的数据库列表。是的,其中有很多数据库。几乎每篇有关PHPFlexRails或其他技术的文章都会用到数据库,所以我拥有大量的数据库。
      创建表视图代码
      创建示例Flex应用程序的最后一步就是添加表格的下拉菜单,并在数据网格中显示选中表格的数据。该例的完整代码如清单4所示。
      清单 4. flexmysql.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
      initialize="onInitialize()">
      <mx:Script>
      <![CDATA[
      import mx.collections.ArrayCollection;
      private static const SERVICE_BASE:String = "http://localhost/sql/req.php";
      private var loadingDatabases:Boolean = true;
      private var loadingTables:Boolean = false;
      public function onInitialize():void
      {
      loadingDatabases = true;
      myservice.url = SERVICE_BASE;
      myservice.send( null );
      } public function onResult(event:Event):void
      {
      if ( loadingDatabases )
      {
      loadingDatabases = false;
      selectedDatabase.dataProvider = myservice.lastResult..database.*;
      onSelectDatabase();
      }
      else if ( loadingTables )
      {
      loadingTables = false;
      var tables:Array = new Array();
      for each ( var tablRecord:XML in myservice.lastResult..record )
      {
      for each( var tablCol:XML in tablRecord.* )
      tables.push( tablCol..*.toString() );
      }
      selectedTable.dataProvider = tables;
      onSelectTable();
      } else
      {
      var records:Array = new Array();
      for each ( var record:XML in myservice.lastResult..record )
      {
      var outRecord:Array = new Array();
      for each( var column:XML in record.* )
      outRecord[ column.name() ] = column..*.toString();
      records.push( outRecord );
      }
      var data:ArrayCollection = new ArrayCollection( records );
      dg1.dataProvider = data;
      }
      } public function onSelectDatabase():void
      {
      loadingDatabases = false;
      loadingTables = true;
      var url:String = SERVICE_BASE;
      url += "?mode=getTables&db="+selectedDatabase.selectedLabel;
      myservice.url = url;
      myservice.send(null);
      } public function onSelectTable():void
      {
      var url:String = SERVICE_BASE;
      url += "?mode=getData&db="+selectedDatabase.selectedLabel;
      url += "&table="+selectedTable.selectedLabel;
      myservice.url = url;
      myservice.send(null);
      }
      ]]>
      </mx:Script>
      <mx:HTTPService id="myservice" result="onResult(event)" resultFormat="e4x">
      </mx:HTTPService>
      <mx:VBox horizontalAlign="left">
      <mx:HBox>
      <mx:Label text="Database:" />
      <mx:ComboBox id="selectedDatabase" width="381" height="21"
      change="onSelectDatabase()">
      </mx:ComboBox>
      </mx:HBox>
      <mx:HBox>
      <mx:Label text="Table:" />
      <mx:ComboBox id="selectedTable" width="381" height="21"
      change="onSelectTable()">
      </mx:ComboBox>
      </mx:HBox>
      <mx:DataGrid id="dg1" width="452">
      </mx:DataGrid>
      </mx:VBox>
      </mx:Application>
      其中有一处重要修改,即添加了onSelectDatabase()函数的代码,以获取表格列表,然后将其输入到onResult()函数中,还添加了onSelectTable()函数,该函数可检索表格中的数据,并在onResult()处理器中设置数据网格。
      在浏览器中运行该例时,结果如图3所示。
      3. 运行“show tables”查询之后的结果
      本例中使用了nasa数据库,这是我为NASA Ames演讲而创建的数据库(我用了“火箭科学”的笑话,因为当时我的听众是一群火箭科学家)。该数据库只有一个名为mission的表,其中包含两列,分别代表每项由NASA发起但已撤消的任务名称和年份。
      在数据网格中单击名称列即可按名称排序,如图4所示。
      4. 显示mission表中的数据
      然后单击年份列,以按照年份排列数据,如图5所示。
      5. 迪斯科球式查询
      在过去几年中,我们似乎并未发起任何任务。
      后续步骤
      至此,本例已可应用于许多场合。在前台Flex应用中,可以添加一些对用户更友好的控件,以添加、删除或更新表格。甚至可以提供数据过滤功能或者编辑功能,以修改表格中的数据。数据网格控件非常强大,可以处理现场编辑任务。也可以用在完全不同的场合,例如使用Flex绘图软件包执行数据分析和可视化工作。
      总结
      PHPFlex的结合潜力无限。利用PHP可以方便地在后台发布web服务,可以单独发布,可以与HTML前台程序一起发布。PHPMyAdmin带有web服务接口扩展功能,使任何人都能以FlexAjaxSilverlight、桌面小部件或其他任何技术编写前台程序。FlexPHP开发人员提供了强大的前台工具。它避开了困扰Ajax开发人员的客户端不兼容问题。Flex 2并非只能使用特定的服务器技术,因此Flex应用程序编译完成后,它就可以部署在任何场合,因为它只是一个SWF文件。可以看到,利用简单的web服务对象和强大的E4X语言扩展,就可以让Flex应用程序方便地与几乎任何一种后台程序进行通讯。
      读者不妨一试,如果您使用PHPFlex创建了有趣的程序,请告诉我,也许我们可以合写一篇文章来介绍它。
       

      发表于 @ 2008年01月30日 10:45:00|评论(loading...)|编辑

      新一篇: 利用Adobe AIR创建桌面对话应用程序 | 旧一篇: NetBeans Web开发中设置页面导航

      评论:没有评论。

      发表评论  


      当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
      Csdn Blog version 3.1a
      Copyright © 付江