Web 框架 DuckPHP 发布
代码: https://github.com/dvaknheo/duckphp 作者 QQ: 85811616 官方 QQ 群: 714610448
安装
composer require dvaknheo/duckphp # 用 require ./vendor/bin/duckphp --help # 查看有什么指令 ./vendor/bin/duckphp --create # --full # 创建工程
为什么叫 DuckPHP ? 取名鸭子类型的典故。 动态语言中经常提到鸭子类型,所谓鸭子类型就是:如果走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子( If it walks like a duck and quacks like a duck, it must be a duck )。鸭子类型是编程语言中动态类型语言中的一种设计风格,一个对象的特征不是由父类决定,而是通过对象的方法决定的。
Web 框架这么多,为什么要用你的框架。 首先,DuckPHP 所有组件都可以替换,这是现代 PHP 框架必备的品质, 出现什么安全问题,替换官方组件就可以。不必等着 composer update。
其次,DuckPHP 本着普通程序员和核心程序员两个层级的使用观点,普通程序员根本不会触及到 DuckPHP 的代码,只要简单的教学就能使用。 核心程序员,可以由浅及深扩展甚至魔改框架。
这也涉及到另一个特点,DuckPHP 更自由开放, 不会让你的 工程代码限制于 App 或 app 命名空间。 你写的 DuckPHP 工程 可以作为 插件用于其他 DuckPHP 工程( 旧框架没这个功能。
DuckPHP 支持 composer,但无引用第三方组件。无引用第三方组件对系统的可靠性很重要。比如某框架用了第三方旧组件,或许会引发安全问题不可控。
DuckPHP 的适应性也是很强的,不像某些框架,只能用于全站。DuckPHP 可以在网站子目录里使用,如果不支持 path_info,也可以调整。 一般的框架的配合是很难处理的。 但是 DuckPHP 很容易插入其他框架里提前使用,你也很容易在 DuckPhp 不处理的时候接其他框架。
DuckPHP 的代码层次分明, 用主类把其他所有独立类连在一起。你很容易可以写 DuckPHP 的扩展。你可以很容易读懂。template 目录,附带了好些 demo,但文档还没跟上。 工程方面,做了 phpunit 全覆盖测试。 用了 psr-2 的标准格式化代码。希望有一小撮人能搞起来, 杜绝我现在这种闭门造车的情况。
末了,贴一份完全 demo 源文件在 template/public/demo.php
<?php declare(strict_types=1); /** * DuckPHP * From this time, you never be alone~ */ namespace { require_once(__DIR__.'/../../autoload.php'); // @DUCKPHP_HEADFILE //头文件可以自行修改。 } // 以下部分是核心程序员写。 namespace MySpaceBase { use DuckPhpCoreView; use DuckPhpExtCallableView; // 默认的 View 不支持函数调用,我们这里替换他。 class App extends DuckPhpApp { protected function onInit() { // 本例特殊,这里演示函数调用的 CallableView 代替系统的 View $this->options['callable_view_class'] = 'MySpaceViewViews'; View::G(CallableView::G()); //// return parent::onInit(); } } //服务基类, 为了 XXService::G() 可变单例。 class BaseService { use DuckPhpSingletonEx; } // 模型基类, 为了 XXModel::G() 可变单例。 class BaseModel { use DuckPhpSingletonEx; } } // end namespace // 助手类 namespace MySpaceBaseHelper { class ControllerHelper extends DuckPhpHelperControllerHelper { // 一般不需要添加东西,继承就够了 } class ServiceHelper extends DuckPhpHelperServiceHelper { // 一般不需要添加东西,继承就够了 } class ModelHelper extends DuckPhpHelperModelHelper { // 一般不需要添加东西,继承就够了 } class ViewHelper extends DuckPhpHelperViewHelper { // 一般不需要添加东西,继承就够了 } } // end namespace // 以下部分是普通程序员写的。不再和 DuckPhp 的类有任何关系。 namespace MySpaceController { use MySpaceBaseHelperControllerHelper as C; use MySpaceServiceMyService; class Main { public function __construct() { //设置页眉页脚。 C::setViewWrapper('header', 'footer'); } public function index() { //获取数据 $output = "Hello, now time is " . C::H(MyService::G()->getTimeDesc()); $url_about = C::URL('about/me'); C::Show(get_defined_vars(), 'main_view'); //显示数据 } } class about { public function me() { $url_main = C::URL(''); C::setViewWrapper('header', 'footer'); C::Show(get_defined_vars()); } } } // end namespace namespace MySpaceService { use MySpaceBaseHelperServiceHelper as S; use MySpaceBaseBaseService; use MySpaceModelMyModel; class MyService extends BaseService { public function getTimeDesc() { return "<" . MyModel::G()->getTimeDesc() . ">"; } } } // end namespace namespace MySpaceModel { use MySpaceBaseHelperModelHelper as M; use MySpaceBaseBaseModel; class MyModel extends BaseModel { public function getTimeDesc() { return date(DATE_ATOM); } } } // 把 PHP 代码去掉看,这是可预览的 HTML 结构 namespace MySpaceView { class Views { public function header($data) { extract($data); ?> <html> <head> </head> <body> <header style="border:1px gray solid;">I am Header</header> <?php } public function main_view($data) { extract($data); ?> <h1><?=$output?></h1> <a href="<?=$url_about?>">go to "about/me"</a> <?php } public function about_me($data) { extract($data); ?> <h1> OK, go back.</h1> <a href="<?=$url_main?>">back</a> <?php } public function footer($data) { ?> <footer style="border:1px gray solid;">I am footer</footer> </body> </html> <?php } } } // end namespace // 以下部分是核心程序员写。 // 这里是入口,单一文件下要等前面类声明 namespace { $options = []; $options['namespace'] = rtrim('MySpace\', '\'); //项目命名空间为 MySpace, 你可以随意命名 $options['is_debug'] = true; // 开启调试模式 $options['skip_app_autoload'] = true; // 本例特殊,跳过 app 用的 autoload 免受干扰 $options['skip_setting_file'] = true; // 本例特殊,跳过设置文件 DuckPhpApp::RunQuickly($options, function () { }); } // end namespace
DuckPHP 的前身是 DNMVCS,因为太拗口,所以改名了。这个名字应该可以吧。