BT

Integrating PHP with .NET Using Phalanger

Posted by Tomas Petricek on Oct 12, 2011 |

Phalanger is a PHP language compiler and a PHP runtime for .NET. It can be used to compile PHP web projects into .NET bytecode and execute them as ASP.NET applications using either IIS on Windows or using Mono and Apache on Linux. However, Phalanger goes beyond just compiling existing PHP applications to .NET.

Phalanger can be used to create solutions that combine .NET and PHP in ways that are not possible with the standard PHP interpreter. Thanks to Phalanger extensions, PHP programs can directly use .NET classes and .NET programs (e.g. written in C#) can dynamically invoke PHP scripts or use functions and classes implemented in PHP [6].

In this article, we’ll briefly introduce Phalanger and then look at three usage scenarios. We’ll discuss how to integrate PHP applications with ASP.NET; how to efficiently run PHP applications on Windows and how to use PHP as a view engine for ASP.NET.

Introducing Phalanger

Phalanger has been around for quite some time. The first version of Phalanger was created as a software project at Charles University in Prague in 2003. The development of version 2.0 started later and was released as open-source project in 2006 on CodePlex. Microsoft supported the project for a while and one of the Phalanger developers later joined Microsoft to work on the Dynamic Language Runtime (DLR).

The activity on Phalanger resumed in 2008 thanks to collaboration with Jadu which used Phalanger to build a .NET version of their CMS developed in PHP [8]. Since 2010, the development of Phalanger has been mainly funded by DEVSENSE, which provides commercial support for Phalanger. Recently released version Phalanger 2.1 [7] improves compatibility with the standard PHP implementation, takes advantage of the DLR in the implementation of dynamic operations and provides better interoperability between PHP and other .NET languages (like C#, F# and Visual Basic).

Components of Phalanger

Phalanger consists of several, partly independent, components that can be used to develop PHP applications running on .NET and to run them using .NET or Mono:

  • Phalanger Compiler. Phalanger compiles PHP source code into .NET assemblies that are executed using .NET JIT (Just-in-time compiler that generates native code for the current platform). Compiled PHP code uses Phalanger Runtime and Dynamic Language Runtime that provides efficient implementation of dynamic features of the PHP language.
  • Phalanger Runtime and Libraries. The Phalanger Runtime provides an implementation of PHP features like arrays. Phalanger also comes with a .NET implementation of standard PHP libraries for I/O, regular expressions and others.
  • Native Extensions. On 32 bit Windows platform, Phalanger is capable of using any existing PHP 4 extension via a native bridge. Despite some runtime overhead, this makes it possible to run some PHP applications without additional effort.
  • Managed Extensions. PHP extensions can be also re-implemented by wrapping similar functionality available in .NET. These extensions can be written in any .NET language and provide great performance. Phalanger comes with several extensions including SPL, JSON, SimpleXML, MySQL and MS SQL providers. Additional extensions such as Memcached, image, or cURL are available from DEVSENSE [9].
  • Visual Studio Integration. Phalanger also integrates with Visual Studio (recently updated to support Visual Studio 2010). The integration adds color highlighting and IntelliSense for PHP files and allows debugging of PHP applications running using Phalanger.

Phalanger Use Cases

Phalanger is largely compatible with PHP 5 and can run a large number of open-source PHP projects including WordPress and MediaWiki. It can be used to integrate these projects in a .NET ecosystem as well as to develop new projects that combine the benefits of PHP and .NET. In the rest of the article, we discuss the following three use cases:

  • Scenario #1: Running PHP Applications Efficiently. The performance of PHP applications compiled using Phalanger on Windows is better than when using a standard PHP interpreter via FastCGI. This makes Phalanger an attractive option for hosting PHP in Windows environment.
  • Scenario #2: Integrating WordPress with ASP.NET. PHP code compiled using Phalanger can call any .NET library. This can be used to share database of users or other data between PHP and ASP.NET applications.
  • Scenario #3: Calling PHP from ASP.NET Applications. The flexibility of PHP is useful for scripting or writing the presentation layer of web applications. Thanks to Phalanger, it is possible to develop an application in .NET and use PHP as a scripting language or a view engine.

The following three sections discuss each of the scenarios in detail. We first give a general overview and then look at some technical details that demonstrate interesting aspects of Phalanger.

Scenario #1: Running PHP Applications Efficiently

Phalanger makes running PHP applications efficient for two reasons. Firstly, it compiles the PHP source code instead of interpreting it and secondly, it runs the application as an ASP.NET application, which provides additional performance benefits on Windows.

Compiling PHP using Phalanger and .NET

The compilation process is shown in Figure 1. As the diagram shows, Phalanger compiles PHP source code to a .NET IL (Intermediate Language), which is a low-level bytecode that is independent of the architecture. The compiled code uses PHP Core Library (a part of Phalanger) and Dynamic Language Runtime (DLR) to perform standard PHP operations. When the application starts, the .NET JIT (Just-in-time) compiler turns all these components into a native code optimized for the current processor architecture.

Figure 1. Compilation of PHP source code to native code using Phalanger

As Phalanger Benchmarks show [10], the performance of WordPress compiled using Phalanger on Windows is significantly better than when using standard PHP interpreter via FastCGI and slightly better than using PHP with WinCache. However, the benchmarks did not test the most recent version of Phalanger that is further optimized using the DLR.

Hosting PHP applications using ASP.NET

Phalanger applications run in the same mode as ASP.NET applications. This gives an important performance advantage, especially on Windows systems where processes are more expensive than threads.

The diagram in Figure 2 shows different options for running PHP applications.

When using the standard CGI mode, the web server starts a new process for every incoming request. On Windows, this is inefficient, but it also prevents sharing state in a shared memory or easy in-process caching. When using FastCGI mode, the web server reuses processes, so it doesn’t have to start new process for every request. However, it is still not possible to share state in memory, because different processes would have different state.

(Click on the image to enlarge it)

Figure 2. Running PHP using CGI, FastCGI and Phalanger

Phalanger behaves just like any ASP.NET application. A single ASP.NET process, called Application Pool handles all incoming requests. It is even possible to configure multiple PHP applications (such as several independent instances of WordPress) in a single process (Application Pool). Inside the process, there are multiple threads that are re-used to handle individual requests. On Windows, threads are more lightweight than processes, so this is more efficient and less memory-consuming solution.

That the application runs in a single process allows further optimizations and other interesting scenarios. For example, Phalanger uses the Dynamic Language Runtime (DLR) for dynamic method invocation. DLR uses a caching mechanism that adapts over time, so after several requests, the DLR “learns” what methods the application uses and becomes faster. This is only possible if requests are handled within a single process.

Running all code in a single process also means the application can store global state in memory. This can be used to implement functionality similar to the User Cache provided by WinCache, but without the overhead of inter-process communication.

Scenario #2: Integrating WordPress with ASP.NET

One of the benefits of PHP is the wide range of excellent open-source CMS systems (WordPress, Joomla, etc.), form applications (phpBB and others) or wikis (MediaWiki and others), many of which have been tested with Phalanger.

These applications often provide more features than similar packages for the .NET platform. A company that develops an ASP.NET based web page may face the following situation:

  • It needs to add wiki, forum or blogs to an existing ASP.NET solution, but the only suitable applications (e.g., free, with all necessary features) are available in PHP.
  • The application may run under a sub-domain, but it should share the user database. Moreover, once the user signs-in on the main page, it should remain signed-in on the wiki, forum or a blog.

ASP.NET applications can use ASP.NET Membership, which is a standardized mechanism for managing users, roles and their profiles. With Phalanger, it is possible to modify any open-source PHP project to use the same mechanism. The next section demonstrates how this works using WordPress.

Implementing ASP.NET Membership Plugin for WordPress

If you’re not interested in code, you can skip this section and look at the third scenario. However, we won’t look at any technical details – just a very brief overview of PHP extensions that allow PHP to call .NET libraries.

Handling of users in WordPress can be easily customized using a plugin. The plugin for managing users’ needs to implement a PHP class with various member functions. One of the expected functions is authenticate, which gets a user name and a password. It should fill information about the current user or set the name to NULL if the user does not exist.

To implement authentication using ASP.NET Membership in .NET, we can use functionality from the System.Web.Security namespace. The static method Membership.ValidateUser tests whether the password is correct and Membership.GetUser returns basic information about the user. Using Phalanger, we can access .NET objects as if they were standard PHP objects, so implementing the authentication is easy. Listing 1 shows a simplified version of the code.

Listing 1. Function implementing authentication in a WordPress plugin

import namespace System:::Web:::Security;

function authenticate(&$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->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 = username_exists($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;
  }
}

The code starts with an import namespace declaration. This is a non-standard Phalanger extension that imports functionality from a .NET namespace of one of the referenced assemblies (assemblies can be referenced using a web.config file). In a future version, Phalanger will use standard namespaces as supported by PHP 5.3, but this change is not fully implemented yet.

The rest of the code looks like standard PHP code. However, the Membership class is actually a standard .NET class. Phalanger treats PHP classes and .NET classes equally, so we can use standard syntax for calling .NET methods. The functions ValidateUser and GetUser are static functions, so they are called using the :: syntax. The result of GetUser is a .NET object MembershipUser with various properties that contain basic information about the user. Again, we can use the standard notation to access fields of the object (which are implemented as .NET properties).

As you can see, using .NET functionality from PHP is very natural. Since the code is compiled to .NET assembly, there is also no overhead when calling .NET libraries. The next section shows integration in an opposite direction – calling PHP from .NET application.

Scenario #3: Calling PHP from ASP.NET Applications

The main advantage of PHP is its flexibility and simplicity, which makes it a great language for writing scripts or implementing rendering of HTML. However, some people find it easier to implement large-scale applications in statically-typed languages such as Java or C#. Using Phalanger, we can get the best of both worlds.

The scenario discussed in this section demonstrates one way to combine ASP.NET and PHP. It is based on the modern ASP.NET MVC (Model View Controller) Framework that separates the presentation layer, layer responsible for interaction and the business logic of the application. We can develop individual components in different languages:

  • C# Model and Controllers. The model and the controllers will be written in C#. This part of the application implements the business logic, which is often easier to write in a statically-typed language, especially if the logic becomes more complicated. Moreover, it is possible to use technologies like LINQ for data access and Task Parallel Library to implement high-performance calculations using multiple threads.
  • PHP Views. The presentation layer of the application will be written in PHP. This is where the simplicity and flexibility of PHP provides the most benefits. Moreover, it means that this part of application can be written by less experienced developers, because most of web developers and web designers know some PHP.

There are other situations where calling PHP from C# would be useful. For example, you can use PHP as a scripting language in a larger C# project. This is again very useful, because PHP is a widely known language. Another situation is when using PHP library from C# - this is largely simplified thanks to Phalanger’s duck typing mechanism, which can even generate a statically-typed C# interface for calling well documented PHP code.

In the rest of the article, we focus on the scenario that uses PHP to implement presentation layer of an ASP.NET application. You can find references to information about other scenarios (such as scripting) at the end of the article.

Creating Model-View-Controller Application in C# and PHP

Let’s first look at a simple application we could create using a combination of C# and PHP. The Model and Controller of the application is written in C# and are shown in Listing 2. In the example, the model is just a simple C# class representing information about products. In reality, this would be responsible for loading data from a database and might be implemented using LINQ.

Listing 2. Model and Controller of a sample web application (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();
  }
}

The controller component is implemented by the HomeController class, which inherits from ASP.NET MVC Controller. The class contains a single action representing the index page of the application. The action will be invoked when the user accesses /Home/Index (or just the root URL). It creates the model (instance of Product class) and passes it to the View component.

In a standard ASP.NET MVC application, the View component is typically implemented using ASPX page or using Razor view engine with code written using C# or Visual Basic. Phalanger makes it possible to use PHP in the implementation of the views. Listing 3 shows an example.

Listing 3. View of a sample web application (PHP)

<html><head>
  <title>Sample view written in PHP</title>
</head>
<body>
  <h1>Product Listing using Phalanger</h1>
  Product: <? echo $MODEL->ProductName; ?><br />
  Price: <? echo $MODEL->Price; ?>
</body></html>

The view is rendered using and ASP.NET MVC extension described below. The extension executes the PHP script shown in Listing 3 and defines a global variable named $MODEL that contains the data returned by the controller. In the above example, $MODEL is a reference to a standard .NET class. Phalanger treats .NET classes as equal to PHP objects, so it is very easy to display properties of the product using the echo construct.

The example shows the basic structure of the application, but it is extremely simple, so it doesn’t really show all the benefits we can get by using PHP in the presentation layer:

  • The dynamic nature of PHP makes it easy to render data of any structure. The view is not limited to simple scripts, but can use any existing PHP libraries, including popular templating engines.
  • The view can be structured into multiple files using PHP include, so you have full control over how the page is generated.
  • The developer creating the view doesn’t need to know anything about .NET. This means a company transitioning from PHP to C# can still leverage existing developer skills.

To give you some idea how this scenario works, the following section reveals some technical details about the PHP and C# integration. If you’re not interested in the details, you can go straight to the summary.

Looking Under the Cover

The scenario described in this section is based on the PicoMVC project [4], which allows combining PHP with F#. To keep the examples simpler, I translated them from F# to C#. The core of the PHP integration in PicoMVC is a simple function that takes a file name of a PHP script and runs it using the Phalanger runtime. The function is shown in Listing 4.

Listing 4. Calling PHP script from an ASP.NET web application.

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);
  }
}

The PhalangerView method gets a file name (referring to a PHP script), a .NET object that represents the data returned as a model, and a current HTTP context. It first initializes RequestContext, so Phalanger knows it is processing a script as part of HTTP request. Then it ensures all output generated by the PHP script is sent directly as a HTTP response. When running PHP as a script, the output can be redirected to a memory stream and processed in a different way. Finally, the method declares a global variable MODEL and executes the PHP script using the Include method provided by Phalanger.

This example is not a definitive guide on calling PHP scripts from C# - you can find more detailed information in an article on the Phalanger blog. However, it should demonstrate that calling PHP scripts from C# using Phalanger is quite easy. This can be useful in the web programming scenario discussed in this section, but it gives a wide range of other options.

Summary

This article briefly introduced Phalanger – a PHP compiler for .NET – and several scenarios where it can be used to solve important problems in practice. The Phalanger project has been very active recently and version 2.1 includes many compatibility improvements, use of Dynamic Language Runtime (DLR) for better performance, as well as Visual Studio 2010 integration.

We looked at three scenarios where Phalanger can be used in web development. The first case was using Phalanger to run an unmodified open-source PHP project (such as WordPress) in Windows environment. Thanks to the fact that applications compiled using Phalanger run as ASP.NET, the hosting is more light-weight and can be more efficient.

In the second scenario, we looked at integrating PHP application in a .NET ecosystem. Thanks to the Phalanger extensions, it is possible to call .NET libraries directly from PHP code. This can be used, for example, to integrate user databases between ASP.NET applications and WordPress.

Finally, the last scenario demonstrated a web framework that uses PHP as a language for writing views in ASP.NET MVC. This way, .NET developers can easily provide business functionality of the application and PHP developers can use it directly in the presentation layer.

About the Author

Tomas Petricek is Microsoft C# MVP and F# enthusiast. Together with Jon Skeet, he wrote a book Real-World Functional Programming that explains functional concepts and F# to developers with C# background. Tomas is also a co-founder of DEVSENSE and he contributed to numerous open-source projects including Phalanger and F# language integration for MonoDevelop.

 

 

References

[1] The Phalanger homepage contains recent news about the project
[2] Documentation and installation instructions (Phalanger Wiki)
[3] Phalanger 2.1 downloads including installer and source code (CodePlex)
[4] PicoMVC project uses Phalanger as a lightweight view engine (Robert Pickering’s Strange Blog)
[5] PHP as a scripting language for C# discusses another possible use of Phalanger (Phalanger Blog)

[6] Using PHP objects from C# in a type-safe way explains a safe mechanism provided by Phalanger for accessing PHP objects from C# (Tomas Petricek’s Blog)
[7] Phalanger takes advantage of DLR announces a release of Phalanger 2.1 (Phalanger Blog)
[8] Jadu CMS and Microsoft .NET – a case study using Phalanger to compile PHP applications to .NET

[9] Phalanger support includes additional managed PHP5 extensions (DEVSENSE)
[10] Phalanger benchmarks contains additional performance information (Phalanger Blog)

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2014 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT