继续标题党哈。老习惯,自己吹过的牛就算含着泪也要实现,自从上次初步分析过 三步实现PHP低代码框架 后,其实这两个月也在团队内小范围试用一些产品,主要试用对象是 Erupt,基于 Java Spring Boot 构建的一款框架,从开发效率上看还是效果很明显的。低代码的低,强调的是要大幅减少代码,从这个角度对比市面上一些商业化产品来看,Erupt 还有很大提升空间,尤其没有整合工作流引擎,但是相比于市面上另外一派主打代码生成器的产品来说,体验已经好了太多太多。而且非常佩服作者的产品性思维能力,整合的东西扩展性非常强,使用这套框架实在是干活时的利器。
但是,作为个人业余爱好,要想快速实现一些概念原型,个人还是喜欢用 PHP。所以继续基于 PHP 语言做了一次探索,续上文内容。
这次偷懒,先引入了完整的 ThinkPHP 框架作为起步,前端使用百度的 AMIS ,做整合。100 行代码真的没有吹牛,但是整到这个程度只是开了个头,还不具备真正的实用价值。
这里想提醒自己的是,积木式或者模块化或者还原论的思维方式,有助于真正解决好问题,对应在商业角度的思考还要再深入些。
知识点
- amis 的 service 组件 https://baidu.gitee.io/amis/zh-CN/components/service,支持动态渲染页面;
- 引入一个前端 SPA 路由解析库;route-recognizer https://github.com/tildeio/route-recognizer ;
- thinkphp 的路由定义机制 http://static.kancloud.cn/manual/thinkphp6_0/1037499 ;
- amis 的 crud 组件 https://baidu.gitee.io/amis/zh-CN/components/crud ;
路由定义
route/app.php
-
- // 构建基于前端低代码框架下的UI自动生成接口
- Route::post('/lc/build/table/:modelName', 'UIBuilder/table');
- Route::get('/lc/data/table/:modelName', 'UIData/table');
控制器
app/controller/UIBuilderController.php
- <!--?php
-
- namespace app\controller;
-
- use app\BaseController;
- use app\fe\amis\Crud;
- use think\helper\Str;
-
- class UIBuilderController extends BaseController
- {
- public function table($modelName)
- {
- $modelClass = '\\app\\model\\' . ucfirst($modelName);
-
- $model = new $modelClass(); /** @var \think\Model $model */
- $fields = $model--->db()->getFields();
-
- $view = new Crud();
- $view->api = url('/lc/data/table/' . $modelName)->suffix(false)->build();
-
- // TODO 调整 DAO 层和 ViewModel 层分工,然后从 ViewModel 取相关数据
- $view->columns = [];
- foreach ($fields as $field) {
- $view->columns[] = [
- 'name' => $field['name'],
- 'label' => Str::title(str_replace('_', ' ', $field['name'])),
- ];
- }
-
- return $this->toJson(0, $view);
- }
-
- }
app/controller/UIDataController.php
- <!--?php
-
- namespace app\controller;
-
- use app\BaseController;
- use app\fe\amis\Crud;
- use think\helper\Str;
-
- class UIDataController extends BaseController
- {
- public function table($modelName)
- {
- $modelClass = '\\app\\model\\' . ucfirst($modelName);
-
- $model = new $modelClass(); /** @var \think\Model $model */
-
- // TODO 实现按条件查询及分页
- $rows = $model--->select();
-
- $totalCount = 2104;
-
- return $this->dataToJson($rows, $totalCount);
- }
-
- protected function dataToJson($rows, $totalCount)
- {
- return $this->toJson(0, [
- 'items' => $rows,
- 'total' => $totalCount,
- ]);
- }
- }
编写脚本自动生成 DB Model
前端入口
- <script type="text/javascript">
- (function () {
- var router = new RouteRecognizer();
- router.add([{
- path: "/table/:model/*pathVar",
- handler: function (args) {
- console.log('default handler', args)
- }
- }]);
-
- var hash = window.location.hash.split('#')[1];
-
- var result = router.recognize(hash);
- var defaultModel = 'Project';
- var currentModel = (result.length > 0) ? result[0].params.model : defaultModel;
- var schemaApi = "{:url('/lc/build/table/:model')->suffix(false)}".replace(/:\w+/g, function(model) {
- return currentModel;
- });
-
- let amis = amisRequire('amis/embed');
- // 通过替换下面这个配置来生成不同页面
- let amisJSON = {
- type: 'page',
- title: '数据管理',
- body: {
- type: 'service',
- schemaApi: schemaApi,
- },
- };
- let amisScoped = amis.embed('#root', amisJSON, {}, {
- theme: 'cxd'
- });
- })();
- </script>