After months of implementing the required PHP functionality in Peachpie, our platform is now finally ready to run a larger real-world application: WordPress.

Announcing WordPress on .NET

The popular Phalanger project already proved that running a virtually unmodified clone of WordPress on Microsoft .NET is possible. Still the solution had its issues and was not compatible with new WordPress releases. Now the successor to Phalanger, Peachpie, is also able to run WordPress as a fully managed application on .NET and .NET Core.

Please consider this a proof of concept and keep in mind that Peachpie is still a work in progress. We do not recommend using this in a production environment yet. Our primary objective with this announcement is to prove that Peachpie really is compatible with the standard PHP used in WordPress and to demonstrate its benefits.

Motivation

There are several reasons why it is desirable to run WordPress on .NET:

Performance: compiled code is fast and also optimized by the .NET ‘Jitter’ for your actual system. Additionally, the .NET performance profiler may be used to resolve bottlenecks. C# Extensibility: plugin functionality can be implemented in a separate C# project and/or PHP plugins may use .NET libraries. Sourceless distribution: after the compilation, most of the source files are not needed. Power of .NET: Peachpie allows the compiled WordPress clone to run in a .NET jittered, secure and manageable environment, updated through windows update. No need to install PHP: Peachpie is a modern compiler platform and runtime distributed as a dependency to your .NET project. It is downloaded automatically on demand as a NuGet package or it can be even deployed standalone together with the compiled application as its library dependency.

Last but not least, we simply wanted to prove that it works. This article will show how.

Prerequisites

.NET Core 1.0

MySQL Server

Modifications to the original WordPress

As of Peachpie version 0.5.0, the compiler does not support classes extending a class that is declared conditionally, e.g.

wp-includes/class-json.php:

Commented condition if (!class_exists(...))

Commented first class Services_JSON_Error (we don’t have PEAR_Error yet), keeping the second one

We prepared a version of WordPress with these modifications already included for you to compile the project easily.

Download WordPress From Here

In addition, we preconfiguired the wp-config.php file containing the credentials for the MySQL database. We are using the default port 3306, password ‘password’ and the server is ‘localhost’.

Compiling WordPress

The compilation is driven by dotnet and its website/project.json project file.

{ "version": "1.0.0", "buildOptions": { "compilerName": "php", "compile": "**\*.php", "debugType": "portable", "xmlDoc": true }, "dependencies": { "Peachpie.App": "0.5.0-*" }, "tools": { "Peachpie.Compiler.Tools": "0.5.0-*" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } } } } }

This is all dotnet needs to compile WordPress. It even downloads Peachpie by itself from nuget.org. Line 5 specifies that the compiler is ‘php’ instead of the default ‘csharp’. The next line lists the files included into the compilation. In line 11 we tell dotnet there is a dependency to the Peachpie runtime and default libraries. It will be automatically downloaded from nuget.org if the component has not been downloaded yet. Similarly, line 14 tells dotnet to use the Peachpie.Compiler.Tools package during the compilation process. It actually contains the whole compiler and is again downloaded and used seamlessly.

Web Server

WordPress as such contains a plethora of script files, but you still need a web server to run them. Since we are now in a .NET Core environment, we can use Kestrel – an open-source lightweight web server that is completely modular. Peachpie even contains an extension for Kestrel, which allows it to handle *.php requests and to process them with a DLL library compiled from the PHP project.

app/Program.cs

static void Main() { var root = Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory()) + "/website"; var host = new WebHostBuilder() .UseKestrel() .UseWebRoot(root).UseContentRoot(root) // content root with wp static files .UseUrls("http://*:5004/") .UseStartup<Startup>() // initialization routine, see below .Build(); host.Run(); } class Startup { public void Configure(IApplicationBuilder app) { Pchp.Core.Context.DefaultErrorHandler = new Pchp.Core.CustomErrorHandler(); // disables debug asserts app.UsePhp(); // installs handler for *.php files and forwards them to our website.dll app.UseDefaultFiles(); app.UseStaticFiles(); } }

app/project.json

{ "version": "1.0.0", "buildOptions": { "emitEntryPoint": true, "debugType": "portable" }, "dependencies": { "Microsoft.AspNetCore.Server.Kestrel": "1.1.0", "Microsoft.AspNetCore.StaticFiles": "1.1.0", "Peachpie.NETCore.Web": "0.5.0-*", "website": "*" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } } } } }

The project.json file of the web server has dependencies to Kestrel packages, to the Peachpie web extension and the website project (our WordPress itself), causing dotnet to copy the result of the website compilation (website.dll) to the output folder of our web server.

Putting it all together to run WordPress on .NET

Now you know what the project looks like and how to get everything set up.

In order to make this all work, first ensure you did all the prerequisites.

On our development computer, we will use the virtualization platform Docker to create a MySQL server. If you have MySQL installed on your machine, you can simply use that. It is important that the information in your wp-config.php file is correct. We will use the following command to start our MySQL with the required information:

docker run -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress -p 3306:3306 -d mysql

Note: On PCs with Windows 10 Home edition, you could run into trouble running Docker. Make sure you either have MySQL installed locally or that your virtualization platform works, otherwise WordPress will not run.

In order to tell dotnet to download and update the dependencies, run the following command:

dotnet restore

Now you should see that .NET Core itself, Peachpie and other dependencies are being downloaded and copied to the local NuGet cache.

The next command performs the compilation using the C# and Peachpie (PHP) compiler for your current platform. It is important to run the command within the app directory (because we were too lazy to look up the ‘website’ directory in program.cs in a more civilized way). The command also runs the app project.

cd app dotnet run

If everything goes as planned, you should see something like:

Hosting environment: Production Content root path: d:Projectspeachpie-wordpress/website Now listening on: http://*:5004 Application started. Press Ctrl+C to shut down.

Open your web browser and go to http://localhost:5004:

There it is. You are running WordPress on .NET and you can begin with its installation as if it were regular PHP. You will then see the classic WordPress login window:

After logging in with the credentials you set, you will see the familiar WordPress dashboard:

And here is our WordPress site, running on .NET Core:

To prove that the site really is running on .NET Core, let us take a look at ILSpy. The screenshot below shows generated MSIL instructions in the compiled website.dll assembly. Note, ILSpy does not know ‘portable’ debug symbols (website.pdb). In order to use ILSpy, delete the PDB file first.

And here is a snippet of that very MSIL code decompiled to the C# language, just to make it more legible:

We hope you enjoy the option of running one of the greatest blogging and CMS platforms in the secure, fast, and managed environment of Microsoft .NET. Please keep in mind that we are still working on the development of Peachpie, so we do not recommend using this in a production environment yet, as not all functions are already supported.

If you encounter any issues, please do not hesitate to share them with the community, we do our best to answer all inquiries there.

Make sure you follow our progress on GitHub, Twitter and Facebook, and stay tuned for more updates.