介紹一個基於 .NET 的船新 PHP SDK + Runtime: PeachPie

介紹一個基於 .NET 的船新 PHP SDK + Runtime: PeachPie

前言#
這幾天想基於 .NET Core 搞一個自己的博客網站,於是在網上搜刮各種博客引擎,找到了這些候選:Blogifier、Miniblog 以及 edi 寫的 Moonglate。

Blogifier:這是前端是個 Angular SPA 應用,不利於 SEO,同時首屏加載速度慢,因此排除。

Miniblog:顧名思義 Mini,可以完美承載內容但是主題實在是過於簡單,沒有可自定義性,因此排除。

Moonglate:總體感覺不錯,界面設計得也很好,功能全面,然而需要 SQL Server 作爲數據庫,然而 SQL Server 雖然有 Linux 版本,但受限於主機配置和預算因此也被排除。

難道就沒有適合我需求的博客引擎了嗎?答案當然是:有。

衆所周知 PHP 是世界上最好的語言(滑稽),還是衆所周知有一個叫做 WordPress 的博客引擎生態非常龐大,而且是使用 PHP 構建的。

可是 PHP 和 .NET 又有什麼關係呢?

PeachPie#
PeachPie 是一個完全構建於 .NET Standard 之上的一套完整的 PHP SDK + Runtime,包含編譯器和運行時等等,兼容 PHP 5.4-7.4(當然部分功能仍在開發中)。

官網:https://www.peachpie.io

那麼 PeachPie 有什麼優點呢:

開源:https://github.com/peachpiecompiler/peachpie
跨平臺:因爲 PeachPie 完全構建於 .NET 之上,因此也就跟着跨平臺了,Windows、MacOS、Linux 等等,從架構上跨 x86、x86_64、ARM、ARM64,未來甚至還會有 MIPS、MIPS64、Risc-V 等等......
純託管代碼:藉助 VS 強大的調試器和 IDE 體驗,從開發、調試到測試、Profile 一條龍非常爽
編譯:PHP 是沒有編譯之說的,這門動態類型語言和 Python 面臨一樣的問題,幾乎無法在編譯時發現代碼中的錯誤,即便藉助 linter 診斷出了語法錯誤也很難診斷出類型的錯誤。而 PeachPie 則有完善的編譯器套件將 PHP 代碼完整的編譯爲 .NET Standard 程序集,意味着在編譯期就做好了語法和類型檢查,保證了運行時不會因爲代碼問題導致程序崩潰,同時應用分發的時候也不需要源代碼,確保了源碼安全
與 .NET 互操作:PeachPie 在保留了 PHP 原本的生態基礎上做到了 PHP 和 .NET 的互操作,一個 PeachPie 項目不但可以使用 PHP 原有生態中的包和插件,還能享受 .NET 的生態,快樂超級加倍
運行在 .NET 上:CLR/CoreCLR 自帶久經考驗的 JIT 和 GC,因此通過 PeachPie 編譯的程序集運行在 CLR/CoreCLR 之上則無需做任何的代碼改動即可享受到這些東西,在 php-bench 中,藉助 CoreCLR 平臺的 JIT,函數調用性能拉開了原來 PHP 幾個數量級
.NET Foundation 項目:背後有 .NET Foundation 支持,瓦利亞高品質,有保證
可是有人就要問了,爲什麼我不直接用 PHP 而是選用 PeachPie 曲線救國呢?

因爲我樂意,雨女無瓜(逃

開始使用#
本文開發環境採用 Visual Studio Code(需要安裝 PeachPie 插件),當然你也可以用 Visual Studio 等其他開發工具。

安裝 PeachPie 最新的項目模板:

Copy
dotnet new -i Peachpie.Templates::*
然後就會出現三個新的項目模板:Console Application、Class library 和 ASP.NET Core Empty。

我們這次整個 Console Application 看看。

Copy
dotnet new console -lang PHP
然後隨便寫點代碼:

Copy
<?php

function main()
{

$students = 
    array(
        array("first_name" => "Joe", "score" => 83, "last_name" => "Smith"),
        array("first_name" => "Frank", "score" => 92, "last_name" => "Barbson"),
        array("first_name" => "Benji", "score" => 90, "last_name" => "Warner")   
    );

foreach ($students as $value) {
    echo $value["first_name"], " ", $value["last_name"], "'s score is ", $value["score"], "\n";
}

}

main();
用配置 .NET Core 項目的方式寫好 Visual Studio Code 需要的 tasks.json 和 launch.json,隨便下點斷點然後編譯 + F5 運行!

編譯輸出(請無視掉我的霓虹語電腦環境):

Copy
.NET Core 向け Microsoft (R) Build Engine バージョン 16.7.0-preview-20220-01+80e487bff
Copyright (C) Microsoft Corporation.All rights reserved.

復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
プレビュー版の .NET Core を使用しています。https://aka.ms/dotnet-core-preview をご覧ください
PeachPie PHP Compiler version 0.9.981+565af85b9aafc42fe1af2f30ccd73ff093a2fad7
PeachPieConsole -> C:Usershez20sourcereposPeachPieConsolebinDebugnetcoreapp3.1PeachPieConsole.dll

ビルドに成功しました。

0 個の警告
0 エラー

経過時間 00:00:12.98
Voila!

輸出:

Copy
Joe Smith's score is 83
Frank Barbson's score is 92
Benji Warner's score is 90
如果去掉打錯一個變量 $value 變成 $vuale 會怎麼樣呢?

Copy
<?php

function main()
{

$students = 
    array(
        array("first_name" => "Joe", "score" => 83, "last_name" => "Smith"),
        array("first_name" => "Frank", "score" => 92, "last_name" => "Barbson"),
        array("first_name" => "Benji", "score" => 90, "last_name" => "Warner")   
    );

foreach ($students as $value) {
    echo $vuale["first_name"], " ", $value["last_name"], "'s score is ", $value["score"], "\n";
}

}

main();
編譯輸出:

Copy
.NET Core 向け Microsoft (R) Build Engine バージョン 16.7.0-preview-20220-01+80e487bff
Copyright (C) Microsoft Corporation.All rights reserved.

復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
プレビュー版の .NET Core を使用しています。https://aka.ms/dotnet-core-preview をご覧ください
PeachPie PHP Compiler version 0.9.981+565af85b9aafc42fe1af2f30ccd73ff093a2fad7
program.php(13,14): warning PHP5007: Undefined variable: $vuale [C:Usershez20sourcereposPeachPieConsolePeachPieConsole.msbuildproj]
PeachPieConsole -> C:Usershez20sourcereposPeachPieConsolebinDebugnetcoreapp3.1PeachPieConsole.dll

ビルドに成功しました。

program.php(13,14): warning PHP5007: Undefined variable: $vuale [C:Usershez20sourcereposPeachPieConsolePeachPieConsole.msbuildproj]

1 個の警告
0 エラー

経過時間 00:00:09.51
由於上述代碼在 PHP 中是合法代碼,因此爲了保持兼容性,PeachPie 不會報錯而是給了警告。

但如果我們少一個分號呢:

Copy
<?php

function main()
{

$students = 
    array(
        array("first_name" => "Joe", "score" => 83, "last_name" => "Smith"),
        array("first_name" => "Frank", "score" => 92, "last_name" => "Barbson"),
        array("first_name" => "Benji", "score" => 90, "last_name" => "Warner")   
    )

foreach ($students as $value) {
    echo $value["first_name"], " ", $value["last_name"], "'s score is ", $value["score"], "\n";
}

}

main();
編譯輸出:

Copy
.NET Core 向け Microsoft (R) Build Engine バージョン 16.7.0-preview-20220-01+80e487bff
Copyright (C) Microsoft Corporation.All rights reserved.

復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
プレビュー版の .NET Core を使用しています。https://aka.ms/dotnet-core-preview をご覧ください
PeachPie PHP Compiler version 0.9.981+565af85b9aafc42fe1af2f30ccd73ff093a2fad7
program.php(12,5): error PHP2014: Syntax error: unexpected token 'foreach' [C:Usershez20sourcereposPeachPieConsolePeachPieConsole.msbuildproj]

ビルドに失敗しました。

program.php(12,5): error PHP2014: Syntax error: unexpected token 'foreach' [C:Usershez20sourcereposPeachPieConsolePeachPieConsole.msbuildproj]

0 個の警告
1 エラー

経過時間 00:00:01.77
這次就會直接報錯了。

由此可見,使用 PeachPie 能夠無需第三方工具輔助,直接在編譯時就驗證代碼正確性,對項目的健壯性有很大幫助。

PHP 與 .NET 互操作#
我們試試互操作,在 PHP 裏面創建一個 .NET 中的 HashSet:

Copy
<?php

function main()
{

$list = new System\Collections\Generic\HashSet<string>;
$list->Add("test");
$list->Add("hello");
$list->Add("hello");
$list->Add("lol");
foreach ($list as $key => $value) {
    echo $key, ": ", $value, "\n";
}

}

main();
輸出:

Copy
0: test
1: hello
2: lol
完美,另外,鑑於 PHP 代碼最後都會被編譯成 .NET Standard 程序集,因此反過來當然也沒問題,就不做介紹了。

一些坑#
當然,PeachPie 現在還處於比較早期階段,儘管大多數 PHP 代碼都能正常運行,但是標準庫仍存在一些兼容性問題,具體可以去這裏跟蹤:https://docs.peachpie.io/compatibility-status 。

也正是因爲還是處於早期狀態,所以很多優化工作(比如數組的優化)都沒有做,性能方面還有很大的提升空間。

不過官方目前開發進度十分快,因此短時間內就能看到大量的新庫函數被實現,到目前已經是 0.9.800,1.0 正式版也快要發佈了,很快就能正式投入生產使用啦。

Blog 搭建#
回到前面的主題,有了 PeachPie,我就能把 WordPress 放到 .NET Core 上面跑啦。

當然,直接下載下來 WordPress 的源代碼編譯跑到 ASP.NET Core 上面時會出現一些問題,比如資源加載全部 404,這是因爲 PeachPie 在編譯 PHP 代碼時默認不會將非 .php 的文件包含到編譯過程中,我們需要修改 .msbuildproj 調整項目屬性將資源文件包含在編譯過程中,並作爲 Content 引入。

另外由於 WordPress 首次配置會現場生成一個 config.php 文件,但是由於該文件是編譯後的程序集在運行時生成的,未參與編譯過程,因此運行時是找不到這個類的,除非重新編譯一遍。因此我們想採用更清真的方式,直接在 appsettings.json 裏面寫入配置然後運行時讀入代替原來的 config.php。

總之需要經過一系列操作,並且編寫少量代碼。不過,PeachPie 已經幫我們做好了這一切:iolevel 提供了一個即插即用的 WordPress 包 PeachPied.WordPress.AspNetCore(https://github.com/iolevel/wpdotnet-sdk ),可直接作爲 ASP.NET Core 中間件使用,非常方便。

那麼事情就簡單了:

Copy
dotnet new web
dotnet add package PeachPied.WordPress.AspNetCore --version 1.0.0-*
然後編寫少量服務端代碼,配置一下 https 跳轉、響應壓縮和靜態文件什麼的,再加入 WordPress 中間件:

Startup.cs

Copy
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace KeBlogs
{

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression(options =>
        {
            options.Providers.Add<BrotliCompressionProvider>();
            options.Providers.Add<GzipCompressionProvider>();
            options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] {
                "image/svg+xml",
                "image/png",
                "font/woff",
                "font/woff2",
                "font/ttf",
                "font/eof",
                "image/x-icon",
                "application/json",
                "application/octet-stream" });
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseHttpsRedirection();
        app.UseResponseCompression();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseDefaultFiles();
        app.UseStaticFiles();

        app.UseWordPress();
    }
}

}
代碼部分搞定,當然上述代碼你也可以用 PHP 來寫。

然後在 appsettings.json 寫入自己的配置,比如(SALT 部分可以沒有):

Copy
{
"WordPress": {

"dbhost":        "localhost",
"dbpassword":    "password",
"dbuser":        "root",
"dbname":        "wordpress",
"dbTablePrefix": "wp_",
"SALT": {
  "AUTH_KEY":         "r(EoMbKEvlg){+!T42fh-e+~IGj-4q}g8HHB9hjbiC0J*ySU1Y*3z[3c}F;6=TA5",
  "AUTH_SALT":        "q0#AzvJ*[4~Bexa9*M(sC_#pDuGQBdjL1}j*RilSe0ku]P~KuTir[7PxjE:4)_zR",
  "LOGGED_IN_KEY":    "!AAienFSridCUzF(v}m#}_;+t%Rclg;mOPKwe;w7dN0M{d,]?8V+TRW_UG)tSswa",
  "LOGGED_IN_SALT":   "C=(4(8WPMeRu_h?g7!ddI*P:+SYU=3C%g)92oV}-y5tE0r?DHWl!fjPOp=bjx2YJ",
  "NONCE_KEY":        "Z[e37@=y)m.CHa:OSldh#RT@nIZxKYGwu!/hd:vK#^{_Ec7e{KNb(G.8ch/MkH(d",
  "NONCE_SALT":       ";v7Wv/BV)Pz{W,FaAKC0buH*5U4:g]qn~;b94x]f8=lm6!yyYSbW5*2y*kRXXEF5",
  "SECURE_AUTH_KEY":  "pc}_Pv52,m=j9l#llSkLVQib.Zm!;9FRzg:{(G]tM8}[}]pPDwB4k{xV+!e)9lmR",
  "SECURE_AUTH_SALT": "#n]+o^w/%-~MVzf{AUuxUAwF[n03r{kr^r1V?wqQ?Vjt}!0HSkCB-):u-ra1%tB="
},
"constants": {
}

}
}
然後發佈我們的 WordPress!

Copy
dotnet publish -c Release
最後打包 bin/Release/netcoreapp3.1/publish 上傳到服務器上面,搭建好數據庫然後運行即可。

完結撒花#
進入管理面板,大多數主題、插件都能正常工作,安裝點主題,配置配置插件和 SMTP,就全部搞定啦。

內存佔用 195 MB,運行在 .NET Core 3.1.3 上,非常清真!

至此我的 Blog 搭建完成,歡迎大家訪問:https://hez2010.com 。

評論和註冊什麼的也開放了,歡迎大家常光臨~

後續我也會不斷在上面更新文章,當然,這個 Blog 上面的內容也就不僅限於編程啦,敬請期待~

完結撒花~

作者: hez2010

出處:https://www.cnblogs.com/hez2010/p/12878619.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章