介绍一个基于 .NET 的船新 PHP SDK + Runtime: PeachPie

前言

这几天想基于 .NET Core 搞一个自己的博客网站,于是在网上搜刮各种博客引擎,找到了这些候选:Blogifier、Miniblog 以及 edi 写的 Moonglade。

Blogifier:这是前端是个 Angular SPA 应用,不利于 SEO,同时首屏加载速度慢,因此排除。

Miniblog:顾名思义 Mini,可以完美承载内容但是主题实在是过于简单,没有可自定义性,因此排除。

Moonglade:总体感觉不错,界面设计得也很好,功能全面,然而需要 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 最新的项目模板:

dotnet new -i Peachpie.Templates::*

然后就会出现三个新的项目模板:Console Application、Class library 和 ASP.NET Core Empty。

我们这次整个 Console Application 看看。

dotnet new console -lang PHP

然后随便写点代码:

<?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 运行!

编译输出(请无视掉我的霓虹语电脑环境):

.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:\Users\hez20\source\repos\PeachPieConsole\bin\Debug\netcoreapp3.1\PeachPieConsole.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:12.98

Voila!

Debug

输出:

Joe Smith's score is 83
Frank Barbson's score is 92
Benji Warner's score is 90

如果去掉打错一个变量 $value 变成 $vuale 会怎么样呢?

<?php

function main()
{
    $students = 
        array(
            array("first_name" => "Joe","last_name" => "Warner")   
        );
    
    foreach ($students as $value) {
        echo $vuale["first_name"],"\n";
    }
}

main();

编译输出:

.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:\Users\hez20\source\repos\PeachPieConsole\PeachPieConsole.msbuildproj] 
  PeachPieConsole -> C:\Users\hez20\source\repos\PeachPieConsole\bin\Debug\netcoreapp3.1\PeachPieConsole.dll

ビルドに成功しました。

program.php(13,14): warning PHP5007: Undefined variable: $vuale [C:\Users\hez20\source\repos\PeachPieConsole\PeachPieConsole.msbuildproj] 
    1 個の警告
    0 エラー

経過時間 00:00:09.51

由于上述代码在 PHP 中是合法代码,因此为了保持兼容性,PeachPie 不会报错而是给了警告。

但如果我们少一个分号呢:

<?php

function main()
{
    $students = 
        array(
            array("first_name" => "Joe","last_name" => "Warner")   
        )
    
    foreach ($students as $value) {
        echo $value["first_name"],"\n";
    }
}

main();

编译输出:

.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:\Users\hez20\source\repos\PeachPieConsole\PeachPieConsole.msbuildproj]

ビルドに失敗しました。

program.php(12,5): error PHP2014: Syntax error: unexpected token 'foreach' [C:\Users\hez20\source\repos\PeachPieConsole\PeachPieConsole.msbuildproj]
    0 個の警告
    1 エラー

経過時間 00:00:01.77

这次就会直接报错了。

由此可见,使用 PeachPie 能够无需第三方工具辅助,直接在编译时就验证代码正确性,对项目的健壮性有很大帮助。

PHP 与 .NET 互操作

我们试试互操作,在 PHP 里面创建一个 .NET 中的 HashSet<TValue>

<?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();

输出:

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.AspNetCorehttps://github.com/iolevel/wpdotnet-sdk ),可直接作为 ASP.NET Core 中间件使用,非常方便。

那么事情就简单了:

dotnet new web
dotnet add package PeachPied.WordPress.AspNetCore --version 1.0.0-beta980

然后编写少量服务端代码,配置一下 https 跳转、响应压缩和静态文件什么的,再加入 WordPress 中间件:

Startup.cs

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 部分可以没有):

{
  "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!

dotnet publish -c Release

最后打包 bin/Release/netcoreapp3.1/publish 上传到服务器上面,搭建好数据库然后运行即可。

完结撒花

进入管理面板,大多数主题、插件都能正常工作,安装点主题,配置配置插件和 SMTP,就全部搞定啦。

Admin

内存占用 195 MB,运行在 .NET Core 3.1.3 上,非常清真!

至此我的 Blog 搭建完成,欢迎大家访问:https://hez2010.com

评论和注册什么的也开放了,欢迎大家常光临~

后续我也会不断在上面更新文章,当然,这个 Blog 上面的内容也就不仅限于编程啦,敬请期待~

Blog

从此 PHP 也是 .NET 上的一门语言了,完结撒花~

原文地址:https://www.cnblogs.com/hez2010

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发、订阅和处理的流程。这种实现太简单了,百十行代码就展示了一个基本工作原理。然而,要将这样的解决方案运用到实际生产环境,还有很长的路要走。今天,我们就研究一下在事件处理器中,对象生命周期的管理问题。事实上,不仅仅是在事件处理器
上文已经介绍了Identity Service的实现过程。今天我们继续,实现一个简单的Weather API和一个基于Ocelot的API网关。 回顾 《Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)》 Weather API Weather
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是为了让大家更为方便地学习和使用.NET Core、最新的前端开发框架Angular,以及Apwork
HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务端接口的耦合度。很多当今流行的RESTful API开发框架,包括Spring REST,也都默认支
在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅、通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现。接下来对于事件驱动型架构的讨论,就需要结合一个实际的架构案例来进行分析。在领域驱动设计的讨论范畴,CQRS架构本身就是事件驱动的,因此,
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了。领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architecture Pattern),它也不是一种软件开发方法论,所以,是否应该使用领域驱动设计,以及什么时候使用
《在ASP.NET Core中使用Apworks快速开发数据服务》一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介绍,你会看到,使用Apworks框架开发数据服务是何等简单快捷,提供的功能也非常多,比如对Hypermedia的
在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证。在本讲中,我们会讨论在当前这种架构的应用程序中,如何完成用户授权。 回顾 《Angular SPA基于
Keycloak是一个功能强大的开源身份和访问管理系统,提供了一整套解决方案,包括用户认证、单点登录(SSO)、身份联合、用户注册、用户管理、角色映射、多因素认证和访问控制等。它广泛应用于企业和云服务,可以简化和统一不同应用程序和服务的安全管理,支持自托管或云部署,适用于需要安全、灵活且易于扩展的用
3月7日,微软发布了Visual Studio 2017 RTM,与之一起发布的还有.NET Core Runtime 1.1.0以及.NET Core SDK 1.0.0,尽管这些并不是最新版,但也已经从preview版本升级到了正式版。所以,在安装Visual Studio 2017时如果启用了
在上文中,我介绍了如何在Ocelot中使用自定义的中间件来修改下游服务的response body。今天,我们再扩展一下设计,让我们自己设计的中间件变得更为通用,使其能够应用在不同的Route上。比如,我们可以设计一个通用的替换response body的中间件,然后将其应用在多个Route上。 O
不少关注我博客的朋友都知道我在2009年左右开发过一个名为Apworks的企业级应用程序开发框架,旨在为分布式企业系统软件开发提供面向领域驱动(DDD)的框架级别的解决方案,并对多种系统架构风格提供支持。这个框架的开发和维护我坚持了很久,一直到2015年,我都一直在不停地重构这个项目。目前这个项目在
好吧,这个题目我也想了很久,不知道如何用最简单的几个字来概括这篇文章,原本打算取名《Angular单页面应用基于Ocelot API网关与IdentityServer4ʺSP.NET Identity实现身份认证与授权》,然而如你所见,这样的名字实在是太长了。所以,我不得不缩写“单页面应用”几个字
在前面两篇文章中,我介绍了基于IdentityServer4的一个Identity Service的实现,并且实现了一个Weather API和基于Ocelot的API网关,然后实现了通过Ocelot API网关整合Identity Service做身份认证的API请求。今天,我们进入前端开发,设计
Ocelot是ASP.NET Core下的API网关的一种实现,在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot,而是介绍一下最近在学习过程中遇到的一个问题,以及如何使用中间件(Middleware)来解决这样的问题。 问题描述 在上文中,我介绍了一种在Angu
在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台。市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计算平台Azure,为大数据处理提供了强大的计算能力,让大数据处理变得更为稳定高效。由于工作中我的项目
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容。下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了。其中绿色的部分就是上文中新实现的部分,包括一个简单的Event Store,一个事件处理器执行上下文的接
在之前《在ASP.NET Core中使用Apworks快速开发数据服务》一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语法解析提供支持。在此非常感激友哥给我的建议,也让我了解了一些Roslyn的知识。使用Roslyn的一个很大的好处
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构。这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地订阅来自于某个渠道的事件消息,并对接收到的消息进行处理,于此同时,它还能够向该渠道发送事件消息,以便