zoukankan      html  css  js  c++  java
  • PHP Laraval系列之文件结构、Artisan、路由、控制器

    一、文件结构

    打开项目代码之后,我们就可以在 Sublime的左侧边栏里清楚的看到 Laravel源码的结构:

    下面简单介绍一下 Laravel源码里每个文件夹都是用来做什么的,了解结构才能更好地进行后续的开发。

    文件夹 介绍
    app 网站的业务逻辑代码,例如:控制器/模型/路由等
    bootstrap 框架启动与自动加载设置相关的文件
    config 网站的各种配置文件
    database 数据库操作相关的文件
    public 网站的对外文件夹,入口文件和静态资源(CSS,JS,图片等)
    resources 前端视图文件和原始资源(CSS,JS,图片等)
    storage 编译后的视图、基于会话、文件缓存和其它框架生成的文件
    tests 自动化测试文件
    vendor Composer 依赖文件
    app/Http/Controllers 存放控制器
    app/Http/Middleware 存放中间件
    resources/views 视图路径 blade视图

    除了上述文件夹,根目录下有些文件也比较常用:

    文件 介绍
    .env 环境配置文件
    .env.example .env 文件的一个示例
    .gitignore git 的设置文件,制定哪些文件会被 git忽略,不纳入文件管理
    composer.json 网站所需的 composer扩展包
    composer.lock 扩展包列表,确保这个网站的副本使用相同版本的扩展包
    gulpfile.js GULP 配置文件( GULP 后边会学到)
    package.json 网站所需的 npm包
    readme.md 网站代码说明文件
    app/Http/routes.php 网站的大多数路由都定义在该文件中,该文件将会被AppProvidersRouteServiceProvider类加载。

    有个简单的了解就好,在后续开发过程中会通过实践对 Laravel 的结构进行更深的理解。

    二、编写第一行代码

    下面就让我们编写第一行代码,Hello World!
    首先我们需要定位到我们之前看到过的欢迎页面,这个页面的位置是:“`

    `resources/views/welcome.blade.php`

    打开这个文件,按 ctrl+f 搜索 Laravel 5 可以定位到代码具体位置
    修改为 Hello world 然后记得 ctrl+s 保存。

        <body>
            <divclass="container">
                <divclass="content">
                    <divclass="title">My first Demo</div>
                </div>
            </div>
        </body>
    

    现在打开浏览器,在地址栏输入 localhost 可以看到如下效果:
    这里写图片描述

    很简单,我们的第一行代码就完成了:)

    三、初始强大的 Artisan

    (一) 什么是Artisan呢?

    熟悉 linux 的朋友都知道,我们平时的创建/删除文件等常用操作都可以在命令行里来完成,Artisan 就相当于 Laravel 为我们独家定制的一个命令行工具,提供了很多实用的命令,可以用来快速生成 Laravel 开发中常用的一些文件并完成相关的配置。

    (二) 常用 Artisan 命令

    使用命令行进入我们的代码根目录:

    cd ~/Code/myweb

    然后,执行 php artisan list 可以查看常用 artisan 命令:

    php artisanlist

    如下图,可以看到显示出了很多的 artisan 命令:
    这里写图片描述
    下面列出最常用的一些命令,使用方法就像上面的php artisan list一样,先有个简单了解就好,我们在后面的开发中会多次使用到这些命令:

    命令 说明
    php artisan key:generate 生成 App Key
    php artisan make:controller 生成控制器
    php artisan make:model 生成模型
    php artisan make:policy 生成授权策略
    php artisan make:seeder 生成 Seeder文件
    php artisan migrate 执行迁移
    php artisan migrate:rollback 回滚迁移
    php artisan migrate:refresh 重置数据库
    php artisan db:seed 填充数据库
    php artisan tinker 进入 tinker环境
    php artisan route:list 查看路由列表

    在开发过程中,应该尽量使用 artisan 命令,这样不仅可以提高开发效率,还可以减少bug。
    在后续的实验中,我们也会多次使用 artisan 命令。

    四、路由

    我们学习 Laravel 基础功能之一:路由。

    (一) 什么是路由呢?

    在浏览器中输入http://blog.csdn.net/u014665013我们可以访问实验楼网站的首页,如果我们输入http://blog.csdn.net/u014665013/article/details/77588281呢?我们会来到博客的文章页面。
    这就是路由了,即路由系统会对用户输入的 URL 地址 进行解析,然后分配不同的工作,有点像路由器。
    路由不仅可以美化 URL,还可以便于用户记忆等。
    那么 Laravel 是怎么处理 url 的呢?
    首先,我们打开项目代码,找到路由设置文件,文件位置:

    app/Http/routes.php

    我们可以看到,当前 routes.php 文件中只有如下几行代码,这几行代码都实现了哪些功能呢?

    Route::get('/', function(){
        return view('welcome');
    });

    这几行代码表示,当我们输入的 url为 网址 + ‘/’,也就是localhost/ 时,为我们返回 欢迎页,也就是之前我们写 Hello World 的页面。
    注意:在输入网址的时候,localhost和 localhost/是一样的。
    我们可以尝试将这段代码修改一下:

    Route::get('welcome', function(){
        return view('welcome');
    });

    然后我们打开浏览器,再输入localhost,我们会发现,报错了!
    这个错误的大概意思是,没有找到处理该 url 的办法,因为我们没有定义 ‘/’ 这条路由。
    现在我们输入 localhost/welcome 并刷新页面,我们看到了熟悉的页面原来的征程welcome界面
    通过上面的尝试,你是否对路由有了一个简单的认识?
    下面我们来系统的学习一下 Laravel 的路由。

    (二) 基本路由

    网站的大多数路由都定义在 app/Http/routes.php 文件中,该文件将会被 AppProvidersRouteServiceProvider 类加载。最基本的 Laravel 路由仅接受 URI 和一个闭包,下面我们再定义两条路由。

    app/Http/routes.php

    <?php
    /*
    |--------------------------------------------------------------------------
    | Application Routes
    |--------------------------------------------------------------------------
    |
    | Here is where you can register all of the routes for an application.
    | It's a breeze. Simply tell Laravel the URIs it should respond to
    | and give it the controller to call when that URI is requested.
    |
    */
    
    Route::get('welcome', function(){
        return view('welcome');
    });
    
    Route::get('/', function(){
        return'Index Page';
    });
    
    Route::get('/help', function(){
        return'Help Page';
    });

    然后我们分别访问 localhost 和 localhost/help 可以看到返回了对应的信息:
    这里写图片描述

    (三) 路由动作

    我们知道,一个url请求可能有多种类型,除了常用的GET,还可能有 POST、PUT、DELETE 等类型的请求。
    对应的处理方法如下:

    Route::post('/foo', function(){
        //该路由将匹配 post方法的 '/foo' url
    });
    
    Route::put('/foo', function(){
        //该路由将匹配 put方法的 '/foo' url
    });

    除此之外,还可以用 match 来同时处理多种类型的请求:

    Route::match(['get', 'post'],'/foo', function(){
        // 该路由将匹配 get 和 post 方法的 'foo' url
    });

    甚至,还可以使用 any 来同时处理所有类型的请求:

    Route::any('/foo', function(){
        // 该路由将匹配所有类型的 'foo' url
    });

    (四) 路由参数

    1.基础的路由参数

    有时候你可能需要从 URL 中获取一些参数,比如姓名、年龄等。
    下面打开 routes.php,加入一个带参路由。
    app/Http/routes.php

    <?php
    Route::get('name/{name}', function($name){
        return'I`m '.$name;
    });

    然后我们如果访问 localhost/name/Tom 我们可以看到网页返回了对应的信息:
    这里写图片描述
    如果试图访问 localhost/name 将会出现错误:

    我们也可以定义多个参数:
    app/Http/routes.php

    <?php
    Route::get('hello/{name?}', function($name = null){
        return'Hello! '.$name;
    });

    这时你访问 localhost/hello 将不会报错,只是参数是空值。

    你可以为该可选参数设定一个默认值,当 url 未传参时,将显示默认值。
    app/Http/routes.php

    <?php
    Route::get('hello/{name?}', function($name = 'Tom'){
        return'Hello! '.$name;
    });

    这时访问 localhost/hello 将返回默认的信息,如下图:
    这里写图片描述
    如果访问localhost/hello/John 将会显示参数,如下图:
    这里写图片描述

    (五) 命名路由

    所谓命名路由,就是给路由起个名字,这样我们就可以通过这个名字获取到该条路由的相关信息,也更利于后期维护。
    建议在开发过程中给每个路由命名,使用下面两种方式都可以为一个路由命名。

    Route::get('foo', ['as' => 'foo', function(){
        //方法一
    }]);
    
    Route::get('foo', function(){
        //方法二
    })->name('foo');

    (六) 路由群组

    路由群组允许你共用路由属性,例如:中间件、命名空间等,你可以利用路由群组统一为多个路由设置共同属性,而不需在每个路由上都设置一次。共用属性被指定为数组格式,当作Route::group方法的第一个参数。
    下面通过几个常用样例来熟悉这些特性。

    1.为路由群组添加共用的中间件

    至于什么是中间件,在后面的实验中会专门的学习。

    Route::group(['middleware' => 'auth'], function(){
        Route::get('/', function()    {
            // 该路由将使用 Auth 中间件
        });
    
        Route::get('name', function(){
            // 该路由也将使用 Auth 中间件
        });
    });
    2.为路由群组添加共用的命名空间

    什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。
    你可以简单的把命名空间理解为,当前文件所在的位置。

    Route::group(['namespace' => 'Admin'], function()
    {
        // 控制器在「AppHttpControllersAdmin」命名空间
    
        Route::group(['namespace' => 'User'], function()
        {
            // 控制器在「AppHttpControllersAdminUser」命名空间
        });
    });

    3.为路由群组添加共用的前缀

    你可能有一系列路由都具有一个相同的前缀,比如:

    Route::get('user/name', function(){
        //
    });
    Route::get('user/age', function(){
        //
    });
    Route::get('user/introduction', function(){
        //
    });

    这时你就可以用路由群组来简化代码:

    Route::group(['prefix' => 'user'], function(){
        Route::get('name', function()    {
            //
        });
        Route::get('age', function()    {
            //
        });
        Route::get('introduction', function()    {
            //
        });
    });

    路由群组也可以添加参数:

    Route::group(['prefix' => 'user/{id}'], function(){
        Route::get('name', function($id)    {
            // 符合 'user/{id}/name' URL 
        });
        Route::get('age', function($id)    {
            // 符合 'user/{id}/age' URL 
        });
    });

    (七) 查看路由

    我们可以使用url(‘foo’)函数来生成完整的 URL,例如,我们这样修改一下代码:
    app/Http/routes.php

    <?php
    Route::get('/help', function(){
        return url('/help');
    });

    然后,访问localhost/help,我们可以看到返回了完整的 URL 信息:
    这里写图片描述

    我们还可以使用命名路由函数route(‘foo’)来生成完整的 URL 信息。
    app/Http/routes.php

    <?php
    Route::get('/help', function(){
        return route('foo');
    });
    
    Route::get('/foo', function(){
        //
    })->name('foo');

    然后,访问 localhost/help,我们可以看到返回了 foo 路由的完整 URL 信息:

    (八) 正则表达式限制路由

    你可以使用 where 方法来限制参数的格式。where 方法接受参数的名称和正则表达式。
    app/Http/routes.php

    <?php
    Route::get('hello/{name?}', function($name = 'Tom'){
        return'Hello! '.$name;
    })->where('name','[A-Za-z]+');

    然后如果访问 localhost/hello/John 这样的 url 就会正确显示。
    如果访问 localhost/hello/55 这样的 url 将会报错,如下图:
    这里写图片描述
    同样,也可对多个参数都设置正则验证:
    app/Http/routes.php

    <?php
    Route::get('name/{name}/age/{age}', function($name, $age){
        return'I`m '.$name.' ,and I`m '.$age;
    })->where(['name' => '[A-Za-z]+', 'age' => '[0-9]+']);

    如果你想对所有的路由参数都加上某种限制,需要在RouteServiceProvider 的 boot 方法里定义这些限制。

    /**
     * 定义你的路由模型绑定,模式过滤器等。
     *
     * @param  IlluminateRoutingRouter  $router
     * @return void
     */
    publicfunctionboot(Router $router)
    {
        $router->pattern('id', '[0-9]+');
    
        parent::boot($router);
    }

    五、控制器

    本次实验我们学习控制器(Controller)。

    (一) 准备工作

    首先,我们先创建一个路由,顺便再练习一下上次试验的内容,打开routes.php文件。
    app/Http/routes.php

    <?php
    Route::get('/', function(){
        return view('welcome');
    });
    Route::get('user/name', function(){
        return'Name Page';
    });

    当我们访问网站地址 localhost/user/name 时,会返回 ‘NamePage’.

    但是我们知道,实际的网站功能不可能这么单调,我们需要更多的返回信息和操作,显然把大量的处理代码写在这里是不合适的,这时候就要用到Controller。
    现在我们对上面的代码进行更改:

    <?php
    Route::get('/', function(){
        return view('welcome');
    });
    
    Route::get('/user/name', 'UserController@name');

    这段代码的意思就是,当用户访问 ‘localhost/user/name’ 这个 URL 的时候,调用 UserController 这个控制器的 name 方法来处理请求。也就是说,将原来的闭包函数放到了一个单独的文件中。
    我们可以将有共同特征的路由处理函数放到一个共同的控制器中,例如下面这种方式:

    Route::get('/user/name', 'UserController@name');
    Route::get('/user/age', 'UserController@age');
    Route::get('/user/introduction', 'UserController@introduction');

    三条不同的路由的处理函数放在了同一个控制器(用户控制器)的三个不同的方法内。
    下面我们通过几个简单的例子来体会一下 Controller是怎么工作的。

    (二) 基础控制器

    控制器一般存放在 app/Http/Controllers 目录下,下面是一个基础控制器的例子,先来简单感受一下控制器文件的结构:

    <?php
    namespaceAppHttpControllers;
    useAppUser;
    useAppHttpControllersController;
    classUserControllerextendsController
    {
        /**
         * 显示指定用户的个人数据。
         *
         * @param  int  $id
         * @return Response
         */
        public function show($id)
        {
            return view('user.profile', ['user' => User::findOrFail($id)]);
        }
    }

    所有 Laravel 控制器都应继承基础控制器类,它包含在Laravel 的默认安装中。该基础类提供了一些便捷的方法,例如 middleware 方法(middleware 是中间件 后边会讲解),该方法可以用来将中间件附加在控制器行为上。
    然后你就可以通过一个路由把请求引入到这个控制器文件来,像下面这样:

    Route::get('user/{id}', 'UserController@show');

    现在,当请求和此特定路由的 URI 相匹配时,UserController 类的 show 方法就会被运行。当然,路由的参数也会被传递至该方法。
    现在,让我们动手实践来感受一下控制器。
    首先用 artisan 命令创建一个新的控制器,打开命令行,进入代码根目录:

    cd ~/Code/myweb

    然后运行 artisan命令生成控制器:

    php artisan make:controller UserController

    然后转到 app/Http/Controllers目录下,可以看到刚刚创建的 UserController.php。打开这个文件:

    <?php
    
    namespaceAppHttpControllers;
    
    useIlluminateHttpRequest;
    
    useAppHttpRequests;
    useAppHttpControllersController;
    
    classUserControllerextendsController
    {
        /**
         * Display a listing of the resource.
         *
         * @return IlluminateHttpResponse
         */
        public function index()
        {
            //
        }
    
        /**
         * Show the form for creating a new resource.
         *
         * @return IlluminateHttpResponse
         */
        public function create()
        {
            //
        }
    
        /**
         * Store a newly created resource in storage.
         *
         * @param  IlluminateHttpRequest  $request
         * @return IlluminateHttpResponse
         */
        public function store(Request $request)
        {
            //
        }
    
        /**
         * Display the specified resource.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        public function show($id)
        {
            //
        }
    
        /**
         * Show the form for editing the specified resource.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        public function edit($id)
        {
            //
        }
    
        /**
         * Update the specified resource in storage.
         *
         * @param  IlluminateHttpRequest  $request
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        public function update(Request $request, $id)
        {
            //
        }
    
        /**
         * Remove the specified resource from storage.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        public function destroy($id)
        {
            //
        }
    }

    我们可以看到,Laravel 为我们生成了一些默认的代码,仔细观察可以发现是 7 个空方法,分别是

    index()create()store()show()edit()update()destroy()

    其中index()通常用来显示引导页/首页,其他的六个通常用来对数据的创建/读取/更新/删除操作,简称 CRUD (Create Retrieve Update Delete)。
    现在我们先删除这些空操作,然后创建一个新方法:

    <?php
    
    namespaceAppHttpControllers;
    
    useIlluminateHttpRequest;
    
    useAppHttpRequests;
    useAppHttpControllersController;
    
    classUserControllerextendsController
    {
        public function name(){
            return'Name Page';
        }
    }

    对应之前创建过的路由:

    Route::get('/user/name', 'UserController@name');

    现在我们可以访问一下localhost/user/name看下效果:
    这里写图片描述
    可以看到,实现了跟以前一样的效果,但是我们应用了 Controller ,一个很简单的例子。

    (三) 控制器的命名空间

    可能你会注意到控制器文件中有这么一行代码:

    namespace AppHttpControllers;

    这行代码就是说明了此控制器的命名空间。

    这个目录也是控制器的默认目录,所以我们在 routes.php 文件中引入的时候可以直接使用:

    Route::get('/user/name', 'UserController@name');

    有一点非常重要,那就是我们在定义控制器路由时,不需要指定完整的控制器命名空间。我们只需要定义「根」命名空间 AppHttpControllers 之后的部分类名称即可。默认 RouteServiceProvider 会使用路由群组,把 routes.php 文件里所有路由规则都配置了根控制器命名空间。

    现在假如你在 AppHttpController 目录下新建了一个 User 文件夹来存放 UserControllser.php。
    你的 routes.php 文件中就需要这么写:

    Route::get('/user/name', 'UserUserController@name');

    相应的,控制器中的命名空间也要改变:

    namespaceAppHttpControllersUser;

    现在让我们来删掉刚才的控制器,重新生成一个新的控制器,打开命令行:

    rm app/Http/Controllers/UserController.php

    然后重新生成一个 UserController ,这次我们单独创建一个 User 文件夹来存放这个 Controller 。

    php artisan make:controller User/UserController

    然后打开工程文件,我们可以看到,在 apphttpControllers 文件夹下新建了一个 User 文件夹,里边有我们刚刚创建的 UserController.php 文件,打开这个文件:

    <?php
    
    namespaceAppHttpControllersUser;
    
    useIlluminateHttpRequest;
    
    useAppHttpRequests;
    useAppHttpControllersController;
    
    classUserControllerextendsController
    {
        /**
         * Display a listing of the resource.
         *
         * @return IlluminateHttpResponse
         */
        publicfunctionindex()
        {
            //
        }
    
        .
        .
        .
    }

    注意看命名空间,可以看到,默认生成的命名空间就是AppHttpControllerUser 这就是 artisan 命令为我们做的。
    修改为我们自己的方法:

    <?php
    
    namespaceAppHttpControllersUser;
    
    useIlluminateHttpRequest;
    
    useAppHttpRequests;
    useAppHttpControllersController;
    
    classUserControllerextendsController
    {
        publicfunctionname(){
            return'Name Page';
        }
    }

    然后对应更改 routes.php 文件:

    Route::get('/user/name', 'UserUserController@name');

    然后访问 localhost/user/name 可以看到实现了正确的跳转!

    (四) 控制器的依赖注入

    细心的你肯定发现,控制器中还有几行神奇的代码:

    use IlluminateHttpRequest;
    
    use AppHttpRequests;
    use AppHttpControllersController;

    这几行代码说明了该控制器的依赖注入,简单来说,依赖注入就是将该控制器用到的依赖添加进来。
    比如,所有的 Controller 都依赖 基础 Controller.php ,所以需要:

    use AppHttpControllersController;

    比如,当我们处理请求的时候,我们引入 Request 类,才可以使用很多 Laravel 提供的方法:

    use IlluminateHttpRequest;

    在后边的实验中你会慢慢体会到依赖注入的强大之处。

  • 相关阅读:
    JAVA整理05---手写简单的linkedlist来学习linkedlist
    JAVA整理04---手写简单的arraylist来学习arraylist
    java整理03--常用类
    java整理02--面向对象深入
    每周学习进度
    软件工程课程总结
    梦断代码阅读笔记03
    scrum第二阶段项目冲刺_day10
    scrum第二阶段项目冲刺_day09
    scrum第二阶段项目冲刺_day08
  • 原文地址:https://www.cnblogs.com/zswbky/p/8454103.html
Copyright © 2011-2022 走看看