代碼自動生成工具(Alpaca-Builder)目的用來快速的編寫代碼,減小一些重複的工做。使用Alpaca-Laravel框架開發項目時,能夠利用代碼生成工具,快速的生成代碼,減小工做時間,提升工做效率。javascript
Alpaca-Spa-Laravel 是 先後端分離 開發的一個後臺管理系統的DEMO。Laravel用來實現後端功能,Alpaca-Spa用來實現前端功能,先後端之間經過Json交換數據。php
詳情請閱讀《Alpaca-Laravel 框架(一) --- 概述,先後分離的後臺管理系統》。css
Alpaca-Builder使用靈活的模版格式來配置代碼生成文件,若是現有的代碼模版不能知足需求,只須要修改代碼模版,或者新增代碼模版便可。html
主要功能是根據輸入的數據庫表名聲生成一下內容:前端
1 生成後端實體類 2 生成後端控制器 3 生成後端路由 4 生成前端JS控制器 5 生成前端編輯頁面 6 生成前端列表頁面 7 生成配置接口url 8 選擇是否複製到對應頁面
訪問方式,瀏覽器中輸入地址:你的域名\builderjava
(注意: 只有當配置文件中APP_ENV=local時,才允許訪問)git
你固然直接使用Laravel的視圖模板, 在這裏,咱們編寫一個簡單的視圖模版引擎,github
主要的功能能,讀取指定模版文件,將數據渲染到模版指定位置。數據庫
代碼以下:bootstrap
<?php namespace Builder\View; /** * View - 視圖模板 * @author Chengcheng * @date 2017-2-27 15:50:00 */ class View { //單例 private static $instance = null; //數據 private $data; //模板 private $template; //佈局模板 public $layout = null; /** * 建立視圖 * @author Chengcheng * @param string $template 視圖模板名字 * @param array $data 視圖數據 * @date 2016年11月5日 14:47:40 * @return static */ public static function tbl($template, $data = null) { //實例化新的對象 $newTpl = new static; //設置視圖 $newTpl->template = __DIR__ . '/Template/' . $template . ".php"; //數據 $newTpl->data = $data; //layout $newTpl->layout = static::layoutTpl(); //返回 return $newTpl; } /** * 建立layout視圖 * @author Chengcheng * @param string $template 視圖模板名字 * @param array $data 視圖數據 * @date 2016年11月5日 14:47:40 * @return static */ public static function layoutTpl($template = 'layout', $data = null) { //實例化新的對象 $newTpl = new static; //設置視圖 $newTpl->template = __DIR__ . '/Template/' . $template . ".php"; //數據 $newTpl->data = $data; //返回 return $newTpl; } /** * 建立視圖 * @author Chengcheng * @param null $data * @return null|string * @throws \Exception */ public function html($data = null) { //加載本身的模板 if (!empty($this->data)) { foreach ($this->data as $key => $value) { $this->$key = $value; } } //參數中的數據 if (!empty($data)) { foreach ($data as $key => $value) { $this->$key = $value; } } //讀取模板中的信息 $html = null; try { ob_start(); require $this->template; $html = ob_get_clean(); } catch (\Exception $ex) { ob_end_clean(); throw $ex; } //加載layout的模板 if ($this->layout) { $html = $this->layout->html(['content' => $html]); } //返回信息 return $html; } }
編寫一個交互頁面,用來接受用戶輸入的數據庫表名,生成的內容等。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0"> <title>Alpaca - Builder</title> <link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css"> <link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/??sm.min.css,sm-extend.min.css"> <script type='text/javascript' src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script> <script type='text/javascript' src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script> <script type='text/javascript' src='//g.alicdn.com/msui/sm/0.6.2/js/??sm.min.js,sm-extend.min.js' charset='utf-8'></script> <style> .line-right { text-align: right; } </style> </head> <body ontouchstart> <div class="page-group"> <div class="page page-current"> <!-- 你的html代碼 --> <header class="bar bar-nav"> <a class="button button-link button-nav pull-left" href="" data-transition='slide-out'> <span class="icon icon-left"></span> 返回 </a> <h1 class="title">Alpaca-Builder</h1> </header> <nav class="bar bar-tab"> <a class="tab-item active" href="#"> <span class="icon icon-home"></span> <span class="tab-label">首頁</span> </a> <a class="tab-item" href="#"> <span class="icon icon-me"></span> <span class="tab-label">我</span> </a> <a class="tab-item" href="#"> <span class="icon icon-settings"></span> <span class="tab-label">設置</span> </a> </nav> <div class="content"> <form action="/builder/create/builder" id="sub-form"> <div class="content-block-title">配置</div> <div class="list-block"> <ul> <!-- Text inputs --> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-name"></i></div> <div class="item-inner"> <div class="item-title label">數據表名稱</div> <div class="item-input"> <input type="text" placeholder="請輸入數據表名稱" name="table_name"> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-email"></i></div> <div class="item-inner"> <div class="item-title label">表名前綴</div> <div class="item-input"> <input type="text" placeholder="E-mail" value="tb_" name="table_prefix"> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-email"></i></div> <div class="item-inner"> <div class="item-title label">中文名稱</div> <div class="item-input"> <input type="text" placeholder="中文名稱" value="" name="table_name_cn"> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-email"></i></div> <div class="item-inner"> <div class="item-title label">二級模塊</div> <div class="item-input"> <input type="text" placeholder="二級模塊" value="" name="sub_module_name"> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-email"></i></div> <div class="item-inner"> <div class="item-title label">後端模塊</div> <div class="item-input"> <input type="text" placeholder="後端模塊" value="manage" name="b_module_name"> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-email"></i></div> <div class="item-inner"> <div class="item-title label">前端模塊</div> <div class="item-input"> <input type="text" placeholder="前端模塊" value="admin" name="f_module_name"> </div> </div> </div> </li> </ul> </div> <div class="content-block-title">後端</div> <div class="list-block"> <ul> <!-- Switch (Checkbox) --> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">生成Model</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_model"> <div class="checkbox"></div> </label> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">生成Controller</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_b_controller"> <div class="checkbox"></div> </label> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">配置Router</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_b_router"> <div class="checkbox"></div> </label> </div> </div> </div> </li> </ul> </div> <div class="content-block-title">前端</div> <div class="list-block"> <ul> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">List頁面</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_list"> <div class="checkbox"></div> </label> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">Edit頁面</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_edit"> <div class="checkbox"></div> </label> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">前端Controller</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_f_controller"> <div class="checkbox"></div> </label> </div> </div> </div> </li> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">配置接口url</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_init_inter"> <div class="checkbox"></div> </label> </div> </div> </div> </li> </ul> </div> <div class="content-block-title">自動複製到對應目錄</div> <div class="list-block"> <ul> <li> <div class="item-content"> <div class="item-media"><i class="icon icon-form-toggle"></i></div> <div class="item-inner"> <div class="item-title label">複製到對應目錄</div> <div class="item-input line-right"> <label class="label-switch"> <input type="checkbox" checked name="is_auto_copy"> <div class="checkbox"></div> </label> </div> </div> </div> </li> </ul> </div> <div class="content-block"> <div class="row"> <div class="col-50"><a href="#" class="button button-big button-fill button-danger">取消</a></div> <div class="col-50"><a href="#" class="button button-big button-fill button-success" onclick="submit()">提交</a></div> </div> </div> </form> </div> </div> </div> <script> var submit = function () { $('#sub-form').submit(); } </script> </body> </html>
根據輸入的表名稱,查詢數據庫,獲取表結構,解析字段內容,而後格式化字段內容。
public function builder() { $table_name = request()->input('table_name'); $table_prefix = request()->input('table_prefix', ''); $table_name_cn = request()->input('table_name_cn'); $sub_module_name = request()->input('sub_module_name'); $b_module_name = request()->input('b_module_name', 'manage'); $f_module_name = request()->input('f_module_name', 'admin'); $is_init_model = request()->input('is_init_model'); $is_init_b_controller = request()->input('is_init_b_controller'); $is_init_b_router = request()->input('is_init_b_router'); $is_init_list = request()->input('is_init_list'); $is_init_edit = request()->input('is_init_edit'); $is_init_f_controller = request()->input('is_init_f_controller'); $is_init_inter = request()->input('is_init_inter'); $is_auto_copy = request()->input('is_auto_copy', false); if (empty($table_name)) { die('Table Name Is Null!'); } if (empty($table_name_cn)) { $table_name_cn = $table_name; } $orgName = $table_name; $table = str_replace(' ', '', $orgName); $className = ucwords(str_replace(array('.', '-', '_'), ' ', $table)); $moduleName = explode(',', $className)[0]; if (!empty($sub_module_name)) { $moduleName = $sub_module_name; } $b_module_name = ucwords($b_module_name); $f_module_name = ucwords($f_module_name); $b_module_name_lc = lcfirst($b_module_name); $f_module_name_lc = lcfirst($f_module_name); $className = str_replace(' ', '', $className); $classNameLc = lcfirst($className); $moduleNameLc = lcfirst($moduleName); $result = DB::select("SHOW FULL COLUMNS FROM " . $table_prefix . $table); $fields = []; foreach ($result as $r) { if (in_array($r->Field, $this->ignoreField)) { continue; } $field = []; $field['db_type'] = $r->Type; $field['field'] = $r->Field; $field['comment'] = $r->Comment; $field['in_type'] = 'string'; $field['in_name'] = $r->Comment; $comment = str_replace(',', ',', $r->Comment); $comment = preg_replace("# #", '', $comment); $array = explode(',', $comment); $field['in_common'] = $array[0]; if (!empty($array[1])) { $typeContent = explode('|', $array[1]); switch ($typeContent[0]) { case '枚舉': $field['in_type'] = 'enum'; $in_value = []; foreach ($typeContent as $index => $typeContentValue) { if ($index == 0) { continue; } $key = explode('-', $typeContentValue); $value = []; $value['value'] = $key[0]; $value['label'] = (isset($key[1]) ? $key[1] : $key[0]); $value['key'] = $field['field'] . "_" . (isset($key[2]) ? $key[2] : (isset($key[1]) ? $key[1] : $key[0])); $value['common'] = '//' . $field['in_common'] . ":" . (isset($key[1]) ? $key[1] : $key[0]); $value['const'] = 'const ' . strtoupper($value['key']) . ' = ' . $key[0] . '; ' . $value['common']; array_push($in_value, $value); } $field['in_value'] = $in_value; break; case '開關': $field['in_type'] = 'switch'; $in_value = []; foreach ($typeContent as $index => $typeContentValue) { if ($index == 0) { continue; } $key = explode('-', $typeContentValue); $value = []; $value['value'] = $key[0]; $value['label'] = (isset($key[1]) ? $key[1] : $key[0]); $value['key'] = $field['field'] . "_" . (isset($key[2]) ? $key[2] : (isset($key[1]) ? $key[1] : $key[0])); $value['common'] = '//' . $field['in_common'] . ":" . (isset($key[1]) ? $key[1] : $key[0]); $value['const'] = 'const ' . strtoupper($value['key']) . ' = ' . $key[0] . '; ' . $value['common']; array_push($in_value, $value); } $field['in_value'] = $in_value; break; case '富文本': $field['in_type'] = 'rtext'; break; default: { $field['in_type'] = 'string'; break; } } } array_push($fields, $field); } }
讀取相應的代碼模版,填充數據字段內容,生成代碼文件
$viewResult = []; //建立目錄 $filePath = base_path() . "\\bootstrap\\builder\\output\\{$table}\\"; if (!is_dir($filePath)) { mkdir($filePath, 0777, true); } $data = []; $data['tableName'] = "tb_" . $table; $data['fields'] = $fields; $data['className'] = $className; $data['moduleName'] = $moduleName; $data['classNameLc'] = $classNameLc; $data['moduleNameLc'] = $moduleNameLc; $data['b_module_name'] = $b_module_name; $data['f_module_name'] = $f_module_name; $data['b_module_name_lc'] = $b_module_name_lc; $data['f_module_name_lc'] = $f_module_name_lc; $data['orgName'] = $orgName; //建立 - model if (!empty($is_init_model)) { $view = View::tbl('model', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_M'; $resultItem = []; $resultItem['title'] = 'model-後端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*後端模型,目錄*/ if ($is_auto_copy) { $models_dir = base_path() . "\\app\\Models\\"; $models_file_name = $className; if (!file_exists($models_dir . $models_file_name . '.php')) { copy($fileName, $models_dir . $models_file_name . '.php'); } else { copy($fileName, $models_dir . $models_file_name . ''); } } } //建立 - controller if (!empty($is_init_b_controller)) { $view = View::tbl('controller', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_Controller'; $resultItem = []; $resultItem['title'] = 'Controller-後端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*後端Controller,目錄*/ if ($is_auto_copy) { $controller_dir = base_path() . "\\app\\Modules\\{$b_module_name}\\Controllers\\"; $controller_file_name = $className . 'Controller'; if (!file_exists($controller_dir . $controller_file_name . '.php')) { copy($fileName, $controller_dir . $controller_file_name . '.php'); } else { copy($fileName, $controller_dir . $controller_file_name . ''); } } } //建立 - list if (!empty($is_init_list)) { //建立 - list_view $view = View::tbl('list_view', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_ListView'; $resultItem = []; $resultItem['title'] = 'list頁面-前端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*前端Controller,目錄*/ if ($is_auto_copy) { $display_dir = base_path() . "\\public\\{$f_module_name_lc}\\main\\view\\" . $classNameLc . "\\"; if (!is_dir($display_dir)) { mkdir($display_dir, 0777, true); } $display_file_name = $classNameLc . 'ListView'; if (!file_exists($display_dir . $display_file_name . '.html')) { copy($fileName, $display_dir . $display_file_name . '.html'); } else { copy($fileName, $display_dir . $display_file_name . ''); } } //建立 - list_display $view = View::tbl('list_display', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_ListDisplay'; $resultItem = []; $resultItem['title'] = 'list-table頁面-前端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*前端Controller,目錄*/ if ($is_auto_copy) { $display_dir = base_path() . "\\public\\{$f_module_name_lc}\\main\\view\\" . $classNameLc . "\\"; if (!is_dir($display_dir)) { mkdir($display_dir, 0777, true); } $display_file_name = $classNameLc . 'ListDisplay'; if (!file_exists($display_dir . $display_file_name . '.html')) { copy($fileName, $display_dir . $display_file_name . '.html'); } else { copy($fileName, $display_dir . $display_file_name . ''); } } } //建立 - Edit-html if (!empty($is_init_edit)) { $view = View::tbl('edit_html', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_EditView'; $resultItem = []; $resultItem['title'] = 'edit-編輯頁面-前端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*前端Controller,目錄*/ if ($is_auto_copy) { $edit_dir = base_path() . "\\public\\{$f_module_name_lc}\\main\\view\\" . $classNameLc . "\\"; if (!is_dir($edit_dir)) { mkdir($edit_dir, 0777, true); } $edit_file_name = $classNameLc . 'EditView'; if (!file_exists($edit_dir . $edit_file_name . '.html')) { copy($fileName, $edit_dir . $edit_file_name . '.html'); } else { copy($fileName, $edit_dir . $edit_file_name . ''); } } } //建立 - Controller - JS if (!empty($is_init_f_controller)) { $view = View::tbl('controller_js', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_Controller_JS'; $resultItem = []; $resultItem['title'] = 'controller_js-前端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*前端Controller,目錄*/ if ($is_auto_copy) { $controller_js_dir = base_path() . "\\public\\{$f_module_name_lc}\\main\\controller\\"; $controller_js_file_name = $classNameLc . ''; if (!file_exists($controller_js_dir . $controller_js_file_name . '.js')) { copy($fileName, $controller_js_dir . $controller_js_file_name . '.js'); } else { copy($fileName, $controller_js_dir . $controller_js_file_name . ''); } } } //建立 - 後臺路由 if (!empty($is_init_b_router)) { //建立 - Router $view = View::tbl('router', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_Router'; $resultItem = []; $resultItem['title'] = 'router_路由-後端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); /*拷貝到指定目錄*/ /*前端Controller,目錄*/ if ($is_auto_copy) { $router_name = base_path() . "\\app\\Modules\\{$b_module_name}\\router.php";; if (!file_exists($router_name)) { } else { file_put_contents($router_name, $html, FILE_APPEND | LOCK_EX); } } } //建立 - config_js if (!empty($is_init_inter)) { $view = View::tbl('config_js', $data); $view->layout = false; $html = $view->html(); $fileName = $filePath . $className . '_Config_js'; $resultItem = []; $resultItem['title'] = 'config_接口配置文件-前端'; $resultItem['fileName'] = $fileName; array_push($viewResult, $resultItem); file_put_contents($fileName, $html, LOCK_EX); } //設置菜單 $result['result'] = $viewResult; $view = View::tbl('result',$result); $view->layout = false; echo $view->html(); die();
主頁 (Alpaca-Spa): http://www.tkc8.com
後臺(Alpaca-Spa-Laravel) : http://full.tkc8.com
手機端sui(Alpaca-Spa-Sui) : http://full.tkc8.com/app
代碼 (oschina ): http://git.oschina.net/cc-sponge/Alpaca-Spa-Laravel
代碼 (github ): https://github.com/big-sponge/Alpaca-Spa-Laravel
QQ羣: 298420174
做者: Sponge 郵箱: 1796512918@qq.com