编程技术分享

主要分享java php javascript 编程技术

Laravel--使用介绍

2020-11-16 xiaxiang

1、简介

Laravel 应用默认的目录结构试图为不管是大型应用还是小型应用提供一个好的起点,当然,你可以自己按照喜好重新组织应用目录结构,Laravel 对类在何处被加载没有任何限制——只要 Composer 可以自动载入它们即可。

Models目录在哪里?

许多初学者都会困惑Laravel为什么没有models目录,我可以负责任的告诉大家,这是故意的。因为models这个词对不同人而言有不同的含义,容易造成歧义,有些开发者认为应用的模型指的是业务逻辑,另外一些人则认为模型指的是与关联数据库的交互。

正是因为这个原因,我们默认将Eloquent的模型直接放置到app目录下,从而允许开发者自行选择放置的位置,关注我的博客,larave详解,会告诉你的;

2、根目录

App目录

app目录包含了应用的核心代码,此外你为应用编写的代码绝大多数也会放到这里;

Bootstrap目录

bootstrap目录包含了少许文件,用于框架的启动和自动载入配置,还有一个cache文件夹用于包含框架为提升性能所生成的文件,如路由和服务缓存文件;

Config目录

config目录包含了应用所有的配置文件,建议通读一遍这些配置文件以便熟悉所有配置项;

Database目录

database目录包含了数据迁移及填充文件,如果你喜欢的话还可以将其作为 SQLite 数据库存放目录;

Public目录

public目录包含了入口文件index.php和前端资源文件(图片、JavaScript、CSS等);

Resources目录

resources目录包含了视图文件及原生资源文件(LESS、SASS、CoffeeScript),以及本地化文件;

Routes目录

routes 目录包含了应用的所有路由定义。Laravel默认提供了三个路由文件:web.phpapi.phpconsole.php

web.php文件包含的路由都会应用web中间件组,具备Session、CSRF防护以及Cookie加密功能,如果应用无需提供无状态的、RESTful风格的API,所有路由都会定义在web.php文件。

api.php 文件包含的路由应用了api中间件组,具备频率限制功能,这些路由是无状态的,所以请求通过这些路由进入应用需要通过token进行认证并且不能访问Session状态。

console.php 文件用于定义所有基于闭包的控制台命令,每个闭包都被绑定到一个控制台命令并且允许与命令行IO方法进行交互,尽管这个文件并不定义HTTP路由,但是它定义了基于控制台的应用入口(路由)。

Storage目录

storage目录包含了编译过的Blade模板、基于文件的session、文件缓存,以及其它由框架生成的文件,该目录被细分为成appframeworklogs子母录,app目录用于存放应用要使用的文件,framework目录用于存放框架生成的文件和缓存,最后,logs目录包含应用的日志文件;

storage/app/public 目录用于存储用户生成的文件,比如可以被公开访问的用户头像,要达到被访问的目的,你还需要在public目录下生成一个软连接storage 指向这个目录。你可以通过php artisan storage:link 命令生成这个软链接。

Tests目录

tests目录包含自动化测试,其中已经提供了一个开箱即用的PHPUnit示例;每一个测试类都要以 Test 开头,你可以通过phpunit 或php vendor/bin/phpunit 命令来运行测试。

Vendor目录

vendor目录包含Composer依赖。

3、App目录

应用的核心代码位于app目录下,默认情况下,该目录位于命名空间 App 下,  并且被 Composer 通过 PSR-4自动载入标准 自动加载。

app目录下包含多个子目录,如ConsoleHttpProviders等。ConsoleHttp目录提供了进入应用核心的API,HTTP协议和CLI是和应用进行交互的两种机制,但实际上并不包含应用逻辑。换句话说,它们只是两个向应用发布命令的方式。Console目录包含了所有的Artisan命令,Http目录包含了控制器、中间件和请求等。

其他目录将会在你通过Artisan命令make生成相应类的时候生成到app目录下。例如,app/Jobs目录直到你执行make:job 命令生成任务类时才会出现在app目录下。

注意:app目录中的很多类都可以通过Artisan命令生成,要查看所有有效的命令,可以在终端中运行php artisan list make命令。

Console目录

Console目录包含应用所有自定义的Artisan命令,这些命令类可以使用make:command命令生成。该目录下还有console核心类,在这里可以注册自定义的Artisan命令以及定义调度任务。

Events目录

这个目录默认不存在,但是可以通过 event:generate 和 make:event 命令创建。该目录用于存放事件类。事件类用于告知应用其他部分某个事件发生并提供灵活的、解耦的处理机制。

Exceptions目录

Exceptions目录包含应用的异常处理器,同时还是处理应用抛出的任何异常的好地方。如果你想要自定义异常如何记录异常或渲染,需要修改 Handler 类。

Http目录

Http 目录包含了控制器、中间件以及表单请求等,几乎所有进入应用的请求处理都在这里进行。

Jobs目录

该目录默认不存在,可以通过执行 make:job 命令生成,Jobs目录用于存放队列任务,应用中的任务可以被队列化,也可以在当前请求生命周期内同步执行。同步执行的任务有时也被看作命令,因为它们实现了命令模式。

Listeners目录

这个目录默认不存在,可以通过执行 event:generate 和 make:listener 命令创建。Listeners目录包含处理事件的类(事件监听器),事件监听器接收一个事件并提供对该事件发生后的响应逻辑,例如,UserRegistered事件可以被SendWelcomeEmail监听器处理。

Mail目录

这个目录默认不存在,但是可以通过执行 make:mail 命令生成,Mail目录包含邮件发送类,邮件对象允许你在一个地方封装构建邮件所需的所有业务逻辑,然后使用Mail::send 方法发送邮件。

Notifications目录

这个目录默认不存在,你可以通过执行 make:notification 命令创建,Notifications 目录包含应用发送的所有通知,比如事件发生通知。Laravel的通知功能将通知发送和通知驱动解耦,你可以通过邮件,也可以通过Slack、短信或者数据库发送通知。

Policies目录

这个目录默认不存在,你可以通过执行 make:policy 命令来创建,Policies 目录包含了所有的授权策略类,策略用于判断某个用户是否有权限去访问指定资源。更多详情,请查看授权文档

Providers目录

Providers 目录包含应用的所有服务提供者。服务提供者在启动应用过程中绑定服务到容器、注册事件以及执行其他任务以为即将到来的请求处理做准备。

在新安装的Laravel应用中,该目录已经包含了一些服务提供者,你可以按需添加自己的服务提供者到该目录。

技术特点

1、Bundle是Laravel的扩展包组织形式或称呼。Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中。你可以选择下载一个扩展包(bundle)然后拷贝到bundles目录,或者通过命令行工具“Artisan”自动安装。

 

2、在Laravel中已经具有了一套高级的PHP ActiveRecord实现 -- Eloquent ORM。它能方便的将“约束(constraints)”应用到关系的双方,这样你就具有了对数据的完全控制,而且享受到ActiveRecord的所有便利。Eloquent原生支持Fluent中查询构造器(query-builder)的所有方法。

 

3、应用逻辑(Application Logic)可以在控制器(controllers)中实现,也可以直接集成到路由(route)声明中,并且语法和Sinatra框架类似。Laravel的设计理念是:给开发者以最大的灵活性,既能创建非常小的网站也能构建大型的企业应用。

 

4、反向路由(Reverse Routing)赋予你通过路由(routes)名称创建链接(URI)的能力。只需使用路由名称(route name),Laravel就会自动帮你创建正确的URI。这样你就可以随时改变你的路由(routes),Laravel会帮你自动更新所有相关的链接。

 

5、Restful控制器(Restful Controllers)是一项区分GET和POST请求逻辑的可选方式。比如在一个用户登陆逻辑中,你声明了一个get_login()的动作(action)来处理获取登陆页面的服务;同时也声明了一个post_login()动作(action)来校验表单POST过来的数据,并且在验证之后,做出重新转向(redirect)到登陆页面还是转向控制台的决定。

 

6、自动加载类(Class Auto-loading)简化了类(class)的加载工作,以后就可以不用去维护自动加载配置表和非必须的组件加载工作了。当你想加载任何库(library)或模型(model)时,立即使用就行了,Laravel会自动帮你加载需要的文件。

 

7、视图组装器(View Composers)本质上就是一段代码,这段代码在视图(View)加载时会自动执行。最好的例子就是博客中的侧边随机文章推荐,“视图组装器”中包含了加载随机文章推荐的逻辑,这样,你只需要加载内容区域的视图(view)就行了,其它的事情Laravel会帮你自动完成。

 

8、反向控制容器(IoC container)提供了生成新对象、随时实例化对象、访问单例(singleton)对象的便捷方式。反向控制(IoC)意味着你几乎不需要特意去加载外部的库(libraries),就可以在代码中的任意位置访问这些对象,并且不需要忍受繁杂、冗余的代码结构。

 

9、迁移(Migrations)就像是版本控制(version control)工具,不过,它管理的是数据库范式,并且直接集成在了Laravel中。你可以使用“Artisan”命令行工具生成、执行“迁移”指令。当你的小组成员改变了数据库范式的时候,你就可以轻松的通过版本控制工具更新当前工程,然后执行“迁移"指令即可,好了,你的数据库已经是最新的了!

 

10、单元测试(Unit-Testing)是Laravel中很重要的部分。Laravel自身就包含数以百计的测试用例,以保障任何一处的修改不会影响其它部分的功能,这就是为什么在业内Laravel被认为是最稳版本的原因之一。Laravel也提供了方便的功能,让你自己的代码容易的进行单元测试。通过Artisan命令行工具就可以运行所有的测试用例。

 

11、自动分页(Automatic Pagination)功能避免了在你的业务逻辑中混入大量无关分页配置代码。方便的是不需要记住当前页,只要从数据库中获取总的条目数量,然后使用limit/offset获取选定的数据,最后调用‘paginate’方法,让Laravel将各页链接输出到指定的视图(View)中即可,Laravel会替你自动完成所有工作。Laravel的自动分页系统被设计为容易实现、易于修改。虽然Laravel可以自动处理这些工作,但是不要忘了调用相应方法和手动配置分页系统哦
 

配置即一切

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

 

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

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

 

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

后台大概会有几个页面:

列表页:

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

新建页面:

 

编辑页面:

 

好了,对应这几个页面,我们可以设置配置项了。

 

基本想法是搭建一个FormController,所有以后需要配置生成后台的controller就继承这个FormController就好了。在FormController中定义属性:

复制代码

 
  1. class FormController extends BaseController {
  2. // 对应的模型
  3. protected $model;
  4. // 所有的字段
  5. protected $fields_all;
  6. // 列表页显示的字段
  7. protected $fields_show;
  8. // 编辑页面显示的字段
  9. protected $fields_edit;
  10. // 创建页面显示的字段
  11. protected $fields_create;
  12. }

复制代码

定义了Model,来表示这个Controller是对那个Model进行单表操作的。

定义了fields_all属性,来将所有的字段来进行一个说明和定义。这个定义和说明就包括字段显示名字,字段是否要进行搜索,字段类型是什么。

对于列表页,不是所有属性都显示出来,所以定义一个fieldsshow,这个数组存放的是

fields_all中的一些字段,用来显示的字段。

对于编辑页面,要显示的字段就放在$field_edit中

对于创建页面,要显示的字段就放在$field_create中

 

好了,现在继承FormController的类就只需要这么配置就好;

复制代码

 
  1. <?php
  2. // 账号管理系统
  3. class BadminController extends FormController
  4. {
  5. public function __construct()
  6. {
  7. $this->model = '\Badmin';
  8. $this->fields_all = [
  9. 'id' => [
  10. 'show' => '序号',
  11. ],
  12. 'nickname' => [
  13. 'show' => '昵称',
  14. 'search' => "nickname like CONCAT('%', ?, '%')"
  15. ],
  16. 'username' => [
  17. 'show' => '用户名',
  18. ],
  19. 'email' => [
  20. 'show' => '邮箱',
  21. ],
  22. 'password' => [
  23. 'show' => '密码',
  24. ],
  25. 'created_at' => [
  26. 'show' => '创建时间',
  27. ],
  28. 'updated_at' => [
  29. 'show' => '更新时间',
  30. ],
  31. ];
  32. $this->fields_show = ['id' ,'nickname', 'username', 'email', 'created_at'];
  33. $this->fields_edit = ['nickname', 'username'];
  34. $this->fields_create = ['nickname', 'username', 'email', 'password'];
  35. parent::__construct();
  36. }

复制代码

在构造函数中定义model,fieldsall,

fields_show, fieldsedit,

fields_create。

对于fields_all,key为数据库对应的字段名,value为一个数组,show是显示名,如果你在列表页希望这个字段能进行搜索,就设置下search属性。

 

路由

下面是路由,laravel中路由基本有三种:

 
  1. Route::get('order/{id}',['as'=>'order.detail','uses'=>'OrderController@show']);
  2. Route::controller('preview', 'PreviewController');
  3. Route::resource('badmin', 'BadminController');

 

第三种已经完全定义好了增删改查操作,看起来能省我不少的事情,好吧,我就使用这个resource来做了。

 

所以在route.php中我只需要定义这么一条就ok了

 

 
  1. // 管理员账号管理
  2. Route::resource('badmin', 'BadminController');

 

Controller 

下面写FromController中的resource方法

 

按照laravel的resource定义的,需要填充的方法有:

 

我习惯在构造函数中把一些诸如Input,全局定义的东西都share到模版中,代码如下:

复制代码

 
  1. public function __construct()
  2. {
  3. // TODO:做一些基础的判断,如果没有的话就抛出异常
  4. $route = Route::currentRouteAction();
  5. list($this->controller, $action) = explode('@', $route);
  6. View::share('controller', $this->controller);
  7. $fields_show = array();
  8. foreach ($this->fields_show as $field) {
  9. $fields_show[$field] = $this->fields_all[$field];
  10. }
  11. View::share('fields_show', $fields_show);
  12. $fields_edit = array();
  13. foreach ($this->fields_edit as $field) {
  14. $fields_edit[$field] = $this->fields_all[$field];
  15. }
  16. View::share('fields_edit', $fields_edit);
  17. $fields_create = array();
  18. foreach ($this->fields_create as $field) {
  19. $fields_create[$field] = $this->fields_all[$field];
  20. }
  21. View::share('fields_create', $fields_create);
  22. View::share('input', Input::all());
  23. }

复制代码

 

这里把controller放到外面是为了在view中可以使用诸如:

action(controller.′@destroy′,

model->id),

的路径定义

 

index函数:

 

复制代码

 
  1. public function index()
  2. {
  3. $model = new $this->model;
  4. $builder = $model->orderBy('id', 'desc');
  5. $input = Input::all();
  6. foreach ($input as $field => $value) {
  7. if (empty($value)) {
  8. continue;
  9. }
  10. if (!isset($this->fields_all[$field])) {
  11. continue;
  12. }
  13. $search = $this->fields_all[$field];
  14. $builder->whereRaw($search['search'], [$value]);
  15. }
  16. $models = $builder->paginate(20);
  17. return View::make('form.index', [
  18. 'models' => $models,
  19. ]);
  20. }

复制代码

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

 
  1. ‘search’ => [
  2. 'type' => 'like',
  3. 'value' => '%?%'
  4. ]

 

 

但是考虑到使用这个FromController的都是程序员,所以这里的search直接使用预处理的语句,然后在index中直接使用whereRaw,这样使得配置文件的易读性增加了。

 

下面是

create函数:

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

 

store函数:

复制代码

 
  1. public function store()
  2. {
  3. $model = new $this->model;
  4. $model->fill(Input::all());
  5. $model->save();
  6. return Redirect::to(action($this->controller . '@index'));
  7. }

复制代码

 

这里的model的fill是不是很简单,爽到爆。当然model中还是需要定义fillable字段

 

edit,update,destory函数

如法炮制就好

 

复制代码

 
  1. public function edit($id)
  2. {
  3. $model = new $this->model;
  4. $model = $model->find($id);
  5. return View::make('form.edit', compact('model'));
  6. }
  7. public function update($id)
  8. {
  9. $model = new $this->model;
  10. $model = $model->find($id);
  11. $model->fill(Input::all());
  12. $model->save();
  13. return Redirect::to(action($this->controller . '@index'));
  14. }
  15. public function destroy($id)
  16. {
  17. $model = new $this->model;
  18. $model->destroy($id);
  19. return Redirect::to(action($this->controller . '@index'));
  20. }

复制代码

 

 View

下面就是view的编写。

view大概就只要三个页面,列表页面,编辑页面,创建页面

 

列表页面注意事项:

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

{{models−>appends(

input)->links()}}

 

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

复制代码

 
  1. {{ Form::open(array(
  2. 'id' => "delete_{$model->id}",
  3. 'url' => action($controller . '@destroy', $model->id),
  4. 'class' => 'dropdown-toggle')) }}
  5. {{ Form::hidden('_method', 'DELETE') }}
  6. {{ Form::close() }}

复制代码

 

 

其实自己写DELETE也行,就是在From表单中多传递一个_method隐藏域

 

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

复制代码

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

复制代码

 

编辑页面和创建页面

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

 

复制代码

 
  1. <form class="form-horizontal"
  2. role="form"
  3. action="{{action($controller . "@update", $model->id)}}" method='POST'>
  4. <input type="hidden" name="_method" value="PUT">
  5. @foreach ($fields_edit as $field => $field_info)
  6. <div class="form-group">
  7. <label class="col-sm-2 control-label">{{$field_info['show']}}</label>
  8. <div class="col-sm-10">
  9. <input name="{{$field}}" type="text" class="form-control" placeholder="" value="{{$model->$field}}">
  10. </div>
  11. </div>
  12. <div class="line line-dashed line-lg pull-in"></div>
  13. @endforeach
  14. <div class="col-sm-4 col-sm-offset-2">
  15. <button type="submit" class="btn btn-primary">提交</button>
  16. </div>
  17. </form>

复制代码

 

 

记得resource中更新的操作是要使用PUT方式,删除的操作要使用DELETE方式。

至于view的模版,我这里使用的是一款叫notebook的模版,它是基于bootstrap的,你也可以使用其他更好看的模版来写。

 

好了,至此这么个快速搭建CURD的结构就完成了。现在可以在运营人员给需求的时候,很牛逼地说,等我一分钟,我就给你一个世界~~

laravel改变搜索的对象变数组

路径  App/http/config/database.php

找到:  'fetch' => PDO::FETCH_CLASS,
改成:  'fetch' => PDO::FETCH_ASSOC,

后记

其实回想下,这整个结构不算复杂。配置即一切的思想能解决很多问题。但是依赖配置的路子最怕的是几个事情:

1 配置文件过于复杂。(如果你的配置文件过于复杂,已经超过了敲代码本身需要了解的东西,那么这个配置项的学习成本就太太太高了)

2 配置字段语意不清。(配置的字段名字和意思不对,字段名和变量名一样重要!)

 

当然这个就是个初步,改进的几个点还有

1 所有字段都使用input标签,需要在配置中加入其它标签类型

2 是不是考虑view中所有的东西都使用laravel自带的form对应字段?

发表评论: