8天学会PHP之day5 框架基础功能初探

 

框架的内容非常多,如果仔细学一遍的话,一天时间是不够用的。所以我针对性的选择学习我们需要的内容,大致有路由、中间件、控制器这三个核心部分。即使只有这三部分,也绝不是只需要花3个小时就能掌握的,所以要有所准备。多花些时间来学习。

其实在工作中,接触最频繁的就是框架。而前面学习的内容,都是在为学习框架打基础。但是根据我的工作经验和我个人的观点来看,框架并不是最核心的东西,反而是最不重要的东西。可以这么解释一下:流水的框架,铁打的编程语言。再往深了讲:流水的编程语言,铁打的编译原理。所以在业余时间我除了学习编程语言和框架之外,也还在学习编译学。

我们要明白,框架能实现的,编程语言一样能实现。编程语言学不好,你根本就不知道框架都在做什么。框架存在的目的使用一种统一的方式来快速开发和管理我们的应用。千万别让框架成为你学习编程语言的阻力。

在我短暂的职业生涯中,遇到过只会用Spring而不会Java的Java工程师,也遇到过只会用jQuery而不会JavaScript的前端工程师。我希望我们都不会成为这种人。

关于框架和编程语言的争论,一直没有停下过。我不管其他人怎么想,我对自己的要求始终都是编程语言第一,框架思想第二。至于框架的API我从不死记硬背,常用的会形成肌肉记忆,不常用的背下来浪费脑空间,不如直接去翻官方文档。

 

一、路由

什么是路由?

wikipedia上给出的答案:路由是为网络中或多个网络之间或之间选择路径的过程。

在实际的web应用中,路由通过路由配置表,决定了你从浏览器输入的地址,对应到执行哪些事情,返回哪些资源。

最简单的是windows的hosts文件,就是一个路由配置表。

laravel中的路由内容非常多,我把大多数常用的写了Demo。

laravel的路由配置分两种,一种是api配置,一种是页面配置。我们不需要页面配置,所以只关注api的配置。

在上一章中讲到过,路由配置表在项目根目录的routes目录下,api.php文件代表api路由配置。我们的代码都在这个文件中。

你可以使用postman之类的工具对路由进行测试。

基础路由

基础路由是使用Illuminate\Support\Facades\Route这个类的静态方法创建的。这个方法接受2个参数,第一个是路由名字,第2个是回调函数。

Route::get('route1', function () {
    return 'hello route1';
});

上面这段代码就是基础路由的基本操作。访问http://homestead.test/api/route24就能得到内容。

这里为什么带有一个api前缀呢?目的是为了和页面路由进行区分。

我们可以修改这个前缀,比如加一个版本号。

在app/providers/RouteServiceProvider.php中,找到mapApiRoutes方法,这里面定义了api路由的前缀。我们可以加一个v1表示版本1,这样就需要通过http://homestead.test/api/v1/route24来访问。

protected function mapApiRoutes()
    {
        Route::prefix('api/v1')
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }

上面的route1路由只支持get方式请求,你可以尝试使用post方式请求,会得到一个错误。

The POST method is not supported for this route. Supported methods: GET, HEAD.

意思是这个路由不支持post方法,只支持get方法请求。

那我们可以写一个post的路由。

Route::post('route2', function () {
    return 'hello route2';
});

上面这个路由支持了post方法的请求。

laravel共支持6种方式的请求,这些方式都有对应的Route类静态方法:

  • get

  • post

  • put

  • patch

  • delete

  • options

如果你想创建一个同时支持get和post的路由,可以使用match方法,接受3个参数,第1个是字符串数组,包含支持的请求方式,第2个是路由名称,第3个是回调函数。

Route::match(['get', 'post'], "route3", function () {
    return 'hello route3';
});

如果你想创建一个同时支持所有方式的路由,可以使用any方法。

Route::any('route4', function () {
    return "hello route4";
});
重定向

使用redirect方法。这样能让route5重定向到route4.

Route::redirect('route5', 'route4');

重定向的默认状态码是302.我们可以使用第3个参数自己指定,如301

Route::redirect('route6', 'route4', 301);

除此之外,还可以使用permanentRedirect方法,和上面的代码作用相同。

Route::permanentRedirect('route7', 'route4');

路由参数

必选参数

使用{}包裹,这个参数会自动注入到回调函数中。

Route::get('/route8/{id}', function ($id) {
    return 'id:' . $id;
});
可选参数

在参数名后面加?。必须有默认值,不然会报错

Route::get('/route9/{id?}', function ($id = 1) {
    return 'id:' . $id;
});
使用正则约束参数
Route::get('route10/{id}', function ($id) {
    return 'id:' . $id;
})->where('id', '[A-Za-z]+');

只有route10/a这种字母参数路由能请求响应,route10/1这种数字参数路由就无法匹配。

如果你想进行全局约束,在app/Providers/RouteServiceProvider中的boot方法中设置。比如所有名为id的路由参数只支持数字。

public function boot()
{
    Route::pattern('id', '[0-9]+');
​
    parent::boot();
}

如果全局有设置,同时又存在where方法,where会覆盖全局设置。

路由名命

链式调用name方法。

Route::get('route11/info', function () {
    return 'route 11 info';
})->name('info');

这样route11/info这个路由的名字就是info.

再通过route方法就能得到这个路由。$url = route('info');

回退路由

用于处理其它所有路由都匹配不到的路由,使用fallback方法。在这里适合做一些异常处理,比如返回404.

Route::fallback(function () {
    return "404 啦";
});

除了上述的这几种,还有路由组、路由模型绑定、访问控制等其它API。但这需要理解其它的几个概念才能继续下去。所以路由的内容先到此为止。

 

二、中间件

什么是中间件?

wikipedia上给出的答案:中间件(英语:Middleware),又译中介软件、中介层,是提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通,特别是应用软件对于系统软件的集中的逻辑,在现代信息技术应用框架如Web服务、面向服务的体系结构等中应用比较广泛。

简单地说,a要访问b,中间件在中间进行拦截,a和b就没有直接关系。a访问到中间件,中间件再访问b。

这里的中间件,其实和Java中的过滤器/拦截器是一回事,都属于面向切面编程的范畴,只是叫法不一样。

使用一个中间件大约分3步。

1.定义中间件

假设我们定义一个过滤年龄的中间件。

在命令行输入php artisan make:middleware CheckAge,会自动在App/Http/Middleware文件夹中创建CheckAge.php文件。我们也可以手动创建。

这个文件中有一个和文件同名的类,类中只有一个handle方法。我们可以在里面写一个拦截逻辑。

<?php
​
namespace App\Http\Middleware;
​
use Closure;
​
// 定义中间件, 执行命令 php artisan make:middleware CheckAge,也可以自己手动创建
class CheckAge
{
    public function handle($request, Closure $next)
    {
        if ($request->age < 18) {
            return response('未成年不可观看');
        }
        // 继续传递请求,调用 next,参数为 request
        return $next($request);
    }
}

2.注册中间件

app/Http/Kernel.php 中的 $middleware 属性中列出这个中间件。

// 在对象中添加这个中间件
'checkAge' => \App\Http\Middleware\CheckAge::class,

3.使用中间件

创建一个路由,使用middleware方法设置中间件。middleware方法接受不定个数的参数,如果需要多个中间件,就传递多个参数进去。

Route::middleware('checkAge')->get('route14/{age}', function ($age) {
    return 'route14';
});

这样访问http://homestead.test/api/v1/route14/12就会遭到拦截,而http://homestead.test/api/v1/route14/22则可以得到正确的资源。

中间件生效了。

上面的3步是中间件的基本用法,更高级的用法还有几个,但不常用,这里简单说下。

全局注册中间件

app/Http/Kernel.php 中的 $middleware 属性中列出这个中间件。

中间件群组

修改$middlewareGroups 属性。

中间件排序

$middlewarePriority 属性指定中间件优先级。

中间件参数

在调用middleware方法时,以"中间件名:参数"的方式设置参数。而中间件的handle方法可以多接受一个参数。

 

三、控制器

控制器不是一个新的概念。

控制器的本质,其实就是路由中的回调函数。

控制器能将相关的请求处理逻辑组成一个单独的类。 控制器被存放在 app/Http/Controllers 目录中。

创建控制器

app/Http/Controller目录中新建一个文件,里面创建类和方法,并模拟一些数据。

<?php
​
namespace App\Http\Controllers;
​
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
​
class UserController
{
    private $users = [
        ['id' => 1, 'name' => '小明'],
        ['id' => 2, 'name' => '小红'],
        ['id' => 3, 'name' => '小张'],
    ];
​
    public function searchUserById($id)
    {
        $result = "";
        foreach ($this->users as $user) {
            if ($user['id'] = $id) {
                $result = $user;
                break;
            };
        }
        return $result;
    }
}

使用控制器

创建一个路由,第二个参数替换成命名空间\class名@function名格式的字符串。

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

请求http://homestead.test/api/v1/user/1,就能拿到小明的数据。

单个行为控制器

如果你想定义一个只处理单个行为的控制器,你可以在控制器中放置一个 __invoke 方法。

比如上面的例子中,你只想查询用户。

修改方法名:

public function __invoke ($id)
{
    // 仅修改方法名,内容不变
    // ...
}

修改路由:

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

控制器中间件

除了在路由中使用middleware方法以外,在控制器的构造函数中指定中间件更为方便。但这样必须继承Controller类,因为它提供了middleware方法。

class UserController extends Controller
{
    public function __construct()
    {
        // 表示这个控制器会使用chackAge中间件。
        $this->middleware('checkAge');
    }
}

除了以上内容外,laravel控制器还有资源控制器、依赖注入等高级用法。但应用不多,暂时不讲。

猜你喜欢

转载自www.cnblogs.com/luzhenqian/p/11432623.html