• PHP Laraval系列之文件结构、Artisan、路由、控制器


    一、      文件结构

    二、      编写第一行代码

    三、      初始强大的 Artisan

    (一)     什么是Artisan呢?

    (二)     常用 Artisan 命令

    四、      路由

    (一)     什么是路由呢?

    (二)     基本路由

    (三)     路由动作

    (四)     路由参数

    1.基础的路由参数

    2.可选的路由参数

    (五)     命名路由

    (六)     路由群组

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

    2.为路由群组添加共用的命名空间

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

    (七)     查看路由

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

    五、      控制器

    (一)     准备工作

    (二)     基础控制器

    (三)     控制器的命名空间

    (四)     控制器的依赖注入


    一、文件结构

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

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


    文件夹

    介绍

    app

    网站的业务逻辑代码,例如:控制器/模型/路由等

    bootstrap

    框架启动与自动加载设置相关的文件

    config

    网站的各种配置文件

    database

    数据库操作相关的文件

    public

    网站的对外文件夹,入口文件和静态资源(CSSJS,图片等)

    resources

    前端视图文件和原始资源(CSSJS,图片等)

    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('name/{name}/age/{age}', function($name, $age){
        return'I`m '.$name.' ,and I`m '.$age;
    });

    然后我们如果访问 localhost/name/Tom/age/28 我们可以看到网页返回了对应的信息:


    2.可选的路由参数

    有时你需要指定可选的路由参数,可以通过在参数后面加上 ?来实现。

    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
         */
        publicfunctionshow($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命令生成控制器:

    phpartisanmake:controllerUserController

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

    <?php
     
    namespaceAppHttpControllers;
     
    useIlluminateHttpRequest;
     
    useAppHttpRequests;
    useAppHttpControllersController;
     
    classUserControllerextendsController
    {
        /**
         * Display a listing of the resource.
         *
         * @return IlluminateHttpResponse
         */
        publicfunctionindex()
        {
            //
        }
     
        /**
         * Show the form for creating a new resource.
         *
         * @return IlluminateHttpResponse
         */
        publicfunctioncreate()
        {
            //
        }
     
        /**
         * Store a newly created resource in storage.
         *
         * @param  IlluminateHttpRequest  $request
         * @return IlluminateHttpResponse
         */
        publicfunctionstore(Request $request)
        {
            //
        }
     
        /**
         * Display the specified resource.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        publicfunctionshow($id)
        {
            //
        }
     
        /**
         * Show the form for editing the specified resource.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        publicfunctionedit($id)
        {
            //
        }
     
        /**
         * Update the specified resource in storage.
         *
         * @param  IlluminateHttpRequest  $request
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        publicfunctionupdate(Request $request, $id)
        {
            //
        }
     
        /**
         * Remove the specified resource from storage.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        publicfunctiondestroy($id)
        {
            //
        }
    }

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

    index()create()store()show()editupdatedestroy

    其中index()通常用来显示引导页/首页,其他的六个通常用来对数据的创建/读取/更新/删除操作,简称 CRUD (Create Retrieve Update Delete)。

    现在我们先删除这些空操作,然后创建一个新方法:

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

    对应之前创建过的路由:

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

    现在我们可以访问一下localhost/user/name看下效果:


    可以看到,实现了跟以前一样的效果,但是我们应用了 Controller ,一个很简单的例子。

    (三) 控制器的命名空间

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

    namespaceAppHttpControllers;

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

    这个目录也是控制器的默认目录,所以我们在 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;

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

  • 相关阅读:
    nodeJs-querystring 模块
    nodeJs-process对象
    nodejs-Path模块
    nodejs-os模块
    nodejs-CommonJS规范
    nodejs-Events模块
    nodejs-Http模块
    nodejs-Cluster模块
    转:AOP与JAVA动态代理
    转:jdk动态代理实现
  • 原文地址:https://www.cnblogs.com/zswbky/p/8454125.html
Copyright © 2020-2023  润新知