Inserting PHP scripts#
Before we will start to talk about using classes provided by Peachpie.Blazor
, we introduce the project background and steps to create it. The reader can skip it and use prepared templates, which can be arbitrarily customized. The instructions can be found in the overview.
Starting with empty solution#
Create a standard Blazor WebAssembly application (with .NET 5) and tick ASP.NET Core hosted.
We have to add a package reference for Peachpie.Blazor
library to BlazorApp.Client
and BlazorApp.Server
projects in order to be able to use helper classes providing script navigation and execution.
Now, we have to add support for PHP in the WebAssemblyHost
of BlazorApp.Client
project. Because of Blazor specification, we have to add reference on a type defined in the additional assembly in order to make the assembly be downloaded with the BlazorApp.Client
.
BlazorApp/Client/Program.cs
:
...
using Peachpie.Blazor;
...
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
// Add PHP
builder.AddPhp(new[] { typeof(typeInPHPScripts).Assembly});
await builder.Build().RunAsync();
}
...
The last change in the projects is to redirect navigation of https://sth/sth.php
to index.html
on the server side, which is done by modifying the APS.NET pipeline in the following way:
BlazorApp/Server/Startup.cs
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
...
app.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("index.html");
endpoints.MapFallbackToFile("/{**.php}", "index.html");
});
}
Add a new PeachPie project, where we will have our PHP scripts.
PHPScripts.msbuildproj
:
<Project Sdk="Peachpie.Blazor.Sdk/1.0.11936">
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFramework>net5.0</TargetFramework>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
</Project>
Now, we are ready to add PHP scripts to the web application. The server can be launched by dotnet run --project BlazorApp\Server
.
Inserting PHP scripts#
We have two options for how to insert PHP content into a Blazor web application. The first way uses PhpScriptProvider
class, which is a Blazor component. This component can be configured to execute and render specified script or can automatically find the best-matched script path with the current URL. The second choice is to inherit PhpComponent
class in PHP, which enables to access Blazor API.
Warning: When you have more than one instance of
PhpScriptProvider
orPhpComponent
in the running app (except in specific situations), the JS PHP interoperability will don't works properly (But the interop is an advanced feature, so you can don't bother with it now). This is a limitation of the current implementation.
Inserting PHP scripts into Razor pages#
Thanks to IComponent
interface, we can insert PhpScriptProvider
into Razor page as a normal Blazor component. We can configure a set of PHP scripts, which we want to be executed. The most simple configuration is to navigate just one script by the class.
The provider finds PHP scripts by their relative paths to the project folder. So, when we have https://[server]/folder1/folder2/file.php
URL, the provider tries to find the script with a relative path folder1/folder2/file.php
to the Peachpie project. Superglobal $_GET
works as you expect.
Navigating only one PHP script#
Index.razor
:
@page "/index.php"
@using Peachpie.Blazor
<!--Other Blazor content (optional)-->
<PhpScriptProvider Type="@PhpScriptProviderType.Script" ScriptName="index.php">
<Navigating>
<p>Navigating</p>
</Navigating>
<NotFound>
<p>Script not found</p>
</NotFound>
</PhpScriptProvider>
<!--Other Blazor content (optional)-->
Now, we add a new file named index.php
to PHPScripts
project and launch the server. We can access https://index.html, which is handled by Blazor, and Peachpie.Blazor
library executing the script and rendering its output as page content.
Navigating a set of PHP scripts#
When we want to navigate more PHP scripts, we just change the Type
parameter of PhpScriptProvider
to PhpScriptProviderType.Provider
. It enables to navigate PHP scripts based on matching the current URL with script paths.
So, when we want to navigate all scripts contained in the folder1
folder of PHPScripts
project, we just add the following Razor page to the BlazorApp.Client
project:
@page "/folder1/{*sth}"
@using Peachpie.Blazor
<PhpScriptProvider Type="@PhpScriptProviderType.Provider">
<Navigating>
<p>Navigating</p>
</Navigating>
<NotFound>
<p>Script not found</p>
</NotFound>
</PhpScriptProvider>
@code
{
[Parameter] public string sth { get; set; }
}
PHP Script router#
Navigating only PHP scripts is the last option that the library offers. We set the provider as a root component and change the Type
parameter to PhpScriptProviderType.Router
handling all navigation events. We can see an example below.
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Add PHP
builder.AddPhp(new[] { typeof(force).Assembly });
// Set the provider as a root component
builder.RootComponents.Add(typeof(PhpScriptProvider), "#app");
await builder.Build().RunAsync();
}
Make your Blazor component in PHP#
Because PeachPie enables inheriting C# classes in PHP. We implemented a PhpComponent
class representing the classic Blazor component adjusted to support PHP. It provides us full support of Blazor API though ComponentBase
interface. Because the Blazor API is not fully compatible with PHP language, the helper classes were implemented to help with that.
<?php
#[\Microsoft\AspNetCore\Components\RouteAttribute("/MyComponent")]
class MyComponent extends \Peachpie\Blazor\PhpComponent
{
private $infoTag;
public function BuildRenderTree($builder) : void
{
$this->infoTag->writeWithTreeBuilder($builder, 0);
}
public function OnInitialized() : void
{
parent::OnInitialized();
$this->infoTag = new \Peachpie\Blazor\Tag("p");
$this->infoTag->content[] = new \Peachpie\Blazor\Text("Hello world");
}
}
For those, whose are familiar with Blazor, the code above should be understandable. It is a common Blazor component implemented in the PHP language. There is a collection of helper classes like Tag
helping to render the page content. You can find a full reference API on https://docs.peachpie.io/scenarios/blazor/api-reference/ , which will tell you more about these helpers.
At first glance, this way of adding PHP to Blazor can be considered difficult to use, but it enables utilizing a smart diffing algorithm during rendering. Hence, we can also create render-demanding applications like games by using this way. There is an example of a simple Asteroids-like game, which is fully implemented by PHP and executed as a client-side application. We can see a screenshot from this game below.
Static files serving#
Blazor enables serving static files by saving them into wwwroot
folder in BlazorApp.Client
project. All files stored in the folder are accessible from PHP scripts as well.
For example, when an image
img.jpg
has pathwwwroot\img\img.jpg
. We can render this image in PHP scripts by the code below.
<?php
<img alt="img" src="img\img.jpg"/>
However, the static files only used by PHP scripts should be contained in the project as well due to make the project clear. Peachpie.Blazor
offers two options for how to reference these static files.
wwwroot linking#
The first option is to link a folder containing static files to the BlazorApp.Client
project. It can be done by adding the following code into .csproj. We assume having the folder wwwroot
containing the additional static files in PHPScripts
project.
BlazorApp.Client.csproj:
...
<ItemGroup>
<None Include="..\..\PHPScripts\wwwroot\**\*">
<Link>wwwroot\%(RecursiveDir)/%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
...
appsettings.json#
The second option is utilizing custom ASP.NET Core middleware provided by Peachpie.Blazor
. When you add the app.UseAdditionalWebStaticAssets
method into StartUp
class of server, you will be able to specify folder(s), which should be accessible from the client.
namespace BlazorApp.Server
{
public class Startup
{
public IConfiguration Configuration { get; }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
...
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseAdditionalWebStaticAssets(Configuration);
app.UseRouting();
...
}
}
}
The following configuration means serving files from ..\\..\\PHPScripts\\wwwroot
to the client. They have a root path _content\PHPScripts
.
So for example, when we have an image
img.jpg
placed inPHPScripts\wwwroot\img\img.jpg
, we display it by<img alt="img" src="_content\PHPScripts\img\img.jpg">
appsettings.json:
{
"AdditionalStaticWebAssets": [
{
"Path": "..\\..\\PHPScripts\\wwwroot",
"BasePath": "/PHPScripts"
}
]
}