• 周六. 7 月 27th, 2024

    [Laravel学习笔记] 三、路由

    root

    7 月 17, 2020 #Laravel routers

    一、基本路由

    use Illuminate\Support\Facades\Route;
    Route::get('foo', function() {
        return "Hello World";
    });

    所有路由文件都位于routes目录下,这些文件由App\Providers\RouteServiceProvider服务自动加载。

    routes/web.php 定义web界面的路由。分配给web中间件,提供 会话状态和CSRF保护功能

    routes/api.php 都是无状态的,分配了api中间件组, 该文件中的路由通过RouteServiceProvider被嵌套到一个路由组中,在这个路由组中,会自动添加URL前缀/api 到此文件中的每个路由,这样你就无需再手动添加了。

    use App\Http\Controllers\UserController;
    Route::get('/user', [UserController::class, 'index']); //访问 http://your-app.dev/user

    路由器允许你注册能响应任何HTTP请求的路由

    Route::get($uri, $callback);
    Route::post($uri, $callbaak);
    Route::put($uri, $callback);
    Route::patch($uri, $callback);
    Route::delete($uri, $callback);
    Route::options($uri, $callback);

    响应多个HTTP请求的路由

    Route::match(['get','post'], '/', function(){
      //
    });
    //响应所有请求
    Route::any('/', function() {
      //
    })
    如下,你可以在路由的回调方法中使用类型提示,用来获取路由所需的任何依存关系。声明的依赖项将由Laravel服务容器自动解析并注入到回调中。
    use Illuminate\Support\Http\Request;
    
    Route::get('/users', function(Request $request){
        //....
    });

    CSRF保护,指向web路由文件中定义的POST、PUT或DELETE路由的任何HTML表单都应该包含一个CSRF令牌字段,否则这个请求会被拒绝

    <form method="POST" action="/profile">
        @csrf
        ...
    </form>

    如果要重定向到另一个URI路由,可以使用Route::redirect

    Route::redirect('/here', '/there', 302);  //第三个参数可不填 默认返回状态码302
    Route::permanentRedirect('/here', '/there');  //默认返回301

    如果你的路由只需要返回一个视图,可以使用Route::view方法。

    Route::view('/welcome', 'welcome');
    Route::view('/welcome', 'welcome', ['name'=>'Taylor']);
    @1 必填 视图名称URI
    @2 必填  渲染视图名称
    @3 可选  传参数组

    二、 路由参数

    有时需要在路由中捕获一些URL片段。

    Route::get('user/{id}', function($id) {
        return 'User '. $id;
    });
    Route::get('posts/{post}/comments/{comment}', function($postId,$commentId) {
    });

    路由的参数通常会放在{}内,并且参数名只能为字母,同时路由参数不能包含-符号,路由参数会按顺序依次被注入到路由回调或者控制器中,而不受回调或者控制器的参数名称的影响.

    你可能需要指定一个路由参数,但你希望这个参数是可选的。你可以在参数后面加上?标记来实现,

    Route::get("user/{name?}", function($name=null) {
        return $name;
    });
    Route::get('user/{name?}", function($name="John") {
        return $name;
    });

    使用路由实例上的where方法约束路由参数的格式。where方法接受参数名称和定义参数应如何约束的正则表达式

    Route::get('user/{name}', function($name) {
    })->where('name','[A-Za-z]+');
    Route::get('user/{id}', function($id) {
    })->where('id','[0-9]+');

    如果你希望某个路由参数都遵循同一个正则表达式的约束,就使用pattern方法在RouteServiceProvider的boot方法中定义

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

    一旦定义好,便会自动应用这些规则到所有使用该参数名称的路由上

    路由组件允许除/之外的所有字符。你必须使用where条件正则表达式显式地允许/成为点位符的一部分

    Route::get('search/{search}', function($search) {
        return $search;
    })->where('search', '.*');
    例如请求 /search/abc/cde  $search= abc/cde
    Route::get('user/profile',function(){
     //
    })->name('profile');

    ->name(‘xxx’) 为路由命名

    为路由指定了名称后,就可以使用全局辅助函数route来生成链接或重定向到该路由

    //生成URL..
    $url = route('profile');
    //生成重定向
    return redirect()->route('profile');
    Route::get('user/{id}/profile', function($id) {
    })->name('profile');
    $url = route('profile', ['id'=>1]);

    如果在数组中传递额外的参数,这些值将自动添加到生成的URL的查询字符串中

    Route::get('user/{id}/profile', function($id) {
    })->name('profile');
    $url = route('profile', ['id'=>1, 'photos'=>'yes']);
    // /usr/1/profile?photos=yes

    检查当前路由: 如果你想判断当前请求是否指向了某个命名过的路由,可以调用路由实例上的named方法。

    /**
     * 处理一个请求。
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->route()->named('profile')) {
            //
        }
    
        return $next($request);
    }

    把中间件分配给路由组内所有路由,在定义组之前使用middleware方法。

    Route::middleware(['first', 'second'])->group(function () {
        Route::get('/', function () {
            // Uses first & second middleware...
        });
    
        Route::get('/user/profile', function () {
            // Uses first & second middleware...
        });
    });

    prefix方法可以用给定的URI为组中每个路由做前缀

    Route::prefix('admin')->group(function () {
        Route::get('/users', function () {
            // Matches The "/admin/users" URL
        });
    });

    name方法可以用给定字符串作为组中每个路由名的前缀

    Route::name('admin.')->group(function () {
        Route::get('/users', function () {
            // Route assigned name "admin.users"...
        })->name('users');
    });

    Laravel自动解析在路由或控制器中定义的Eloquent模型,这些模型的类型暗示变量名称与路由段名称相匹配

    use App\Models\User;
    
    Route::get('/users/{user}', function (User $user) {
        return $user->email;
    });

    由于 $user 变量的类型暗示与 App\Models\user Eloquent 模型一样,且变量名与 {user} 的 URI 片段相匹配,Laravel 会自动注入与请求 URI 中对应值 ID 匹配的模型实例。 如果在数据库中没有找到匹配的模型实例,则会自动生成一个 404HTTP 响应。

    通常,如果没有找到隐式绑定模型,将生成 404 HTTP 响应。但是,你可以在定义路由时调用 missing 的方法来定制此行为。missing 的方法接受一个闭包,如果无法找到隐式绑定的模型,该闭包将被调用:

    use App\Http\Controllers\LocationsController;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Redirect;
    
    Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
            ->name('locations.view')
            ->missing(function (Request $request) {
                return Redirect::route('locations.index');
            });

    显式绑定路由参数与模型, 在RouteServiceProvider::boot()中定义

    use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    /**
     * 定义你的路由模型绑定,模式过滤等等。
     *
     * @return void
     */
    public function boot()
    {
        Route::model('user', User::class);
    
        // ...
    }
    
    在routes\web.php中
    use App\Models\User;
    
    Route::get('/users/{user}', function (User $user) {
        //
    });

    由于我们已将所有 {user} 参数绑定到 App\Models\User 模型,该类的实例将被注入到路由中。 因此,例如,对 users/1 的请求将从 ID 为 1 的数据库中注入 User 实例。如果在数据库中没有找到匹配的模型实例,则会自动生成一个 404 HTTP 响应。

    路由缓存

    php artisan route:cache;  //生成缓存
    php artisan route:clear;  //清除缓存

    root

    发表回复