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.
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
When 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.
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.
Using dotPeek we can also see IL code of this class.
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.
- Download project from https://github.com/iolevel/peachpie-wordpress
- Extract files to some folder
- Install MySQL if you don’t have one to use and run it
- Change database connection settings in wp-config.php
- Open command line and go to the folder where you copied WordPress project files
- Run the following commands:
dotnet restore
cd app
dotnet run - Wait few minutes until application is compiled and started
- 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
- Peachpie home page
- Peachpie Benchmarks
- Peachpie @ GitHub
- Peachpie wiki
- Peachpie for Visual Studio Code
- WordPress on Peachpie
- Peachpie – Open Source PHP Compiler to .NET and WordPress under ASP.NET Core (Scott Hanselman)
Hey Gunnar,
Wonderful article, absolutely fantastic. Check out the sample C#/PHP hybrid app below:
https://github.com/iolevel/peachpie-samples/tree/master/csharp-php-hybrid
You were asking about interoperability, that sample is basically it. We have also written blog posts about this topic before, see:
http://www.peachpie.io/?s=interoperability
Kind regards,
Ben (Peachpie core development team)