Laravel 4 初级教程之视图、命名空间、路由

1. 视图分离与嵌套

在 learnlaravel 文件夹下运行命令:

php artisan generate:view admin._layouts.default

这时候generator插件帮我们创建了app/views/admin/_layouts/default.blade.php 文件,将内容修改为:

<!doctype html><html><head>  <meta charset="utf-8">  <title>Learn Laravel 4</title>  @include('admin._partials.assets')</head><body><div class="container">  <div class="navbar navbar-inverse navbar-fixed-top">  <div class="navbar-inner">    <div class="container">      <a class="brand" href="{{ URL::route('admin.pages.index') }}">Learn Laravel 4</a>      @include('admin._partials.navigation')    </div>  </div></div><hr>  @yield('main')</div></body></html>

这就是视图文件,MVC中的V。视图需要仔细讲一下。

views文件夹为视图文件夹,视图文件夹可以嵌套,就像我上面一样创建了admin/_layout嵌套文件夹,在里面创建了一个叫default.blade.php的文件,那么以后我们在Laravel内任何地方要用到这个视图的时候,他就叫admin._layouts.default。

我们看到,上面代码的第七行是“@include('admin._partials.assets')”,根据上面我们刚刚了解的知识,这表示载入了另外一个文件。blade是Laravel的模板引擎,此处的 @include 表示直接把那个文件的所有代码带入进来放到这里,变成当前视图的一部分。

注意看第25行“@yield('main')”,这表示什么呢?这个有点复杂,我们稍后再讲。

2. 权限验证

Laravel支持标准HTTP认证,但是在此处我们需要构建blog系统,所以我们将编写完善的管理员登陆系统,从页面登录。

用命令行创建app/views/admin/auth/login.blade.php文件,代码如下:

@extends('admin._layouts.default')@section('main')  <div id="login" class="login">    {{ Form::open() }}      @if ($errors->has('login'))        <div class="alert alert-error">{{ $errors->first('login', ':message') }}</div>      @endif      <div class="control-group">        {{ Form::label('email', 'Email') }}        <div class="controls">          {{ Form::text('email') }}        </div>      </div>      <div class="control-group">        {{ Form::label('password', 'Password') }}        <div class="controls">          {{ Form::password('password') }}        </div>      </div>      <div class="form-actions">        {{ Form::submit('Login', array('class' => 'btn btn-inverse btn-login')) }}      </div>    {{ Form::close() }}  </div>@stop

大家应该注意到了前两行:

@extends('admin._layouts.default')@section('main')

这代表什么?实际上,以后我们会了解到,在controller中调用view的时候,调用的只是这个login.blade.php文件,第一行表示,此视图是admin._layouts.default的子视图,这时blade引擎会把这个视图也载入进来,怎么组装呢?这时候下面那个@section('main')就该出场了,被它包裹的代码将会直接放到admin._layouts.default中的@yield('main')中。section和yield可以任意搭配,只要两个视图之间有调用关系,他们就可以这样用,非常灵活。

写到这里大家可能有个疑问,为什么示例代码里空行那么多?这一点就是个人经验了。blade引擎的所有标签都会在视图编译时用正则处理,引擎本身有一个问题,算不上bug,就是换行符会被处理掉,导致前后行和这一行都紧紧地挤在一起,在前端浏览器中“查看源代码”时,比较不清晰,前后加上空行可以解决这个问题。当然这可能是一个自动的“压缩”特性,不再深入讨论。

增加控制器文件app/controllers/admin/AuthController.php,这时候有人就说了,这我知道,哈哈,运行

“php artisan generate:controller admin.AuthController”

这个想法是对的,但你运行一下试试?会直接在app/controllers目录下创建一个“admin.AuthController.php”文件,有人又说,那我用“admin/AuthController”总行了吧,你试一下?也不行。所以我们要先在app/controllers 下手动创建 admin 文件夹,这时候,再命令行输入:

php artisan generate:controller admin/AuthController

这样就可以了。接下来改写AuthController.php 的内容为:

<?phpnamespace App\Controllers\Admin;use Auth, BaseController, Form, Input, Redirect, Sentry, View;class AuthController extends BaseController {  /**   * 显示登录页面   * @return View   */  public function getLogin()  {    return View::make('admin.auth.login');  }  /**   * POST 登录验证   * @return Redirect   */  public function postLogin()  {    $credentials = array(      'email'    => Input::get('email'),      'password' => Input::get('password')    );    try    {      $user = Sentry::authenticate($credentials, false);      if ($user)      {        return Redirect::route('admin.pages.index');      }    }    catch(\Exception $e)    {      return Redirect::route('admin.login')->withErrors(array('login' => $e->getMessage()));    }  }  /**   * 注销   * @return Redirect   */  public function getLogout()  {    Sentry::logout();    return Redirect::route('admin.login');  }}

这就是我们登录、注销的控制器,MVC中的C。接下来我将讲解命名空间,这是Laravel的基础,或者说是composer的基础,是整个Laravel教程中的重点、难点,希望大家锱铢必较,任何不懂都不要放过。可以到phphub论坛或者golaravel论坛相应帖子下面提问,或者直接发帖提问。

我们首先观察这个文件的位置,它位于 app/controllers/admin 目录下,这有什么不同呢?在其他框架如 CI 中,子文件夹直接加上文件夹名就可以直接调用到了,虽然最多只能有一层。而Laravel没有这么简单,涉及到了PHP的命名空间。

1. composer 支持 PSR-0 及 PSR-4 标准,标准规定 PHP 包以命名空间为区分,向外提供服务,所有暴露出来的类都应该在 \作者名\包名 命名空间下,例如 \lui\MFFC\Mail 类。这样,哪怕是名称一样的包只要是不同作者也可以在https://packagist.org/上共存,供大家使用。

2. 命名空间可以类比成 Linux 系统中的 目录,在任何目录下都可以直接使用文件名打开当前目录下的所有文件和可执行程序,如果需要打开其他目录下的文件,就需要使用绝对路径或者相对路径。

3. 大家可能在许多其他教程中见到过controller头部没有 namesapce 申明,更没有那一堆的 use xxx,像这个文件https://github.com/cecoo/laravel4demo/blob/master/app/controllers /BlogController.php。这个文件在第8行直接使用了 Blog 这个类,这是为什么呢?

因为他们都已经在 learnlaravel 这个 composer 应用的配置文件中声明为自动加载了,而他们没有在顶部声明他们所在的命名空间,这样就会被自动加为顶级命名空间。这个配置文件是 composer.json,对象配置项为autoload 下的classmap 项。这个声明会让 Composer 在生成自动载入文件的时候,自动扫描该文件下所有的类以及所有子文件夹中的类,只要没有声明特定的命名空间,将会被自动加载为顶级空间。【之前表述有误,特此更正!】

关于命名空间更多详情,可以参考 【PHP 命名空间 入门】。

OK,到目前为止我们的MVC三元素已经集齐了,那接下来该做什么了呢?配置路由。这里的路由并不是家里用的无线路由 :-D,而是 用户请求的URL到控制器某个方法的转换,function是PHP中代码段的最小单位,所以用户请求的一个路径,如 http://ooxx.com/fuck/me ,这条URL打给路由之后,路由就会去解析,应该调用哪个function,最终返回结果给用户。

Laravel的路由采用闭包的方式返回结果,在app/routes.php 中增加下列内容:

Route::get('admin/logout', array('as' => 'admin.logout', 'uses' => 'App\Controllers\Admin\AuthController@getLogout'));Route::get('admin/login', array('as' => 'admin.login', 'uses' => 'App\Controllers\Admin\AuthController@getLogin'));Route::post('admin/login', array('as' => 'admin.login.post', 'uses' => 'App\Controllers\Admin\AuthController@postLogin'));Route::group(array('prefix' => 'admin', 'before' => 'auth.admin'), function(){    Route::any('/', 'App\Controllers\Admin\PagesController@index');    Route::resource('articles', 'App\Controllers\Admin\ArticlesController');    Route::resource('pages', 'App\Controllers\Admin\PagesController');});

前三条的意思是hold住两个get请求和一个post请求,下面是一个路由组,规定了一个前缀admin,增加了一个过滤器,auth.admin,内部有一个能同时适应get和post请求的‘/'路径,其完整路径是 http://ooxx.com/admin/。剩下的两个资源控制器本质上只是一种简写,URL和控制器类中的方法名的对应表见 资源控制器。

上面说的那个过滤器 auth.admin,是Laravel提供的一个请求过滤器,这个文件就在路由文件的旁边,app/filters.php,在文件末尾增加:

Route::filter('auth.admin', function(){ if ( ! Sentry::check()) {  return Redirect::route('admin.login'); }});

这样我们的权限验证就完成了。上面的代码意思是,在进入这个路由组中的任何一条路由之前,会先过一遍 auth.admin这个filter,这个filter会调用Sentry::check(),如果为false,将会进入if代码块,将用户的请求跳转到 命名路由‘admin.login',命名路由文档。从这个命名路由的名称大家也能看出来,就是跟访客说:傻逼,干啥呢,登录去~

这里的“命名路由”功能是为了模仿 Ruby On Rails 的 “link_to”到对象 的路由绑定功能,无奈PHP上传即部署无守护进程的特性,使得我们没法维护一个全量代码的路由表,没法像Rails那样实现 资源路由-资源对象-路由调用 三者绑定的功能,只能搞出一个半成品命名路由,人为地解决了当调整 /people 到 /human 时,要求名称改变而功能不变,同时要求代码自适应的需求。

这时候,我们就可以尝试访问我们的项目了。推荐配置Apache将一个端口指向learnlaravel这个项目的public目录下,即项目通过 http://127.0.0.1:8080 这样的地址访问,十分不建议从子文件夹访问。如果你不会,可以运行

php artisan serve

启动PHP5.4的内建HTTP服务器。地址将会是http://localhost:8000,注意此处 127.0.0.1 不可以访问。

下面,我们在浏览器中访问 /admin,注意URL会自动跳转到 /admin/login,这说明我们的filter起作用了,但你可能得到以下页面

这说明代码出错了。接下来我们修改 app/config/app.php 第一项为:

'debug' => true,

刷新页面,错误提示出来了!有没有感觉Laravel4.2的错误提示很好看啊,确实不错,但我觉得没有4.1之前的好看 :-D。我得到了如下错误:

说“App\Controllers\Admin\AuthController”这个类未找到,这是为什么呢?这个文件明明有啊。

这就涉及到了另一个问题,Laravel中的autoload问题。Laravel基于命名空间,它只会自动加载所有顶级命名空间的类,就是说我们新增的这个控制器类不是在顶级命名空间下,所以就需要告诉Laravel,我这个类是存在的,怎么告诉它呢?运行

composer dump-autoload

可以了,刷新页面,他告诉我

View [admin._partials.assets] not found.

这个确实是,我们还没建立这个文件呢。建立一个空文件即可,如果是用generator建的话,别忘了把里面默认的内容删掉哦。再刷新页面,如果还有问题,我相信这个问题你可以自己解决。

OK,一个丑的一逼的页面出现了,为什么它这么丑?(鸽子为什么这么大?)因为我们没有引入任何css和js文件,甚至连导航栏的html都不完整。这不要紧,来,按照我github上的代码,自己复制到相应文件中吧。另外,非常重要的一点,把我的项目中的public文件下的 js 和 css 两个文件夹完全复制到你们的public文件夹中。

再刷新,如果你看到以下页面,说明你成功了!

3. 尝试登录

用seed新增一名管理员,顺便新增一个管理员组。新建app/database/seeds/SentrySeeder.php,内容为:

<?phpclass SentrySeeder extends Seeder {  public function run()  {    DB::table('users')->delete();    DB::table('groups')->delete();    DB::table('users_groups')->delete();    Sentry::getUserProvider()->create(array(      'email'      => 'oo@xx.com',      'password'   => "ooxx",      'first_name' => 'OO',      'last_name'  => 'XX',      'activated'  => 1,    ));    Sentry::getGroupProvider()->create(array(      'name'        => 'Admin',      'permissions' => ['admin' => 1],    ));    // 将用户加入用户组    $adminUser  = Sentry::getUserProvider()->findByLogin('oo@xx.com');    $adminGroup = Sentry::getGroupProvider()->findByName('Admin');    $adminUser->addGroup($adminGroup);  }}

给app/database/seeds/DatabaseSeeder.php 新增一行:

$this->call('SentrySeeder');

然后运行:

php artisan db:seed

成功以后,进数据库就会发现,users、groups、users_groups表均新增了一行。但是,articles和pages表也分别新增了10行,对,seed就是这么蠢萌^_^

让我们来尝试登录!如果你得到:

Class App\Controllers\Admin\PagesController does not exist

这说明你成功了!

(0)

相关推荐

  • Laravel框架路由配置总结、设置技巧大全

    基本路由 您的应用程序的绝大多数路由将在 app/routes.php 文件中定义.Laravel 中最简单的路由由一个 URI 和一个闭包调用组成. 基本 GET 路由 复制代码 代码如下: Route::get('/', function() { return 'Hello World'; }); 基本 POST 路由 复制代码 代码如下: Route::post('foo/bar', function() { return 'Hello World'; }); 注册一个路由以响应所有 HT

  • 跟我学Laravel之路由

    基本路由 应用中的大多数路都会定义在 app/routes.php 文件中.最简单的Laravel路由由URI和闭包回调函数组成. 基本 GET 路由 复制代码 代码如下: Route::get('/', function() {     return 'Hello World'; }); 基本 POST 路由 复制代码 代码如下: Route::post('foo/bar', function() {     return 'Hello World'; }); 注册一个可以响应任何HTTP动作

  • 修改Laravel5.3中的路由文件与路径

    前言 大家可能没有注意到, 在 Laravel 4 以及更老版本中, 路由逻辑是性能上的一个瓶颈--特别是对于有很多路由定义的应用而言. 一个只有几百条路由定义的 Laravel 站点, 框架光注册路由就需要半秒多的时间. 不过以后不用担心这个问题了, 因为 Laravel 5 引入了 路由缓存(route caching), 可以大大优化路由的性能(闭包方式定义的路由不能缓存, 所以该把所有的闭包路由定义都移到控制器中了). 1.回顾Laravel 5.2中路由的修改 在 Laravel 5.

  • laravel中命名路由的使用方法

    laravel提供了很多magic方法来,先来讲讲命名路由的使用,有两种方法非常便捷. 命名路由让你可以更方便的为特定路由生成 URL 或进行重定向.你可以使用 as 数组键指定名称到路由上 1.第一种:通过route路由中的as关键字来实现 Route::get('api/user',['as'='web.user'],'messageController@userInformation'); 2.第二种:通过Route的magic方法name来实现命名路由 Route::get('api/u

  • ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼

    前言 读过一篇关于Zend Framework2的技术文章<ZF2多级树形路由Route配置实例>,是介绍路由配置的.我觉得很有意思,这是的需求: /user对应用户列表页面 /user/:user_id对应用户的个人主页,比如 /user/AlloVince 就对应AlloVince用户的个人主页 /user/:user_id/blog/对应用户的博客列表页面,比如 /user/AlloVince/blog 就会列出AlloVince写过的Blog /user/:user_id/blog/:

  • Laravel路由设定和子路由设定实例分析

    本文实例讲述了Laravel路由设定和子路由设定方法.分享给大家供大家参考,具体如下: 普通路由设定 1.路由(routes.php)代码: Route::get('min','MinController@index'); min:为路由名称,即url中输入的,如127.0.0.1/min  这里的min就是上面对应的min MinController为文件名(类名) @index为方法名 2.控制器 namespace App\Http\Controllers; use App\Http\Co

  • Laravel最佳分割路由文件(routes.php)的方式

    前言 Laravel 的路由功能很强大,默认都是定义在 routes.php 文件中,随着项目越来越大,我们需要的定义的路由越来越多,想象一下,如果几百上千个路由都定义在一个文件中,如何去维护?也许还有不同的人都在同一个文件定义路由,这就造成了冲突,因此我们需要分割 routes.php 文件. 下面介绍一种很优雅的方式. 在 app/Providers/RouteServiceProvider.php 的 map 方法中可以如下定义: public function map(Router $r

  • Laravel 5框架学习之路由、控制器和视图简介

    查看 app/Http/routes.php 复制代码 代码如下: Route::get('/', 'WelcomeController@index'); @是一个界定符,前面是控制器,后面是动作,表示当用户请求url / 的时候,执行控制器 WelcomeController 中的 index 方法 复制代码 代码如下: app/http/controllers/welcomecontroller.php public function index() { return view('welco

  • Laravel 4 初级教程之视图、命名空间、路由

    1. 视图分离与嵌套 在 learnlaravel 文件夹下运行命令: php artisan generate:view admin._layouts.default 这时候generator插件帮我们创建了app/views/admin/_layouts/default.blade.php 文件,将内容修改为: <!doctype html><html><head>  <meta charset="utf-8">  <title

  • Laravel 4 初级教程之安装及入门

    0. 默认条件 本文默认你已经有配置完善的PHP+MySQL运行环境,懂得PHP网站运行的基础知识.跟随本教程走完一遍,你将会得到一个基础的包含登录的简单blog系统,并将学会如何使用一些强大的Laravel插件和composer包(Laravel插件也是composer包). 软件版本:PHP 5.4+,MySQL 5.1+ 1. 安装 许多人被拦在了学习Laravel的第一步,安装.并不是因为安装教程有多复杂,而是因为[众所周知的原因].在此我推荐一个composer全量中国镜像:http:

  • Laravel 4 初级教程之Pages、表单验证

    1. 构建Pages管理功能 运行命令: php artisan generate:controller admin/PagesController 修改PagesController.php 内容: <?phpnamespace App\Controllers\Admin;use Page;use Input, Notification, Redirect, Sentry, Str;use App\Services\Validators\PageValidator;class PagesCon

  • Laravel框架实现多个视图共享相同数据的方法详解

    本文实例讲述了Laravel框架实现多个视图共享相同数据的方法.分享给大家供大家参考,具体如下: 最近在用Laravel写一个cms,还没有完成,但是也遇到了许多难点,比如cms后台每个视图都要展示相同的导航菜单数据. 环境: PHP 7.1 Apache 2.4 MySQL 5.7 Laravel 5.4 传统方法 假设使用传统的方法,应该是在每个控制器中都调用数据,然后把数据都塞给视图. $menu = DB::table('menu')->get(); return view('xx',[

  • laravel通过a标签从视图向控制器实现传值

    这是我的laravel框架用到的参数 <a href="admin-index-control_del?id={{$val->admin_id}}" rel="external nofollow" >删除</a> 这是标准的写法 <a href="路由?id=要传的值" rel="external nofollow" >删除</a> // 其实这是要传的值是随意写的,比如说

  • Zend Framework教程之视图组件Zend_View用法详解

    本文实例讲述了Zend Framework教程之视图组件Zend_View用法.分享给大家供大家参考,具体如下: Zend_View是Zend Framework的视图组件,MVC中的视图层. Zend_View也是应用的直接对用户展示的页面.这里介绍一下Zend_View的实现类,以及如何和Controller结合在一起的. View的实现 Zend_View的实现主要是通过如下目录的类实现: root@coder-671T-M:/library/Zend# tree | grep View.

  • Django REST framework 视图和路由详解

    DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Django中的request从request.GET中获取URL参数,从request.POST中取某些情况下的POST数据. 在APIView中封装的request,就实现了请求数据的解析: 对于GET请求的参数我们通过request.query_params来获取. 对于POST请求.PUT请求的

  • Laravel 前端资源配置教程

    最近在学Laravel,遇到前端资源加载的问题,记录一下. 一.前端共用资源的配置 1. webpack.mix.js //一般不太更动,透过以下两个档案讲所需资源加载. mix.js('resources/assets/js/app.js', 'public/js') .sass('resources/assets/sass/app.scss', 'public/css'); 2. npm 命令安装前端套件资源(以jquery-ui为例) npm install jquery-ui --sav

  • AngularJS入门教程二:在路由中传递参数的方法分析

    本文实例讲述了AngularJS在路由中传递参数的方法.分享给大家供大家参考,具体如下: 我们不仅可以在控制器中直接定义属性的值,比如: app.controller('listController',function($scope){ $scope.name="ROSE"; }); AngularJS还提供了传递参数的功能,目前我接触到的一种方式是从视图中传参: <!--首页html--> <li><a href="#/user/18"

  • AJAX初级教程之初识AJAX

    从刚刚接触B/S开发,就耳闻AJAX技术,但一直处于模棱两可的状态,大道理明白,一到动手就傻眼了. AJAX仿佛就是深不可测的技术,成为B/S学习过程中的一个阴影. 直到前些日子,小菜才真正开始AJAX实践,真正动手了才发现,AJAX并没有那么困难,如果不考虑AJAX的变型应用,只考虑AJAX基本应用,它还是相当简单的,过于复杂的理论阻碍了我们动手的积极性. 因此,本系列教程将从实用的角度出发,以最快的速度让读者掌握基本的AJAX应用,以最直接的方式展示AJAX技术. 为了更好的阅读本系列教程,

随机推荐