| 首页 >> 网络编程 >> PHP >> PHP实例 >> 新闻正文 | [字体:大 中 小] [打印文档] |
| |
|
第1章 入门 PRADO是在PHP5环境下的一个基于事件驱动和基于组件的WEB应用开发框架。使用PRADO开发WEB应用,你主要需要做的工作就是使用已有的组件(原文是"实例化已经定义好的组件",熟悉面向对象编程的开发者可能比较容易理解这句话),设置组件的属性,为控件组件的各种事件编写对应的处理函数,然后把这些组织成一个个的页面。(译者注:个人倾向于将component翻译为组件,control翻译为控件,事实上大多数场合两者没有什么区别,但是为了读者能够更加容易理解原文,本文一律按此规则翻译。)这个过程和使用RAD开发工具(比如Delphi或者Visual Basic)来开发Windows应用程序非常类似。 下面用一个简单的例子来说明PRADO框架的工作原理。假定我们现在要使用PRADO来开发一个常见的登录页面。首先我们选择PRADO中的2个TTextBox控件和1个TButton控件来分别对应用户名输入,密码输入和提交按钮。然后把对应密码输入的TTextBox控件的TextMode属性设置为"Password",并为TButton控件的OnClick事件指定一个处理函数login。最后把这些控件放到页面模板的合适的位置上(后面会解释什么是页面模板,实际上它和一个html页面很相似),一个功能完善的登录页面就实现了。控件会自己处理好如何显示数据,如何得到用户输入的数据,如何响应用户的操作等这些事情。例如,TTextBox控件会显示一个输入框让用户输入;用户输入的密码会被显示为*号,而开发者在代码中可以通过读取TTextBox控件的Text属性来获取用户实际输入的密码;当用户点击了提交按钮的时候,login 函数将会被自动调用。这和传统的PHP编程处理方式很不一样。使用传统的PHP编程方式,开发人员需要使用HTML标签来显示用户输入框和按钮,同时需要自己解析POST数据来获得用户的输入以及判断按钮是否被点击了等等这些事情。 PRADO 基于组件的编程方式使代码的重用极为方便。一些重复性的单调的工作比如表单输入的验证,页面状态的管理等都可以使用PRADO已经提供的组件来处理。开发者也可以通过继承现有的组件或者组合现有的组件来开发新的组件满足要求。另外一些新的组件即将发布。 总来的说,PRADO 为PHP的编程人员提供了以下的有益之处: 可重用性 - 符合PRADO组件标准的代码是高度可重用的。 和这些框架相比,PRADO更专注于建立一个代码重用和事件驱动的编程标准。如果你曾经用Delphi或者Visual Basic等这些RAD开发工具来开发Windows程序的话,那么你会发现使用PRADO来开发WEB应用是非常类似的,你可以很快就掌握PRADO来进行WEB应用的开发。大多数情况下,你要做的仅仅是设置组件的属性和响应组件的事件。更高层次的代码重用,比如前面所说的用户管理模块,可以基于PRADO组件来实现。 PRADO的思想最先我是从Apache Tapestry项目想到的。在设计和实现的时候, Borland Delphi 和Microsoft ASP.NET的设计思想起到了很重要的作用 。实际上,使用过ASP.NET的人可以发现PRADO中有很多地方和它是相似的。
PRADO需要PHP5的环境,以及SimpleXML模块(PHP5缺省安装后的环境下已经包括了这个模块)。在Windows XP和RedHat Linux环境下,已经在Apache和IIS Web服务器上都通过了测试。 PRADO框架使用一个.zip文件发布。在Linux下可以使用unzip,在Windows下可以使用Winzip来解压。解压完毕后,会在当前目录下创建一个目录prado。这个目录主要包括以下这些文件和目录: 在这一节中,我们主要来说明``Hello, world! 这个例子,让你对使用PRADO开发有一个印象。这个例子非常的简单,只有一个页面,上面显示了一个"Click me"的按钮。当用户点击了这个按钮,这个按钮的标题会变成``Hello, world! 。 要完成这个功能需要这些文件, <?php require_once( ../framework/TApplication.php ); $app=TApplication::getInstance( helloworld/application.spec ); $app->run(); ?> 这里我们假定框架的代码位于 ../framework 目录下。 每一个 PRADO应用都应该有这么一个入口文件。他们之间主要的区别在于 getInstance 函数的参数的不同,这个参数指明了应用的配置文件的位置。 application.spec 是一个XML文件,用来配置应用级别的参数。(就好象全局变量一样,当然现在是只读的,我们正在决定是否下一版本中允许可读写的)在这个例子中,它包含了如下的代码: <application> 的default-page 属性指明了应用启动时缺省进入哪一个页面。在这里我们指定了HomePage页面,它对应了一个页面类HomePage (关于页面和页面类后面会专门对它们进行解释的)。 HomePage.tpl 文件是页面类HomePage一个模板文件,包含如下的代码: HomePage 类继承了 TPage 类。TPage 类是PRADO框架本身提供的,它是所有页面类的基类。HomePage 类只包含了一个方法clickMe ,这个方法就是刚才我们提到的页面模板中响应按钮OnClick 事件的方法clickMe 。这个方法的代码的作用是设置事件的发送者$sender(这里就是这个按钮)的Text 属性为 ``Hello, world!"。我们期望当用户点击这个按钮的时候,按钮的标题改为``Hello, world!" 。 这个包含在 PRADO 发布包中的例子可以通过此URL来访问:href="">http://<Web-server-address>/examples/helloworld.php . 你可能会说完成这么一个简单的功能有什么大惊小怪的。是的,这个功能确实非常简单,用几行php代码就可以完成。但是这个例子主要是目的是为了让你感受一下PRADO编程方式,它是面向对象的,基于组件和基于事件驱动的。用类似的编程方式可以实现更复杂的功能,请继续看下面几章。 第2章 用PRADO编程
根据Clemens Szyperski的说法, ``软件组件是一个具有特定接口的组合单元,可以独立存在,参与组成其它组建。
属性可以被认为是描述组件某一特性的公共变量,比如背景颜色,字体大小等等。属性是有类型的,比如 string, integer , 等等。属性可以是只读的,也可以是可读写的。 一个完整的组件类定义包括两个文件: 一个类文件,它定义了组件类的逻辑。这个文件主要是PHP代码。这个文件的文件名必须和类的名字一样,而且以.php 作为文件后缀。
2.1.1 控件
控件是定义了用户界面的PRADO 组件。每一个控件都有一个父控件和一些子控件(注意,这里的父,子这些关系和面向对象中的父类子类的概念是完全不一样的。一个控件是另外一个控件的父控件只是说明了前者拥有后者,这个拥有关系可以理解为一个目录下包含了一个子目录;而绝不是后者是前者的子类、是从前者继承而来的这个概念)。页面是最高级别的控件,它没有父控件(当然你也可以认为Application是它的父控件)。一个PRADO的应用是一个页面的集合,每一个页面都代表了一个层次树状结构的控件集,控件与控件之间关系是通过父子关系联系在一起的。 这种父子关系可以通过模板文件来建立。模板文件的格式和HTML是很像的,只不过在HTML的基础上增加了一些特殊的标签来定应控件。如果一个控件的标签被另外一个控件的标签所包括,那么前者就被认为是后者的子控件。静态文本也被认为是子控件。 控件可以拥有一个模板文件来描述它的界面内容。缺省情况下模板文件和类文件在同一个目录下,而且文件名是相同的,模板文件的后缀则为 .tpl 。同规格文件一样,如果你需要把模板文件放在不同地方或者用鳖的文件名,可以通过设置类常量 TEMPLATE_FILE 的值来指明模板文件的位置。 每一个控件都有一个ID,它可以在同一级别的控件中来唯一标识控件本身。ID路径则是在控件的树状结构中,从当前控件到目标控件的所有控件ID的序列,它可以用于访问一个控件。比如,在 2.1.2 实例化组件 组件有两种方式来实例化。一种方法是在一个控件的模板文件中定义它,当这个控件被创建的时候,框架会自动的去实例化这个组件。还有一种方法是在PHP代码中手动的实例化。我们先来看一下前面一种静态的创建方法,稍后再来看一下动态的创建方法。 静态创建组件 一个控件在模板文件组件标签来声明,其语法如下: ...... 这里 ComponentType, PropertyName, 和 EventName 应该被真正的组件类名,属性名和事件名所替代。 ID 属性是可选的。如果定义了ID 属性,那么ID 的值必须在平级的控件中是唯一的。如果没有定义,那么框架会自动为这个控件分配一个唯一的ID的。当然,这要求组件的标签被正确的嵌套,每一个开放的组件标签都应该和一个闭合的组件标签组成一对,这个规则和XML的规则是一样的。(译者著:如果你对XML一点都不了解,建议你先看一下一些基本的XML概念,要求并不高,你只需要知道如何正确书写一个XML文件即可。) 注意:控件的ID必须是一个以字母开头的,后面只包含字母,数字和下划线的字符串。
当组件被创建(实例化)的时候,通过规格文件定义的组件的属性和对应事件处理方法就会立刻生效了。
PRADO 允许开发者在自己的PHP代码中实例化组件。组件可以通过调用一个静态类方法Application::createComponent($type)来被实例化,该方法的参数$type 指明了要创建的组件的名称。组件也可以使用new 操作符来实例化。这两者方法的区别是:前者会使用一种缓存机制,下一次创建相同的组件时速度会快很多;而后者不会使用缓存机制,每次都要完全重复执行实例化的步骤。通常情况你应该使用TApplication::createComponent($type) 来实例化(如果你想了解更多,请参考下面的注释)。 如果新创建的组件是一个控件,那么可以通过调用把这个控件作为其他控件的子控件。注意,如果你需要指定这个控件的ID,应该在将它添加作为其他控件的子控件之前就指定ID;否则的话框架会自动为它分配一个ID,而且这个ID是不能更改的。 注:如果在构造函数中使用或申请了资源句柄的话,只能使用 new 操作符来实例化。因为PRADO使用了缓存机制来实例化组件,因此如果在构造函数中使用了资源句柄的话,下次实例化的时候从缓存读出来的数据中的资源句柄部分依然对应着原来的那块内存地址,这样就极容易导致系统崩溃。所以如果你要设计一个自己的组件,也尽可能的不要在构造函数中使用和申请资源句柄,而是应该把这些代码组织在一个别的方法中,在页面的OnInit事件或其它事件中调用。一般来说构造函数只需要实现简单的变量初始化即可。在PRADO的核心代码中,所有的组件的构造函数都没有使用到资源句柄。你在开发自己的组件的时候,可以参考一下它们的源代码。
PHP 5 使用了一种很好的方式来访问组件的属性。你可以把一个组件的属性当作组件的成员变量来使用。比如要设置TButton 控件的Text 属性,你可以使用$button->Text="xxx"的代码,这里$button 代表了控件的实例。对于控件来说,你还可以使用它的ID路径来访问属性。假定现在HomePage页面有一个子控件MenuBar ,MenuBar 控件有一个子控件HyperLink ,那么在页面环境中,可以使用的代码$this->MenuBar->HyperLink->NavigateUrl来读取HyperLink 控件的NavigateUrl 属性。 注意,由于PHP5.0中的一个BUG,如果你需要设置一个属性的值,那么你必须首先通过它的控件的ID路径来获得控件,然后再来设置这个属性的值。在上面这个例子中,需要用下面两行代码来设置NavigateUrl 属性。 $link=$this->MenuBar->HyperLink; $link->NavigateUrl="..."; 如果直接使用 $this->MenuBar->HyperLink->NavigateUrl 来设置属性值会产生一个错误。但是你还可以下面这段代码来设置属性的值,这样就可以避免那个错误了。 $this->MenuBar->HyperLink->setNavigateUrl("..."); 2.1.4 使用事件 事件响应函数通常在规格文件或者模板文件中指定给对应的事件,指定事件响应函数和指定属性的初始值是类似的。注意,在规格文件或者模板文件中指定的事件响应函数,必须在此规格文件或模板文件对应的组件中定义,它的语法如下: function handlerName($sender,$param) { ... } 这里 $sender 指向的是触发这个事件的控件, $param 是事件的参数,它的内容取决于事件的类型。 在编程的时候也可以使用TComponent::addEventHandler() 方法来动态的指定一个事件响应方法。
只有控件才可以数据绑定。
在模版中设定数据绑定的话,只要给属性的值指定一个有效的PHP表达式的字符串,并在前面加上一个# 作为前缀。比如在页面模版文件中使用如下的代码: <com:TLabel Text="#$this->Page->ID" /> 这段代码给TLabel 组件的Text 属性绑定了一个的表达式$this->Page->ID 。这个表达式的作用是获得当前控件所在页面的ID。注意,这个表达式中的$this指的是TLabel控件本身,因为$this所在上下文环境是在TLabel 中。 在代码中要设定数据绑定,可以调用组件的bindProperty() 方法,这时候不需要在前面加上字符# 。
另外,如果在模板文件中你需要给一个属性赋初始值,而不是数据绑定的话,如果这个值是以#开头的,那么应该将#重复一次,就像PropertyName="##...." 一样。
目前发布的 PRADO 包括如下所示的组件树,这些组件的属性,事件和类的方法在PRADO文档中都可以查到。 TComponent |
