配置即一切

一切皆于需求,后台从0开始搭建,但是写了一两个页面后发现太多的是对单表的增删改查操作,于是就想到了,能不能做一个快速搭建的后台。想到一句话,配置即一切。如果一个CURD后台能只进行配置就自动生成,该是多么美妙的事情,那么就开始搭建这么个结构。
 

首先配置文件应该怎么设计

起初想到将配置文件放到config目录下,但是想想还是放弃了这个想法,那样子可能会导致有一个“万能”文件,又臭又长。那么,其次,这个功能只针对单表,所以,是不是可以将配置文件放置在Model中,后来也觉得这个想法不大好,这个配置文件是承担页面展示的功能的,如果放在Model中就算是入侵了Model层了。所以最后决定放在了Controller中。
 

最后的效果大概是什么样子的?

后台大概会有几个页面:

列表页:

列表页中有查询操作,编辑,删除按钮,新建按钮。

新建页面:

 

编辑页面:

 
好了,对应这几个页面,我们可以设置配置项了。
 
基本想法是搭建一个FormController,所有以后需要配置生成后台的controller就继承这个FormController就好了。在FormController中定义属性:
class FormController extends BaseController {

     // 对应的模型
protected $model; // 所有的字段
protected $fields_all; // 列表页显示的字段
protected $fields_show; // 编辑页面显示的字段
protected $fields_edit; // 创建页面显示的字段
protected $fields_create;
}
定义了Model,来表示这个Controller是对那个Model进行单表操作的。
定义了fields_all属性,来将所有的字段来进行一个说明和定义。这个定义和说明就包括字段显示名字,字段是否要进行搜索,字段类型是什么。
对于列表页,不是所有属性都显示出来,所以定义一个$fields_show,这个数组存放的是$fields_all中的一些字段,用来显示的字段。
对于编辑页面,要显示的字段就放在$field_edit中
对于创建页面,要显示的字段就放在$field_create中
 
好了,现在继承FormController的类就只需要这么配置就好;
<?php

// 账号管理系统
class BadminController extends FormController
{ public function __construct()
{
$this->model = '\Badmin';
$this->fields_all = [
'id' => [
'show' => '序号',
],
'nickname' => [
'show' => '昵称',
'search' => "nickname like CONCAT('%', ?, '%')"
],
'username' => [
'show' => '用户名',
],
'email' => [
'show' => '邮箱',
],
'password' => [
'show' => '密码',
],
'created_at' => [
'show' => '创建时间',
],
'updated_at' => [
'show' => '更新时间',
],
]; $this->fields_show = ['id' ,'nickname', 'username', 'email', 'created_at'];
$this->fields_edit = ['nickname', 'username'];
$this->fields_create = ['nickname', 'username', 'email', 'password'];
parent::__construct();
}
在构造函数中定义model,$fields_all, $fields_show, $fields_edit, $fields_create。
对于fields_all,key为数据库对应的字段名,value为一个数组,show是显示名,如果你在列表页希望这个字段能进行搜索,就设置下search属性。
 

路由

下面是路由,laravel中路由基本有三种:
Route::get('order/{id}',['as'=>'order.detail','uses'=>'OrderController@show']);
Route::controller('preview', 'PreviewController');
Route::resource('badmin', 'BadminController');
第三种已经完全定义好了增删改查操作,看起来能省我不少的事情,好吧,我就使用这个resource来做了。
 
所以在route.php中我只需要定义这么一条就ok了
 
// 管理员账号管理
Route::resource('badmin', 'BadminController');

Controller

下面写FromController中的resource方法
 
按照laravel的resource定义的,需要填充的方法有:
 
我习惯在构造函数中把一些诸如Input,全局定义的东西都share到模版中,代码如下:
     public function __construct()
{ // TODO:做一些基础的判断,如果没有的话就抛出异常 $route = Route::currentRouteAction();
list($this->controller, $action) = explode('@', $route);
View::share('controller', $this->controller); $fields_show = array();
foreach ($this->fields_show as $field) {
$fields_show[$field] = $this->fields_all[$field];
}
View::share('fields_show', $fields_show); $fields_edit = array();
foreach ($this->fields_edit as $field) {
$fields_edit[$field] = $this->fields_all[$field];
}
View::share('fields_edit', $fields_edit); $fields_create = array();
foreach ($this->fields_create as $field) {
$fields_create[$field] = $this->fields_all[$field];
}
View::share('fields_create', $fields_create); View::share('input', Input::all());
}
这里把controller放到外面是为了在view中可以使用诸如:
action($controller . '@destroy', $model->id),
的路径定义
 
index函数:

     public function index()
{
$model = new $this->model;
$builder = $model->orderBy('id', 'desc'); $input = Input::all();
foreach ($input as $field => $value) {
if (empty($value)) {
continue;
}
if (!isset($this->fields_all[$field])) {
continue;
}
$search = $this->fields_all[$field];
$builder->whereRaw($search['search'], [$value]);
}
$models = $builder->paginate(); return View::make('form.index', [
'models' => $models,
]);
}

$builder在laravel中真是太TMD好用了,对于这里的搜索,我使用whereRaw进行prepare查询。这里还有一个点,之前在fields_all设计的时候,我定义的直接是一个 'search' => "nickname like CONCAT('%', ?, '%')"  这里定义搜索字段的时候其实有很多种设计方法,比如定义为

‘search’ => [
'type' => 'like',
'value' => '%?%'
]
但是考虑到使用这个FromController的都是程序员,所以这里的search直接使用预处理的语句,然后在index中直接使用whereRaw,这样使得配置文件的易读性增加了。
 
下面是

create函数:

     public function create()
{
return View::make('form.create', []);
}

store函数:

     public function store()
{
$model = new $this->model;
$model->fill(Input::all());
$model->save();
return Redirect::to(action($this->controller . '@index'));
}
这里的model的fill是不是很简单,爽到爆。当然model中还是需要定义fillable字段
 

edit,update,destory函数

如法炮制就好

     public function edit($id)
{
$model = new $this->model;
$model = $model->find($id);
return View::make('form.edit', compact('model'));
} public function update($id)
{
$model = new $this->model;
$model = $model->find($id);
$model->fill(Input::all());
$model->save(); return Redirect::to(action($this->controller . '@index'));
} public function destroy($id)
{
$model = new $this->model;
$model->destroy($id); return Redirect::to(action($this->controller . '@index'));
}

View

下面就是view的编写。
view大概就只要三个页面,列表页面,编辑页面,创建页面
 

列表页面注意事项:

1 使用laravel自带分页,注意记得带上本页的输入参数,这个时候,构造函数中share的Input就很有用了

{{$models->appends($input)->links()}}
 

2 可以使用laravel自带的from操作,比如删除操作由于需要调用HTTP的DELETE 方法,可以这么写

                 {{ Form::open(array(
'id' => "delete_{$model->id}",
'url' => action($controller . '@destroy', $model->id),
'class' => 'dropdown-toggle')) }}
{{ Form::hidden('_method', 'DELETE') }}
{{ Form::close() }}
 
其实自己写DELETE也行,就是在From表单中多传递一个_method隐藏域
 

3 搜索直接使用一个form就可以搞定了

     <form class="form-inline" role="form" action="{{action($controller . '@index')}}">
@foreach ($fields_show as $field => $field_info)
@if (isset($field_info['search']))
<div class="form-group">
<label class="col-sm-3 control-label">{{$field_info['show']}}</label>
<div class="col-md-3">
<input name="{{$field}}" type="input" class="form-control" placeholder="" value="@if (isset($input[$field])){{$input[$field]}}@endif">
</div>
</div>
@endif
@endforeach
<input type="submit" class="btn btn-success" value="查询" />
</form>

编辑页面和创建页面

简单到只需要一个form就能搞定了

  <form class="form-horizontal"
role="form"
action="{{action($controller . "@update", $model->id)}}" method='POST'>
<input type="hidden" name="_method" value="PUT">
@foreach ($fields_edit as $field => $field_info)
<div class="form-group">
<label class="col-sm-2 control-label">{{$field_info['show']}}</label>
<div class="col-sm-10">
<input name="{{$field}}" type="text" class="form-control" placeholder="" value="{{$model->$field}}">
</div>
</div>
<div class="line line-dashed line-lg pull-in"></div>
@endforeach
<div class="col-sm-4 col-sm-offset-2">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
 
记得resource中更新的操作是要使用PUT方式,删除的操作要使用DELETE方式。
至于view的模版,我这里使用的是一款叫notebook的模版,它是基于bootstrap的,你也可以使用其他更好看的模版来写。
 
好了,至此这么个快速搭建CURD的结构就完成了。现在可以在运营人员给需求的时候,很牛逼地说,等我一分钟,我就给你一个世界~~

后记

其实回想下,这整个结构不算复杂。配置即一切的思想能解决很多问题。但是依赖配置的路子最怕的是几个事情:
1 配置文件过于复杂。(如果你的配置文件过于复杂,已经超过了敲代码本身需要了解的东西,那么这个配置项的学习成本就太太太高了)
2 配置字段语意不清。(配置的字段名字和意思不对,字段名和变量名一样重要!)
 
当然这个就是个初步,改进的几个点还有
1 所有字段都使用input标签,需要在配置中加入其它标签类型
2 是不是考虑view中所有的东西都使用laravel自带的form对应字段?

使用laravel一分钟搭建CURD后台页面的更多相关文章

  1. 使用laravel搭建CURD后台页面

    配置即一切 一切皆于需求,后台从0开始搭建,但是写了一两个页面后发现太多的是对单表的增删改查操作,于是就想到了,能不能做一个快速搭建的后台.想到一句话,配置即一切.如果一个CURD后台能只进行配置就自 ...

  2. 基于laravel5.4 vue 和vue-element搭建的单页面后台CMS

    介绍 该项目后台是基于vue和laravel搭建的单页面CMS系统,包含了文章管理,权限管理,用户管理等基本模块. 前台使用了传统web技术,laravel渲染搭建了个博客系统 github地址:ht ...

  3. 一分钟搭建Vue2.0+Webpack2.0多页面项目

    想要自己一步步搭建的比较麻烦,不是很推荐,最少也要使用vue-cli,在其基础上开始搭建,今天我的主题是一分钟搭建,那么常规方法肯定不能满足的, 而我用的方法也很简单,就是使用已经配置完成的demo模 ...

  4. 【SSH网上商城项目实战03】使用EasyUI搭建后台页面框架

    转自:https://blog.csdn.net/eson_15/article/details/51312490 前面两节,我们整合了SSH并且抽取了service和action部分的接口,可以说基 ...

  5. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  6. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  7. ASP.NET MVC搭建项目后台UI框架—7、统计报表

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NET M ...

  8. ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  9. LAMP-五分钟搭建个人论坛

    LAMP-五分钟搭建个人论坛 系统版本:CentOS7 1.##安装lamp及依赖软件wget http://repo.mysql.com/mysql-community-release-el7-5. ...

随机推荐

  1. Yii2 使用Composer

    composer 是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件 compo ...

  2. mono for android学习过程系列教程(6)

    接着上一讲,今天讲的是Button,CheckBox这二个安卓元素, 我们来看第一个Button这个控件,类似winform和webform里面一样,它也是 存在有触发事件的,我们新建初始化项目直接就 ...

  3. TypeScript之接口类型

    Interfaces 作为TypeScript中的核心特色之一,能够让类型检查帮助我们知道一个对象应该有什么,相比我们在编写JavaScript的时候经常遇到函数需要传递参数,可能在编写的时候知道这个 ...

  4. 【Win10】UAP/UWP/通用 开发之 RelativePanel

    [Some information relates to pre-released product which may be substantially modified before it's co ...

  5. Expression Tree 扩展MVC中的 HtmlHelper 和 UrlHelper

    表达式树是LINQ To everything 的基础,同时各种类库的Fluent API也 大量使用了Expression Tree.还记得我在不懂expression tree时,各种眼花缭乱的A ...

  6. C#中的线程一(委托中的异步)

    C#中的线程一(委托中的异步) 一.同步委托 我们平时所用的委托以同步居多,我们编写一个方法和相关委托进行演示: publicdelegatevoid DoSomethingDelegate(stri ...

  7. Java虚拟机1:什么是Java

    前言 让我们来看一下Java的广告词,来自http://www.java.com/zh_CN/about/: 97%的企业桌面运行Java 美国有89%的桌面(或计算机)运行Java 全球有900万J ...

  8. EF6(CodeFirst)+MySql开发脱坑指南

    废话 话说当年,在一个春光明媚的晌午,邂逅了迷人的丁香姑娘,从此拜倒在了她的石榴裙下,至今不能自拔,这位丁香姑娘就是ORM思想. 所谓ORM思想,我的理解就是根据一定的规则,把程序中的对象和数据库中的 ...

  9. 团队项目——站立会议DAY12

    第十二次站立会议记录: 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 项目进展: 1.张靖颜:已经将部分代码完成,对一些模块化的功能进行扩展,对已具备的功能进行完善. 2.钟灵毓秀:对代码进行了修改 ...

  10. Guava - 并行编程Futures

    Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展. 继承至Future的ListenableFuture,允许我 ...