Phalanger 是一种 PHP 语言编译器,也是针对 .NET 的 PHP 运行时。 它能够用于把 PHP web 项目编译成 .NET 字节码,并在 Windows 中使用 IIS 或者在 Linux 上使用 Mono 和 Apache 做为 ASP.NET 应用程序来执行。 然而,Phalanger 不只仅是把已经存在的 PHP 应用编译到 .NET 中。php
咱们可使用 Phalanger 建立组合 .NET 和 PHP 的解决方案,所采用的方式用标准的 PHP 解释器是不可能作到的。 有了 Phalanger 扩展,PHP 程序能够直接使用 .NET 类,而 .NET 程序(比方说用 C# 编写的)也能够动态地调用 PHP 脚本,或者使用在 PHP 中实现的函数和类【6】。html
本文中,我么会简要地介绍 Phalanger,而后查看三种使用方案。 咱们会讨论如何整合 PHP 应用程序和 .NET;如何高效地在 Windows 上运行 PHP 应用程序,以及如何使用 PHP 做为 ASP.NET 的视图引擎(view engine)。web
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 (&username,username,username,password) {
global $errors;
// Test whether the password is correct
if (Membership::ValidateUser (username,username,username,password)) {
// Get information about the user and fill $userarray
user=Membership::GetUser(user = Membership::GetUser (user=Membership::GetUser(username);
$userarray[‘user_login’] = $user->UserName;
$userarray[‘user_email’] = $user->Email;
$userarray[‘display_name’] = $username;
$userarray[‘user_pass’] = $password;
// Loading of roles & profiles omitted for simplicity
// Update or create the user information in WordPress
if (id=usernameexists(id = username_exists (id=usernameexists(username)) {
$userarray[‘ID’] = $id;
wp_update_user ($userarray);
}
else
wp_insert_user ($userarray);
} else {
// Report error if the login failed
$errors->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 的方式。 它基于先进的 ASP.NETMVC(模型、视图、控制器)框架,将表现层、负责交互的层和应用程序的业务逻辑分离开来。 咱们可使用不一样的语言来开发单独的组件:
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”, Price = 99.9 };
return View ();
}
}
控制器组件是经过 HomeController 类实现的,它会继承 ASP.NET MVC 控制器。 类中只包含一个动做,展示应用程序的索引页面。 当用户访问/Home/Index(或者根 URL)的时候就会触发这个动做。 它会建立模型(Product 类的实例)并把它传递给视图组件。
在标准的 ASP.NET MVC 应用程序中,视图组件一般会使用 ASPX 页面或者使用带有使用 C# 或 Visual Basic 编写的代码的 Razor 视图来实现。 Phalanger 让咱们可使用 PHP 来实现视图。 代码 3 展现了这个例子。
代码 3 示例 Web 应用程序(PHP)的视图
head>
Product: $MODEL->ProductName; ?>
Price: $MODEL->Price; ?>
body>html>
视图会使用下面描述的 ASP.NET MVC 扩展来渲染。 扩展会执行代码 3 中所示的 PHP 脚本,并定义名为MODEL的全局变量,其中会包含控制器返回的数据。在上述示例中,MODEL 的全局变量,其中会包含控制器返回的数据。 在上述示例中,MODEL的全局变量,其中会包含控制器返回的数据。在上述示例中,MODEL 是对标准 .NET 类的引用。 Phalanger 会对 .NET 类和 PHP 对象同等对待,因此使用 echo 结构,咱们很容易就能够显示产品的属性。
示例显示了应用程序的基本结构,可是它极为简单,因此不会真正显示出在表现层使用 PHP 所能给咱们带来的好处:
PHP 与生俱来的动态特性使得渲染任何结构的数据都很简单。 视图并不只限与简单脚本,而且可使用任何现存的 PHP 库,包括流行的模板引擎(templating engines)。
视图可使用 PHP 的 include 功能实现多文件的结构,这样你能够彻底控制页面如何生成。
建立视图的开发者不须要知道任何关于 .NET 的知识。 这意味着从 PHP 转型为 C# 的公司,仍然支持现存的开发者技能。
为了让你更好地了解这个方案的工做方式,如下部分会说明关于 PHP 和 C# 整合的技术细节。 若是你对细节不感兴趣,那么就能够直接跳到总结部分。
透过现象看本质
这个部分所描述的方案基于 PicoMVC 项目【4】,它让咱们能够组合 PHP 和F#。 为了让示例更简单,我把代码从F#转换为C#。 在 PicoMVC 中 PHP 整合的核心是一个简单的函数,它会取得 PHP 脚本的文件名,并使用 Phalanger 运行时来运行。 函数如代码 4 所示。
代码 4 从 ASP.NET web 应用程序调用 PHP 脚本
void PhalanagerView (string fileName, object model, HttpContext current) {
// Initialize PHP request context and output stream
using (var rc = RequestContext.Initialize (ApplicationContext.Default, current))
using (var byteOut = HttpContext.Current.Response.OutputStream)
using (var uftOut = new StreamWriter (byteOut)) {
// Current context for evaluating PHP scripts
var phpContext = ScriptContext.CurrentContext;
// Redirect PHP output to the HTTP output stream
phpContext.Output = uftOut;
phpContext.OutputStream = byteOut;
// Declare global $MODEL variable (if model is set)
if (model != null)
Operators.SetVariable (phpContext, null, “MODEL”,
ClrObject.WrapDynamic (model));
phpContext.Include (fileName, false);
}
}
PhalangeriView 方法会得到文件名(指向 PHP 脚本)、表明做为模型返回的数据的 .NET 对象以及当前的 HTTP 上下文。 它首先会初始化 RequestContext,从而 Phalanger 知道它是在处理做为 HTTP 请求一部分的脚本。 而后,它会确保全部 PHP 脚本生成的输出都会直接做为 HTTP 响应发送。 看成为脚本运行 PHP 的时候,输出能够重定向到内存流,从而以不一样的方式处理。 最后,方法会声明全局变量 MODEL,并使用 Phalanger 所提供的 Include 方法来执行 PHP 脚本。
这个例子并不彻底是从 C# 调用 PHP 的指引,你能够在 Phalanger 博客的文章中找到更详细的信息。 然而,它应该能够说明,使用 Phalanger 从 C# 调用 PHP 脚本至关容易。 这在本节讨论的 web 编程状况下会颇有用,可是它给了咱们更多选择。
总结
本文简要地介绍了 Phalanger——针对 .NET 的 PHP 编译器——以及几种方案,咱们能够在实践中使用它来解决重要问题。 最近 Phalanger 项目很是活跃,2.1版本中包含了不少兼容性方面的改善、使用动态语言运行时(DLR)以得到更好的性能,以及与 Visual Studio 2010 的集成。
咱们看了三种能够在 web 开发中使用 Phalanger 的方案。 第一种方案是使用 Phalanger 在 Windows 环境下运行未经修改的开源 PHP 项目(像 WordPress)。 使用 Phalanger 编译的应用程序能够运行在 ASP.NET 下,这种主机会更轻量级,运行效率也更高。
在第二种方案中,咱们查看了集成在 .NET 生态系统中的 PHP 应用程序。 有了 Phalanger 扩展,咱们就能够在 PHP 代码中直接调用 .NET 程序库。 例如,这能够用来整合 ASP.NET 应用程序和 WordPress 之间的用户数据库。
最后一种方案演示了一种 web 框架,它使用 PHP 做为在 ASP.NET MVC 中编写视图的语言。 经过这种方式,.NET 开发者能够很容易地提供应用程序的业务功能,而 PHP 开发者能够在表现层中直接使用它。
关于做者
Tomas Petricek是微软的C# MVP 和F#布道师。 他和 Jon Skeet 一块儿编写了《Real-World Functional Programming》一书,说明了函数式的概念,并向有 C# 背景的开发者说明如何使用F#。 Tomas 仍是 DEVSENSE 的共同创始人,他对不少开源项目都作出了贡献,包括 Phalanger 和F#语言针对 MonoDevelop 的集成。
参考信息
[1] The Phalanger 网站包含了关于项目的最新消息。
[2] 文档和介绍(Phalanger Wiki)
[3] Phalanger 2.1下载包括安装程序和源代码(CodePlex)
[4] PicoMVC 项目使用 Phalanger 做为轻量级的视图引擎(Robert Pkckering 的 Strange 博客)
[5] PHP 做为针对 C# 的脚本语言 讨论了另外一种对 Phalanger 的用法(Phalanger 博客)
[6]以类型安全的方式在 C# 中使用 PHP 对象(Using PHP objects from C# in a type-safe way) 说明了 Phalanger 提供的,用于从 C# 访问 PHP 对象的安全机制。
[7]Phalanger 利用 DLR 的优点宣布了 Phalanger 2.1 的发布(Phalanger 博客)
[8] Jadu CMS 和 Microsoft .NET ——使用 Phalanger 把 PHP 应用程序编译到 .NET 的案例学习 [9]Phalanger 支持包含了额外托管的 PHP5 扩展(DEVSENSE)
[10] Phalanger 评测 包含额外的性能信息
转载出处:http://www.iis7.com/c/90/