代码: 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 MySpace\Base
{
use \DuckPhp\Core\View;
use \DuckPhp\Ext\CallableView;
// 默认的 View 不支持函数调用,我们这里替换他。
class App extends \DuckPhp\App
{
protected function onInit()
{
// 本例特殊,这里演示函数调用的 CallableView 代替系统的 View
$this->options['callable_view_class'] = 'MySpace\View\Views';
View::G(CallableView::G());
////
return parent::onInit();
}
}
//服务基类, 为了 XXService::G() 可变单例。
class BaseService
{
use \DuckPhp\SingletonEx;
}
// 模型基类, 为了 XXModel::G() 可变单例。
class BaseModel
{
use \DuckPhp\SingletonEx;
}
} // end namespace
// 助手类
namespace MySpace\Base\Helper
{
class ControllerHelper extends \DuckPhp\Helper\ControllerHelper
{
// 一般不需要添加东西,继承就够了
}
class ServiceHelper extends \DuckPhp\Helper\ServiceHelper
{
// 一般不需要添加东西,继承就够了
}
class ModelHelper extends \DuckPhp\Helper\ModelHelper
{
// 一般不需要添加东西,继承就够了
}
class ViewHelper extends \DuckPhp\Helper\ViewHelper
{
// 一般不需要添加东西,继承就够了
}
} // end namespace
// 以下部分是普通程序员写的。不再和 DuckPhp 的类有任何关系。
namespace MySpace\Controller {
use MySpace\Base\Helper\ControllerHelper as C;
use MySpace\Service\MyService;
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 MySpace\Service
{
use MySpace\Base\Helper\ServiceHelper as S;
use MySpace\Base\BaseService;
use MySpace\Model\MyModel;
class MyService extends BaseService
{
public function getTimeDesc()
{
return "<" . MyModel::G()->getTimeDesc() . ">";
}
}
} // end namespace
namespace MySpace\Model
{
use MySpace\Base\Helper\ModelHelper as M;
use MySpace\Base\BaseModel;
class MyModel extends BaseModel
{
public function getTimeDesc()
{
return date(DATE_ATOM);
}
}
}
// 把 PHP 代码去掉看,这是可预览的 HTML 结构
namespace MySpace\View {
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; // 本例特殊,跳过设置文件
\DuckPhp\App::RunQuickly($options, function () {
});
} // end namespace
DuckPHP 的前身是 DNMVCS,因为太拗口,所以改名了。这个名字应该可以吧。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.