Phalanger是一种PHP语言编译器,也是针对.NET的PHP运行时。 它可以用于把PHP web项目编译成.NET字节码,并在Windows中使用IIS或者在Linux上使用Mono和Apache作为ASP.NET应用程序来执行。 然而,Phalanger不仅仅是把已经存在的PHP应用编译到.NET中。
\我们可以使用Phalanger创建组合.NET和PHP的解决方案,所采用的方式用标准的PHP解释器是不可能做到的。 有了Phalanger扩展,PHP程序可以直接使用.NET类,而.NET程序(比方说用C#编写的)也可以动态地调用PHP脚本,或者使用在PHP中实现的函数和类【6】。
\本文中,我么会简要地介绍Phalanger,然后查看三种使用方案。 我们会讨论如何整合PHP应用程序和.NET;如何高效地在Windows上运行PHP应用程序,以及如何使用PHP作为ASP.NET的视图引擎(view engine)。
\Phalanger简介
\Phalanger已经存在一段时间了。 第一版Phalanger是于2003年在布拉格的查尔斯大学作为软件项目创建的。稍后就开始了2.0版本的开发,并且于2006年在CodePlex作为开源项目发布。 微软支持了这个项目一段时间,后来一位Phalanger开发者加入微软,并从事动态语言运行时方面的工作。
\Phalanger相关活动在2008年恢复,这多亏有了与Jadu的合作,它使用Phalanger为在PHP中开发的CMS构建了.NET版本。 从2010年开始,Phalanger的开发主要由DEVSENSE提供资金支持,它也为Phalanger提供了商业支持。 最近发布的版本Phalanger 2.1【7】,其中提升了与标准PHP实现的兼容性,在动态操作的实现过程中利用了DLR,并提供了PHP和其他.NET语言(像C#、F#和Visual Basic)之间的互操作性。
\Phalanger的组件
\Phalanger包括多个部分独立的组件,可以用来开发运行在.NET上的PHP应用程序,并使用.NET或Mono来运行它们:
\- Phalanger编译器Phalanger会把PHP源代码编译成.NET程序集,它可以使用.NET JIT(Just-in-time编译器,它会为当前平台生成本地代码)执行。 编译后的PHP代码会使用Phalanger运行时和动态语言运行时,从而提供了PHP语言动态特性的高效率实现。\
- Phalanger运行时和类库Phalanger运行时提供了对数组之类PHP特性的实现。 Phalanger还包含了针对I/O、正则表达式以及其他标准PHP类库的.NET实现。\
- 本地扩展在32位Windows平台上,Phalanger可以通过本地的桥接程序使用所有现存的PHP 4扩展。 尽管这会带来一些运行时负载,但这让我们不需要额外工作就可以运行某些PHP应用程序。\
- 托管的扩展 通过包装.NET中提供的类似功能,PHP扩展也可以重新实现。 这些扩展可以是由任何.NET语言编写,并提供很好的性能。 Phalanger中包含多个扩展,包括SPL、JSON、SimpleXML、MySQL和MS SQL的提供程序。 DEVSENSE【9】还提供了附加的扩展,像Memcached、图像和cURL等。\
- 与Visual Studio的集成Phalanger还与Visual Studio集成(最近的更新支持Visual Studio 2010)。 集成功能添加了针对PHP文件的颜色突出显示和智能提示功能,让我们可以调试使用Phalanger运行的PHP应用程序。\
Phalanger使用案例
\Phalanger在很大程度上与PHP 5兼容,可以运行大量开源的PHP项目,包括WordPress和MediaWiki。 我们可以使用它把这些项目集成到.NET生态系统中,也可以开发新的项目,它会兼有PHP和.NET的优势。 在本文剩下的内容中,我们会讨论以下三种使用案例:
\- 方案1: 高效运行PHP应用程序。 使用PHalanger在Windows上编译的PHP应用程序的性能,要比通过FastCGI使用标准PHP解释器运行的高。 这使得选择Phalanger在Windows环境中部署PHP很具有吸引力。\
- 方案2: 把WordPress与ASP.NET整合。 使用Phalanger编译的PHP代码能够调用所有.NET程序库。 这可以用于在PHP和ASP.NET应用程序之间共享用户数据库或者其他数据。\
- 方案3: 从ASP.NET应用程序中调用PHP。 PHP的灵活性对于编写脚本或者编写web应用程序的表现层非常有用。 有了Phalanger,我们就可以在.NET中开发应用程序,并使用PHP作为脚本语言或者视图引擎。\
以下三个部分会详细讨论各种方案。 我们首先会给出概览,然后查看一些技术细节,它会说明Phalanger中让你感兴趣的内容。
\方案1: 高效运行PHP应用程序
\Phalanger之所以能够高效地运行PHP应用程序,是因为以下两个原因。 首先,它会编译PHP源代码,而不是解释它;其次,它会把应用作为ASP.NET应用程序运行,那会在Windows下提供额外的性能优势。
\使用Phalanger和.NET编译PHP
\编译过程如图1所示。正如图上所显示的,Phalanger会把PHP源代码编译成.NET IL(中间语言),那是与架构独立的低级字节码。 编译后的代码会使用PHP核心库(Phalanger的一部分)和动态语言运行时(DLR)来执行标准的PHP操作。 当应用程序启动时,.NET JIT(just-in-time)编译器会把这些组件转换为针对当前处理器架构优化过的本地代码。
\ \图1. 使用Phalanger把PHP源代码编译成本地代码的过程
\正如Phalanger评测显示【10】,使用Phalanger编译的WordPress在Windows下的性能比通过FashCGI使用标准PHP解释器的好,也比通过WinCache使用PHP的稍好一些。 然而,评测没有测试Phalanger最新的版本,它使用DLR进行了进一步优化。
\使用ASP.NET部署PHP应用程序
\Phalanger应用程序的运行方式和ASP.NET应用程序完全相同。 这让它具有了重要的性能优势,特别是在Windows系统下,进程要比线程耗费更多资源。
\图2显示了运行PHP应用程序的不同可选方案。
\当使用标准CGI模式时,web服务器会为每个进入的请求启动新的进程。 在Windows下,这样做的效率不高,它还阻止了共享位于共享内存中的状态,也很难进行进程中缓存(in-process caching)。 当使用FashCGI模式时,web服务器会重用进程,这样它不需要为每个请求启动新的进程。 然而,这还是无法共享内存中的状态,因为不同的进程拥有不同的状态。
\(点击图像可以放大)
\ \图2. 使用CGI、FashCGI和Phalanger运行PHP
\Phalanger的行为方式和所有ASP.NET应用一样。 单独的叫做应用池(Application Pool)的ASP.NET进程会处理所有进入的请求。 我们甚至可以在单一进程(应用池)中配置多个PHP应用程序(像多个WordPress的独立实例)。 在进程中,会有多个线程,这些线程会被重用以处理单独的请求。 在Windows下,线程要比过程更轻量级,所以这种解决方案更有效率,并且会消耗更少的内存。
\对于运行在单一进程中的应用程序,我们可以进行进一步的优化,并采用其它有趣的方案。 例如,Phalanger会使用动态语言运行时(DLR)来做动态方法调用。 DLR会使用与时间相适应的缓存机制,因此在几次请求之后,DLR就会“知道”应用程序使用的是哪个方法,并变得更快一些。 这只有在单一进程中处理请求的情况下才可能做到。
\在单一进程中运行所有代码也意味着应用程序可以在内存中存储全局状态。 这可以用于实现与WinCache提供的User Cache类似的功能,但是不会有跨进程通信造成的负载。
\方案2: 把WordPress与ASP.NET整合
\PHP的一点优势就在于拥有大量优秀的开源CMS系统(WordPress、Joomla等等)、表单应用程序(phpBB及其他)和wiki(Mediawiki及其他),其中很多都通过了Phalanger的测试。
\这些应用通常会比.NET平台下类似的程序包提供更多特性。 开发基于ASP.NET网页的公司可能会面临以下情况:
\- 它需要向现存的ASP.NET解决方案中添加wiki、论坛或者博客,但是只有在PHP中存在合适的应用程序(例如,免费并且带有所有必要特性)。\
- 应用程序可能会在子域下运行,但是它应该共享用户数据库。 此外,一旦用户登录到主页,那么他就应该同时登录到wiki、论坛和博客上。\
ASP.NET应用程序可以使用ASP.NET的成员管理(ASP.NET Membership),它还用来管理用户、角色和功能的标准机制。 有了Phalanger,我们就可以修改开源的PHP项目,从而使用同样的机制。 下一部分会演示使用WordPress如何做到这一点。
\为WordPress实现ASP.NET成员管理插件
\如果你对代码不感兴趣,那么就可以略过这个部分,直接查看第三种情况。 但是,我们不会查看技术细节,只是对让PHP调用.NET程序库的PHP扩展做简要的概述。
\我们可以使用插件轻松地自定义在WordPress管理用户的方式。 管理用户的插件需要实现一个PHP类,其中有各种成员函数。 其中最值得期待的功能就是身份验证,它会获得用户名和密码。 它应该填充当前用户的信息,或者,当用户不存在的时候,就会把名称设置为NULL。
\为了使用.NET中的ASP.NET成员管理来实现身份验证功能,我们可以使用System.Web.Security命名空间中的功能。 静态方法Membership.ValidateUser会检查密码是否正确,而Membership.GetUser会返回用户的基本信息。 使用Phalanger,我们可以访问.NET对象,就像它是标准的PHP对象一样,这样实现验证机制就很简单了。 代码1展示了简化后的代码。
\代码1 在WordPress插件中实现身份验证功能的函数
\import namespace System:::Web:::Security;\
function authenticate(\u0026amp;$username,$password) {
global $errors;
// Test whether the password is correct
if (Membership::ValidateUser($username,$password)) {
// Get information about the user and fill $userarray $user = Membership::GetUser($username);
$userarray[ 'user_login'] = $user-\u0026gt;UserName;
$userarray[ 'user_email'] = $user-\u0026gt;Email;
$userarray[ 'display_name'] = $username;
$userarray[ 'user_pass'] = $password;
// Loading of roles \u0026amp; profiles omitted for simplicity
// Update or create the user information in WordPress
if ($id = username_exists($username)) {
$userarray['ID'] = $id;
wp_update_user($userarray);
}
else wp_insert_user($userarray);
} else {
// Report error if the login failed $errors-\u0026gt;add('user-rejected', 'Log-in failed!');
$username = NULL;
}
}\
代码首先声明了重要的命名空间。 这是一个非标准的Phalanger扩展,它从引用的程序库的.NET命名空间中导入了功能(我们可以使用web.config文件来引用程序库)。 在将来的版本中,Phalanger会使用PHP 5.3支持的标准命名空间,但是这项改变还没有完全实现。
\剩余部分的代码看起来和标准的PHP代码一样。 然而,Membership类实际上是标准的.NET类。 Phalanger会把PHP类和.NET类同等对待,所以我们可以使用标准的语法来调用.NET方法。 函数ValidateUser和GetUser都是静态函数,所以使用::语法来调用。 GetUser的结果是一个.NET的MembershipUser对象, 其中带有各种属性,包括关于用户的基本信息。 我们仍然可以使用标准的标记法来访问对象的字段(它们被实现为.NET的属性)。
\正如你所看到的,我们可以很自然地在PHP中使用.NET功能。 由于代码会被编译成.NET程序,所以在调用.NET库时不会有任何负载。 下一部分展示的是反方向的整合——从.NET应用程序中调用PHP。
\方案3: 从ASP.NET应用程序中调用PHP
\PHP的主要优势就在于灵活性和简单性,这使得它成为编写脚本和实现渲染HTML很棒的语言。 然而,有些人发现,想要实现大型应用程序,那么在静态类型语言——像Java或C#——会更容易一些。 使用Phalanger,我们可以同时获得两方面的优势。
\这个部分所讨论的方案演示了一种组合ASP.NET和PHP的方式。\t 它基于先进的ASP.NET MVC(模型、视图、控制器)框架,将表现层、负责交互的层和应用程序的业务逻辑分离开来。 我们可以使用不同的语言来开发单独的组件:
\- C#模型和控制器 模型和控制器会在C#中编写。 应用程序的这个部分会实现业务逻辑,通常这在静态类型语言中编写更容易一些,特别是在业务逻辑非常复杂的情况下。 此外,我们还可以使用像LINQ之类的技术来存储数据,使用任务并行库(Task Parallel Library)使用多线程来实现高性能计算。\
- PHP视图 应用程序的表现层会用PHP编写。 在这里,PHP的简单性和灵活性会提供最大的好处。 此外,这意味着应用程序的这个部分可以由开发经验比较少的开发者来编写,因为大多数web开发者的web设计师都对PHP有些了解。\
还有一些情况,从C#中调用PHP会很有用。 例如,你可以在大型的C#项目中使用PHP作为脚本语言。 这也非常有用,因为PHP是一种广为所知的语言。 另一种情况是,当在C#中使用PHP程序库的时候——正因为有了Phalanger的duck typing机制,这才得到了很大程度的简化,该机制甚至可以为调用文档齐备的PHP代码生成静态类型的C#接口。
\在本文剩余的内容中,我们会着重讨论使用PHP实现ASP.NET应用程序表现层的方案。 你可以在文章末尾找到其他方案(像编写脚本)的参考信息。
\在C#和PHP中创建模型-视图-控制器应用程序
\首先让我们看下使用C#和PHP组合创建出来的简单应用程序。 应用程序的模型和控制器都是使用C#编写的,如代码2所示。在这个例子中,模型只是一个简单的C#类,它表示的是产品信息。 在现实情况下,这个类可能会负责从数据库载入数据,并且可能使用LINQ来实现。
\代码2: 示例web应用程序(C#)的模型和控制器
\public class Product {\ public string ProductName { get; set }\ public double Price { get; set }\}\
public class HomeController : Controller {
public ActionResult Index() {
ViewData.Model = new Product { ProductName = \"John Doe\