laravel模块之路由

前言:laravel模块解读,测试是最好的解读

路由

1
2
3
4
5
6
7
8
9
10
11
12
13
"require": {
"php": "^7.1.3",
"illuminate/container": "5.6.*",
"illuminate/contracts": "5.6.*",
"illuminate/http": "5.6.*",
"illuminate/pipeline": "5.6.*",
"illuminate/session": "5.6.*",
"illuminate/support": "5.6.*",
"symfony/debug": "~4.0",
"symfony/http-foundation": "~4.0",
"symfony/http-kernel": "~4.0",
"symfony/routing": "~4.0"
},

主要的类:

  • Route.php 路由基类,基本的路由
  • Router.php 路由实例类,进行了一定的封装,配合容器
  • RouteCollection.php 路由检测类
  • UrlGenerator.php url解析类
  • Redirector.php 跳转类
  • Pipeline.php 中间件类
  • RouteAction.php 控制器解析类
  • RoutingServiceProvider.php 服务提供者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Route
{
/**
* Create a new Route instance.
*
* @param array|string $methods
* @param string $uri
* @param \Closure|array $action
* @return void
*/
public function __construct($methods, $uri, $action)
{
$this->uri = $uri;
$this->methods = (array) $methods;
$this->action = $this->parseAction($action);

if (in_array('GET', $this->methods) && ! in_array('HEAD', $this->methods)) {
$this->methods[] = 'HEAD';
}

if (isset($this->action['prefix'])) {
$this->prefix($this->action['prefix']);
}
}
}

class Router
{
/**
* Create a new Router instance.
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @param \Illuminate\Container\Container $container
* @return void
*/
public function __construct(Dispatcher $events, Container $container = null)
{
$this->events = $events;
$this->routes = new RouteCollection;
$this->container = $container ?: new Container;
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<?php
/**
* Created by PhpStorm.
* User: 小粽子
* Date: 2018/6/16
* Time: 14:54
*/

namespace Tests\Routing;

use Illuminate\Container\Container;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Events\Dispatcher;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use PHPUnit\Framework\TestCase;

class RoutingTest extends TestCase
{

public function testBasicDispatchingOfRoutes()
{
$router = $this->getRouter();
$router->get('foo/bar', function () {
return 'hello';
});
$this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

$router->post('foo/bar', function () {
return 'post hello';
});
$this->assertEquals('post hello', $router->dispatch(Request::create('foo/bar', 'POST'))->getContent());

}


public function testControllerClosureMiddleware()
{
$router = $this->getRouter();
$router->get('foo/bar', [
'uses' => 'Tests\Routing\RouteTestClosureMiddlewareController@index',
'middleware' => 'foo',
]);
$router->aliasMiddleware('foo', function ($request, $next) {
$request['foo-middleware'] = 'foo-middleware';

return $next($request);
});

$this->assertEquals(
'index-foo-middleware-controller-closure',
$router->dispatch(Request::create('foo/bar', 'GET'))->getContent()
);
}

/**
* @expectedException \LogicException
* @expectedExceptionMessage Route for [foo/bar] has no action.
*/
public function testFluentRouting()
{
$router = $this->getRouter();
$router->get('foo/bar')->uses(function () {
return 'middleware';
})->middleware('Tests\Routing\RouteTestControllerMiddleware');
$this->assertEquals('middleware', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
$this->assertContains('Tests\Routing\RouteTestControllerMiddleware', $router->getCurrentRoute()->middleware());

$router->get('foo/bar');
$router->dispatch(Request::create('foo/bar', 'GET'));
}

public function testFluentRoutingWithControllerAction()
{
$router = $this->getRouter();
$router->get('foo/bar')->uses('Tests\Routing\RouteTestControllerStub@index');
$this->assertEquals('Hello World', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

$router = $this->getRouter();
$router->group(['namespace' => 'App'], function ($router) {
$router->get('foo/bar')->uses('Tests\Routing\RouteTestControllerStub@index');
});
$action = $router->getRoutes()->getRoutes()[0]->getAction();
$this->assertEquals('App\Tests\Routing\RouteTestControllerStub@index', $action['controller']);
}

public function testMatchesMethodAgainstRequests()
{
$request = Request::create('foo/bar', 'GET');
$route = new Route('GET', 'foo/{bar}', function () {
});
$this->assertTrue($route->matches($request));

}

public function testRouteRedirect()
{
$router = $this->getRouter();
$router->get('contact_us', function () {
throw new \Exception('Route should not be reachable.');
});
$router->redirect('contact_us', 'contact', 302);

$response = $router->dispatch(Request::create('contact_us', 'GET'));
$this->assertTrue($response->isRedirect('contact'));
$this->assertEquals(302, $response->getStatusCode());
}

protected function getRouter()
{
$container = new Container();

$router = new Router(new Dispatcher(), $container);

$container->singleton(Registrar::class, function () use ($router) {
return $router;
});

return $router;
}

}

class RouteTestClosureMiddlewareController extends Controller
{
public function __construct()
{
$this->middleware(function ($request, $next) {
$response = $next($request);

return $response->setContent(
$response->content().'-'.$request['foo-middleware'].'-controller-closure'
);
});
}

public function index()
{
return 'index';
}
}

class RouteTestControllerMiddleware
{
public function handle($request, $next)
{
$_SERVER['route.test.controller.middleware'] = true;
$response = $next($request);
$_SERVER['route.test.controller.middleware.class'] = get_class($response);

return $response;
}
}

class RouteTestControllerStub extends Controller
{
public function __construct()
{
}

public function index()
{
return 'Hello World';
}
}