跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Web 框架 DuckPHP 发布
未分類
23 6 月 2020

Web 框架 DuckPHP 发布

Web 框架 DuckPHP 发布

資深大佬 : dvaknheo 79

代码: 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,因为太拗口,所以改名了。这个名字应该可以吧。

大佬有話說 (17)

  • 資深大佬 : mokeyjay

    大致看完后有 3 点个人的想法:
    1、单字母函数 /方法很丑,仿佛回到了 N 年前的 ThinkPHP
    2、demo 中还出现了不遵守 PSR 规范的情况
    3、php 参杂 html ……你认真的?

  • 主 資深大佬 : dvaknheo

    因为要一个文件展示所有东西,所以用 php 参杂 html。 正常情况下是写在 view 文件夹里的。

    Model 中可以全 static 方法, 反正也不会改变。
    Service 中的 G 方法。 在 test/JsonRpcExtTest 里有个例子:

    TestService::G(JsonRpcExt::Wrap(TestService::class));

    $data=TestService::G()->foo();

    把本地调用,一下子变成远程调用。

    普通程序员用到的方面。
    Service 层必须要用 G 方法而不能用 静态方法的,只有
    SessionService 这个特殊的用于管理 Session 的 Service 了。

    核心程序员用一个 G 方法 替换掉默认的类,总比配置 超长东西容易记住。
    比如容器别名之类,你还得去找这个容器的别名是什么来替换。

    use ControllerHelper as C。这个单字母类, 是为了减少输入。

  • 資深大佬 : jfcherng

    命名風格太亂了

    protected $exceptionHandlers
    protected $default_exception_handler
    public function assignExceptionHandler
    public function on_error_handler
    public static function Hook
    public static function RunQuickly
    public function _Parameters
    trait Core_Handler
    trait HelperTrait

    我感覺所有能用的風格都用上了…

  • 主 資深大佬 : dvaknheo

    protected $exceptionHandlers // 内部变量,可 override
    protected $default_exception_handler // 内部变量,不建议 override。
    public function assignExceptionHandler // 对外动态方法
    public function on_error_handler // 不得不公开动态方法,不建议外部使用
    public static function Hook // 对外静态方法
    public static function RunQuickly // 对外静态方法
    public function _Parameters // 不得不公开静态方法,不建议外部使用
    trait Core_Handler // 下划线本文件内的功能分块。
    trait HelperTrait // Trait 后缀 表示是 Trait

  • 資深大佬 : agdhole

    有 minggeJS 内味了

  • 資深大佬 : hefish

    看了 demo,不想跟进。很讨厌单字母方法。 另外还分核心程序员,普通程序员,可能是为了展示可替代的特性,但觉着麻烦。

  • 資深大佬 : inclulu

    @agdhole 哈哈,还有人记得 minggeJS,一晃好多年了

  • 主 資深大佬 : dvaknheo

    鉴于单字母方法很令人讨厌。那么 template/public/demo2.php 就把单字母去掉了。
    核心程序员,普通程序员。 那就改为核心代码和业务代码吧。
    还有,因为有人懒得用设置服务器,我们也加了不用设置服务器就能看到结果的方法。
    分出的 四种 Helper 一个人写代码也没必要这么折腾,那就用 App 的静态方法够了。
    这样就只有两个地方用到 DuckPhp 命名空间了。
    我只改动了 demo,没去改 DuckPhp 的代码。

    “`php
    <?php declare(strict_types=1);
    /**
    * DuckPHP
    * From this time, you never be alone~
    */
    namespace {
    require_once(__DIR__.’/../../autoload.php’); // @DUCKPHP_HEADFILE
    //头文件可以自行修改。
    }

    // 以下部分是核心代码。
    namespace MySpaceBase
    {
    // 默认的 View 不支持函数调用,我们这里替换他。
    class App extends DuckPhpApp
    {
    protected function onInit()
    {
    // 本例特殊,这里演示函数调用的 扩展 CallableView 代替系统的 View
    $this->options[‘ext’][‘DuckPhpExtCallableView’] = [
    ‘callable_view_class’ => ‘MySpaceViewViews’,
    ];
    ////
    return parent::onInit();
    }
    }
    } // end namespace
    // 以下部分是业务代码
    namespace MySpaceController //控制器
    {
    use MySpaceBaseApp;
    use MySpaceServiceMyService;

    class Main
    {
    public function __construct()
    {
    App::setViewWrapper(‘header’, ‘footer’);//设置页眉页脚。
    }
    public function index() //主页
    {
    //获取数据
    $output = “Hello, now time is ” . App::H(MyService::getTimeDesc());
    $url_about = App::URL(‘about/me’);
    App::Show(get_defined_vars(), ‘main_view’); //显示数据
    }
    }
    class about
    {
    public function me() //about/me
    {
    $url_main = App::URL(”);
    App::setViewWrapper(‘header’, ‘footer’);
    App::Show(get_defined_vars());// 默认的 view 名称没了。
    }
    }
    } // end namespace
    namespace MySpaceService
    {
    use MySpaceBaseApp;
    use MySpaceModelMyModel;

    class MyService
    {
    public static function getTimeDesc()
    {
    return “<” . MyModel::getTimeDesc() . “>”;
    }
    }

    } // end namespace
    namespace MySpaceModel
    {
    use MySpaceBaseApp;

    class MyModel
    {
    public static 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
    // 以下部分是核心代码
    // 入口文件,默认在 public/index.php
    namespace
    {
    $options = [];
    $options[‘namespace’] = rtrim(‘MySpace\’, ‘\’); //项目命名空间为 MySpace, 你可以随意命名
    $options[‘is_debug’] = true; // 开启调试模式

    $options[‘skip_app_autoload’] = true; // 本例特殊,跳过 app 用的 autoload 免受干扰
    $options[‘skip_setting_file’] = true; // 本例特殊,跳过设置文件

    //没设置服务器,那就用 _r 作为路由吧
    $options[‘ext’][‘DuckPhpExtRouteHookOneFileMode’]=[
    ‘key_for_action’ => ‘_r’,
    ‘key_for_module’ => ”,
    ];

    DuckPhpApp::RunQuickly($options);
    } // end namespace
    “`

  • 資深大佬 : weirdo

    看到 github 页面里那个 和其他框架简单对比 的表格。。
    哈哈哈哈 ,主加油!

  • 資深大佬 : sadfQED2

    我觉得吧,现在 php 的框架没必要造了,足够多了,我们公司的底层框架开源六七年了,就 60 多个 star,还都是我们内部员工。(我们注册用户今年刚刚过亿,全是这套框架撑起来了)

  • 主 資深大佬 : dvaknheo

    @sadfQED2 求一下你们框架的地址。
    现在的国内 PHP7 可用框架并不多。也就只有 Laravel 和 TP 两个可选而已。

    Laravel 的厉害之处在于宣传。这也就是在代码之外的功夫。
    我现在碰到的也不是代码问题,虽然有些 todo 列表。
    文档是最大的问题,我对我写的文档没信心,总觉得写的不知道能看懂。
    如果有人问起,我能说有什么缺的。
    但目前就是缺乏反馈的状态。

  • 資深大佬 : yxzblue

    有点看不懂

  • 資深大佬 : sadfQED2

    @dvaknheo 在 github 上开源了,但是没写任何解释,没写任何 wiki,你不是我们公司的话,或许很难上手

  • 資深大佬 : ben1024

    加油 ing

  • 資深大佬 : sadfQED2

    @dvaknheo 地址 https://github.com/zhangchu/ko 真的太难找了,我翻了半天才翻出来

  • 主 資深大佬 : dvaknheo

    @sadfQED2 过了一下,成不了 CodeIgniter 那样的通用框架。 最别扭的是 方法名都加上了返回类型前缀,和 PHP 的能省则省相冲突。php 的命名空间 5.3 就出来了。如果刚开始没用命名空间还可以接受。

    不能替换默认组件。额外好些功能,有些功能甚至要设置数据库表结构才能用。可以拆分到其他项目。

    DuckPHP 提供的 Logger ,Pager 都是最小化的,如果有更好解决方案可以替换的,甚至 DB 类都可以替换(教程文档就有替换成 thinphp-orm 的。

    说起来我里面也有 facades 的扩展。 DuckPhpExtFacadesAutoLoader。 我宁愿用单字母静态方法而不愿用 facades 的一个原因就是 facades 的东西不好调试。

  • 資深大佬 : sadfQED2

    @dvaknheo 有些问题和我们历史遗留代码有关,业务代码迭代快 10 年了,框架不是随便能改的。而且公司自己的框架,只为自己公司项目考虑,没必要替换组件

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具