Running PHP applications on .NET Core

Ever wondered about mixing up simplicity and flexibility of PHP with power and performance of .NET Core? The solution is coming and it is called Peachpie, the successor of Phalanger. This blog posts introduces Peachpie – the tool to compile PHP code to .NET Core – and helps to get started with it.

Peachpie

Why Peachpie?

For years there was thing called Phalanger that lived a silent life somewhere in internet. At least it didn’t made its way to my work desk. Now, years later, it is reincarnated as Peachpie and now it looks really promising. Peachpie allows us to build and run PHP code on .NET Core. By example, they made WordPress run on .NET Core almost successfully,

Important! Peachpie is not about writing .NET code using PHP. Peachpie is about running PHP code on .NET.

Is there any point for solution like this business wise? It looks very promising if full PHP compilation starts working on day that is hopefully in near future. The question is not what we benefit when using Peachpie and Visual Studio tooling. The question is what we benefit when building PHP code to .NET Core and run it as compiled one? The answer is simple: take a look at Peachpie benchmarks!

Getting started

Peachpie is easy to install. All we need is dotnet utility that comes with .NET Core, Open command line and run the following commands.

mkdir MyWebSite1
dotnet new -i Peachpie.Templates::*
dotnet new peachpie-web
cd MyWebsite1.Server
dotnet restore
dotnet run

If MS Build reports errors then open project file in MyWebSite1 folder (not MyWebSite1.Server) and comment out the following line in the end of file.

<Import Project="$(CSharpDesignTimeTargetsPath)" />

After this application should build and run without errors. This is how Peachpie solution is created, built and run fully on command line.

Peachpie solution

Peachpie solution in Visual StudioWhen run with dotnet utility Peachpie creates solution that can be opened in Visual Studio. There are two projects (I created solution to folder phpnet and this is why my solution is named as phpnet):

  • phpnet – this project hosts all PHP files that make up PHP solution,
  • phpnet.Server – this project is for building and running PHP solution.

Program.cs file is interesting one. It contains Program and Startup classes as both classes are very small in sample application. Assembly built of PHP files is included very politely in Configure() method of Startup class.

public void Configure(IApplicationBuilder app)
{
    app.UseSession();

    app.UsePhp(new PhpRequestOptions(scriptAssemblyName: "phpnet"));
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

Those of my readers who come up with serious questions at conferences want to ask now one question: what happens when I add MVC to solution?

Adding ASP.NET Core MVC to PHP solution

Although I don’t see much point on doing this we can actually use ASP.NET Core MVC is same solution with PHP. As NuGet has issues on adding and updating packages in PHP solution I had to modify project file of phpnet.Server manually. This is how NuGet packages section looks like in my project file.

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
  <PackageReference Include="Microsoft.AspNetCore.Session" Version="1.1.2" />
  <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
  <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="1.1.2" />
  <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
  <PackageReference Include="Peachpie.NETCore.Web" Version="0.7.0-*" />
</ItemGroup>

I restored packages from command line after the change and got no errors. After this I added MVC to request pipeline.

class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromMinutes(30);
            options.CookieHttpOnly = true;
        });

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseSession();

        app.UsePhp(new PhpRequestOptions(scriptAssemblyName: "phpnet"));
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
        app.UseDefaultFiles();
        app.UseStaticFiles();
    }
}

I built solution and ran it. The following screenshow shows the results.

Peachpie: PHP and ASP.NET Core MVC in same application

This good conference crowd wants to know now one more thing. What happens when MVC is added to request pipeline before PHP? It can be easily done and in this case MVC processes request first. If application root is requested then “Hello from ASP.NET!” is shown. When index.php is requested then “Hello from PHP” is shown. So, Peachpie knows also about PHP file names that were used in PHP solution.

I didn’t found much information about .NET Core and PHP interoperability and therefore I don’t know to what point it is possible currently. I’m sure they will provide interoperability in future as it opens one new option: handling execution over to .NET code in some points of code.

Decompiling compiled PHP code

Using dotPeek by JetBrains it is possible to decompile .NET executables. I opened phpnet.dll file from bin folder of my web application and decompiled index_php class. This is how this what compiler produces from PHP.

Peachpie: PHP code compiled to .NET

Using dotPeek we can also see IL code of this class.

Peachpie: Compiled PHP code in IL

Using dotPeek it is possible to explore also contents of other libraries.

WordPress example

Peachpie uses their version of WordPress as an example of PHP compilation to .NET. Here is how to set it up.

  1. Download project from https://github.com/iolevel/peachpie-wordpress
  2. Extract files to some folder
  3. Install MySQL if you don’t have one to use and run it
  4. Change database connection settings in wp-config.php
  5. Open command line and go to the folder where you copied WordPress project files
  6. Run the following commands:
    dotnet restore
    cd app
    dotnet run
  7. Wait few minutes until application is compiled and started
  8. Open http://localhost:5004 in your favorite web browser

If everything went okay and there are no unexpected issues you should be able to see WordPress running in your browser. Don’t be surprised if you face problems – this is still on-going work you are playing with.

Wrapping up

Peachpie is interesting project. PHP code is translated and compiled to .NET Core and then run on .NET runtime. Although the project is in alpha right now it looks very promising. Especially when taking look at current benchmarks where it is compared to Zend. It would be good fit for cloud environments where PHP application get high work loads by customers, by example. It is not very clear from documentation how we can bridge PHP and .NET Core code but I hope that Peachpie offers also something for this in future. I think it is worth to keep eye on Peachpie project and try out what benefits it gives in case of PHP applications we currently build and manage.

Resources

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    One thought on “Running PHP applications on .NET Core

    Leave a Reply

    Your email address will not be published. Required fields are marked *