Pre-compiled ASP.NET PHP Website

Traditionally, PHP websites are hosted on Windows using IIS or Azure, but this standard approach has a few well-known drawbacks. In this article, we will take a look at how Peachpie allows you to run PHP websites on the ASP.NET Integrated Pipeline and why this is desirable.

Background

For years, PHP websites have been hosted on Windows on top of the Internet Information Services (IIS) or Microsoft Azure. This approach continues to be very common despite several known shortcomings. Peachpie offers an alternative solution by running PHP websites as a seamless component of the ASP.NET Integrated Pipeline, without CGI or FastCGI, providing a high throughput and all the benefits of managed code and the .NET Framework.

ASP.NET & Peachpie Project Recap

On Windows and Windows Servers, ASP.NET provides a standardized environment for running web apps. It is deeply integrated into IIS and IIS Express (and Azure). Naturally, ASP.NET provides the best environment for .NET code.

In order to make PHP code a .NET citizen, we will take advantage of Peachpie, which is on its way to becoming a complete re-implementation of the PHP runtime, as well as a compiler for .NET. Thanks to Peachpie, the PHP code can be compiled into a .NET .dll file, just as if it were a C# code.

Prerequisites

In order to perform this tutorial, the following components are required:

  • Windows & IIS
  • .NET Framework 4.6
  • MSBuild 15.0

ASP.NET Pipeline

We won’t discuss the ASP.NET pipeline in details, but there are a few key components:

Firstly, the configuration. The well-known `web.config` file provides various possibilities of configuring and tuning the web application. We will seamlessly use existing standard configuration options to configure our PHP web. In this way, you can configure URL rewriting rules, security and more.

Secondly, the so called Request Handler. It is the entry point of every request that reaches our web server. For every kind of request, we can implement a different Request Handler, so we will have one for PHP files (`*.php`).

Putting both of these things together gives us a single line of configuration that lets the web server know how to handle PHP files. Below is a sample `web.config` file that will be placed in the root of our web site:

[xml]
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="PhpHandler" path="*.php" verb="*" type="Peachpie.RequestHandler.RequestHandler,Peachpie.RequestHandler" />
</handlers>
</system.webServer>
</configuration>
[/xml]

`web.config`

Peachpie.RequestHandler

Notice the request handler type Peachpie.RequestHandler.RequestHandler,Peachpie.RequestHandler on line 5. This is the component from the Peachpie project that we will download as a NuGet package later in this article. Its purpose is to handle requests for .php files by simulating the PHP environment and executing compiled PHP code.

Adding some PHP code

For demonstration purposes, let’s add some PHP code:


`index.php`

Compiling PHP to .NET

This most important step provides the instructions on how to compile the contained PHP files into a DLL, which will then be used by the Request Handler. There are several ways how to do this, including the command line utility peach.exe. The recommended option is to use MSBuild, which can then be utilized on the command line, in Visual Studio or on a build server etc.

[xml]
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<ProjectGuid>0e51d101-0992-4aa6-a134-26ea3f2e3934</ProjectGuid>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<OutDir>.bin</OutDir>
</PropertyGroup>
<ItemGroup>
<Compile Include="**/*.php" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Peachpie.Compiler.Tools" Version="0.8.0-*" />
<PackageReference Include="Peachpie.NET.Sdk" Version="0.8.0-*" PrivateAssets="Build" />
<PackageReference Include="Peachpie.RequestHandler" Version="0.8.0-*" />
</ItemGroup>
</Project>
[/xml]

`website.msbuildproject`

Save the text above into a project file, e.g. website.msbuildproject. All the required dependencies including the Request Handler are specified as a PackageReference and will be deployed into the `/bin` folder upon building the project by MSBuild.

Line 6 sets the target framework to the .NET Framework 4.6, and most importantly, line 10 tells MSBuild to compile all `*.php` files. The compiler itself and the runtime (Peachpie) used to perform the compilation are also downloaded as a NuGet package (lines 13, 14).

Notice that we don’t have to install any additional software to the server. Everything is obtained from the Internet as a NuGet package, just as if it were another dependency of your .NET application.

[bash]
# if you prefer the .NET Core way
dotnet restore
dotnet build
[/bash]

or

[bash]
# if you have Visual Studio 2017
msbuild /t:restore website.msbuildproj
msbuild /t:build website.msbuildproj
[/bash]

The step above (whichever one you prefer) will download the NuGet packages and compile the PHP code into a DLL file, which will be placed within your `/bin` folder. The Request Handler will find it there.

Add an Application in IIS

Now you have to tell the web server about your website. Either place all the files above into the default website root (something like `C:inetpubwwwroot`) or create a new web application in your IIS Management Console. It is important to use the application pool running on .NET 4 with Managed Pipeline Mode : Integrated.

IIS Application Pool Advanced Settings

IIS Site Advanced Settings

The complete application consists of the following files within C:inetpubwwwroot:

  • index.php
  • web.config
  • website.msbuildproject

That’s it

Now you can navigate to `http://localhost`. You will see a compiled PHP code output running natively on the ASP.NET Pipeline as a true managed application. This solution opens the door for many other great features like .NET interoperability, profiling, debugging or configuring other security options.

Posted on August 22, 2017, in category Information, Tutorial, tags: , , , , , ,