Skip to content

Self-contained PHP app

PHP programs usually need a runtime installed on your target machine, appropriate version of PHP itself, a web server and some sort of configuration. This is no longer needed when you are compiling PHP code into .NET. The PHP web or console program can be distributed as a self-contained executable with no such dependencies.

Preqrequisites

The only initial prerequisite for the development environment is the .NET 8 SDK. However, this is only needed during development; after you create your self-contained executable, this is no longer required.

Simple PHP console program

Let’s start with the basics. Create a small console application (you can grab it from github.com/iolevel/peachpie-samples/console-application):

main.php:

<?php
echo "Hello world!";
program.msbuildproj:
<Project Sdk="Peachpie.NET.Sdk/0.9.42">
  <PropertyGroup>
    <OutputType>exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <StartupObject>main.php</StartupObject>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**/*.php" />
  </ItemGroup>
</Project>
And that’s actually it. Now you can do everything you are used to doing with a regular .NET Core application, including building, running, or publishing as a self-contained package (as shown below).

PICTURE MISSING HERE

To just run it, try this command on your favorite shell: dotnet run

Simple PHP web site

A compiled web site is almost the same as the console program above. The most notable difference is that we include the lightweight ASP.NET Core web server in C# together with the PHP code. Grab the project at github.com/iolevel/peachpie-samples/web-application, or create the project as described on https://docs.peachpie.io/get-started/.

Note: the web server is now a part of the PHP web site. You don’t have any dependencies on Apache, IIS or anything else.

Creating the executable

Let’s start by typing the following command in your terminal:

dotnet publish -c release

This compiles the project(s) into binaries, using the release build configuration, and places the result of the compilation into the /bin/release/netcoreapp2.1/publish folder. But this still has a dependency on the .NET runtime – it’s not a self-contained executable just yet!

Next, we have to know what system we are targeting. Take a look at Microsoft's documentation, where you can see different runtime identifiers (RIDs). By specifying the RID, you create the real self-executable that runs without any other dependency on the specified system. For example, let’s build the application for 64bit Windows:

dotnet publish -c release -r win-x64

Or for Linux:

dotnet publish -c release -r linux-x64

That’s it. This creates a native executable for the platform of your choice. For more information on the publishing process, check out Microsoft's docs.

Reducing the executable size

The most frequent question regarding self-executables is how to reduce the size of such an application. Since you are including the entire .NET runtime together with your executable, the size is unnecessarily big. There are, however, a few recommended approaches you can take advantage of in order to reduce the executable size:

  • On Linux, you can get rid of culture-specific functionalities and keep just the “Invariant” culture features. This cuts about 26MB of data. Details here.
  • Use dotnet-warp to merge DLL files and remove unnecessary IL and methods. Read more in Scott Hanselmann’s blog post. A little note: rename the project file so it has the .csproj extension, it will work just fine.

Obfuscation

Another question we often get asked: can we obfuscate the compiled code? You can, but keep in mind that PHP strongly depends on reflection and function names, so although you can indeed use any .NET tool for the obfuscation, I would recommend not to rename method names, class names and class members. You can obfuscate the IL or metadata, however.

Conclusion

Taking full advantage of all the amazing .NET Core tooling, we can now create self-contained PHP applications, with a built-in the web server. It is pretty simple, source-less, and relatively small, and yet another interesting benefit of the bi-directional interoperability PeachPie compiler provides for PHP and .NET.

Resources

  • RIDs: docs.microsoft.com/en-us/dotnet/core/rid-catalog
  • dotnet-warp: hanselman.com/blog/BrainstormingCreatingASmallSingleSelfcontainedExecutableOutOfANETCoreApplication.aspx
  • PeachPie getting started: https://docs.peachpie.io/get-started
  • dotnet publish: docs.microsoft.com/dotnet/core/tools/dotnet-publish
  • More samples: github.com/iolevel/peachpie-samples
  • ASP.NET Core Web Server: docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/