前面讲了singleton和Middleware,现在来继续讲ServiceProviders和Routes,还是看起始文件bootstrap/app.php
/ *
| --------------------------------------------------------------------------
|登记服务提供商
| --------------------------------------------------------------------------
|
|这里我们将登记所有的应用服务提供商
|用于绑定到容器服务。服务提供商
|完全可选的,所以你不需要注释掉这行。
|
* /
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
$app->register(Illuminate\Redis\RedisServiceProvider::class);
//向应用程序注册服务提供者
public function register($provider)
{
if (! $provider instanceof ServiceProvider) {
$provider = new $provider($this);
}
if (array_key_exists($providerName = get_class($provider), $this->loadedProviders)) {
return;
}
$this->loadedProviders[$providerName] = true;
if (method_exists($provider, 'register')) {
$provider->register();
}
if (method_exists($provider, 'boot')) {
return $this->call([$provider, 'boot']);
}
}
前面的是Lumen自带的,后面的UserServiceProvider是我自己加的,我们先来看看AuthServiceProvider
$app->register(App\Providers\User\UserServiceProvider::class);
App\Providers\AuthServiceProvider
namespace App\Providers;
use App\User;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
$this->app['auth']->viaRequest('api', function ($request) {
if ($request->header('api_token')) {
return User:: where('api_token', '=', $request->header('api_token'))->first();
}
});
}
}
App\Providers\AuthServiceProvider
public function register()
{
//
}
public function boot()
{
$this->app['auth']->viaRequest('api', function ($request) {
$env = app()->environment();
if (in_array($env, ['pc', 'test'])) {
return ['uid' => 1558];
}
if (!$request->cookies->has('admin_passport')) {
$ret = [
'code' => 10000,
'data' => '',
'message' => 'cookie获取失败'
];
//HTTP头设置必须json输出
header('Content-Type: application/json');
echo json_encode($ret);
exit;
}
$authorization = $request->cookies->get('admin_passport');
$CryptUtil = new CryptUtil();
$data = $CryptUtil->decrypt($authorization);
if (!empty($data['uid'])) {
return [
'uid' => $data['uid']
];
}
});
}
Illuminate\Redis\RedisServiceProvider
public function register()
{
$this->app->singleton('redis', function ($app) {
$config = $app->make('config')->get('database.redis');
return new RedisManager(Arr::pull($config, 'client', 'predis'), $config);
});
$this->app->bind('redis.connection', function ($app) {
return $app['redis']->connection();
});
}
public function provides()
{
return ['redis', 'redis.connection'];
}
// 从数组中获取一个值,然后删除它
public static function pull(&$array, $key, $default = null)
{
$value = static::get($array, $key, $default);
static::forget($array, $key);
return $value;
}
// 使用“点”符号从数组中获取项
public static function get($array, $key, $default = null)
{
if (! static::accessible($array)) {
return value($default);
}
if (is_null($key)) {
return $array;
}
if (static::exists($array, $key)) {
return $array[$key];
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
return value($default);
}
}
return $array;
}
//确定给定值是否可访问数组
public static function accessible($value)
{
return is_array($value) || $value instanceof ArrayAccess;
}
// 确定给定的键是否存在于提供的数组中
public static function exists($array, $key)
{
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
这里主要有两个比较核心的函数register(注册)与boot(启动),$app->register()会先注册,后启动,这里我有写一篇:Lumen手记:lumen源码解读之初始化(5)——注册(register)与启动(boot)
自己定义ServiceProviders也是同样道理:Lumen手记:如何向 IoC 容器中添加自己定义的类
再来讲一下路由,路由可以说是最简单的啦,
/ *
| --------------------------------------------------------------------------
|负载的应用途径
| --------------------------------------------------------------------------
|
|接下来我们将包括路线的文件,都可以被添加到
|应用。这将提供应用程序的所有URL。
|可以响应,以及可能的处理控制器。
|
* /
$app->group(['namespace' => 'App\Http\Controllers'], function ($app) {
require __DIR__ . '/../routes/web.php';
require __DIR__ . '/../routes/user.php';
});
新建几个加载进来都可以读到,不过要注意路径和不要有重复的路由喔!
// 用一组共享属性注册一组路由
public function group(array $attributes, Closure $callback)
{
if (isset($attributes['middleware']) && is_string($attributes['middleware'])) {
$attributes['middleware'] = explode('|', $attributes['middleware']);
}
$this->updateGroupStack($attributes);
call_user_func($callback, $this);
array_pop($this->groupStack);
}
// 使用给定的属性更新组堆栈
protected function updateGroupStack(array $attributes)
{
if (! empty($this->groupStack)) {
$attributes = $this->mergeWithLastGroup($attributes);
}
$this->groupStack[] = $attributes;
}
// 将给定的组属性与最后添加的组合并
protected function mergeWithLastGroup($new)
{
return $this->mergeGroup($new, end($this->groupStack));
}
// 合并给定的组属性
public function mergeGroup($new, $old)
{
$new['namespace'] = static::formatUsesPrefix($new, $old);
$new['prefix'] = static::formatGroupPrefix($new, $old);
if (isset($new['domain'])) {
unset($old['domain']);
}
if (isset($old['as'])) {
$new['as'] = $old['as'].(isset($new['as']) ? '.'.$new['as'] : '');
}
if (isset($old['suffix']) && ! isset($new['suffix'])) {
$new['suffix'] = $old['suffix'];
}
return array_merge_recursive(Arr::except($old, ['namespace', 'prefix', 'as', 'suffix']), $new);
}
// 获取除指定键数组之外的所有给定数组
public static function except($array, $keys)
{
static::forget($array, $keys);
return $array;
}
// 使用“点”符号从给定数组中删除一个或多个数组项
public static function forget(&$array, $keys)
{
$original = &$array;
$keys = (array) $keys;
if (count($keys) === 0) {
return;
}
foreach ($keys as $key) {
// if the exact key exists in the top-level, remove it
if (static::exists($array, $key)) {
unset($array[$key]);
continue;
}
$parts = explode('.', $key);
// clean up before each pass
$array = &$original;
while (count($parts) > 1) {
$part = array_shift($parts);
if (isset($array[$part]) && is_array($array[$part])) {
$array = &$array[$part];
} else {
continue 2;
}
}
unset($array[array_shift($parts)]);
}
}
// 格式化新组属性的使用前缀
protected static function formatUsesPrefix($new, $old)
{
if (isset($new['namespace'])) {
return isset($old['namespace']) && strpos($new['namespace'], '\\') !== 0
? trim($old['namespace'], '\\').'\\'.trim($new['namespace'], '\\')
: trim($new['namespace'], '\\');
}
return isset($old['namespace']) ? $old['namespace'] : null;
}
//格式化新组属性的前缀
protected static function formatGroupPrefix($new, $old)
{
$oldPrefix = isset($old['prefix']) ? $old['prefix'] : null;
if (isset($new['prefix'])) {
return trim($oldPrefix, '/').'/'.trim($new['prefix'], '/');
}
return $oldPrefix;
}
require __DIR__ . '/../routes/web.php';
$app->get('/info', function() use ($app) {
return [
'app' => $app->version(),
'env' => $app->environment()
];
});
$app->get('test', [
'as' => 'test', 'uses' => 'Controller@test'
]);
$app->post('foo/bar', function() {
return '----post----';
});
$app->patch('foo/bar', function() {
return '----patch----';
});
$app->put('foo/bar', function() {
return '----put----';
});
$app->delete('foo/bar', function() {
return '----delete----';
});
$app->get('/post/{id:[\d]+}', ['middleware' => 'auth', function (Request $request, $id) {
$user = Auth::user();
$user = $request->user();
var_dump($user);
}]);
// 向应用程序注册路由
public function get($uri, $action)
{
$this->addRoute('GET', $uri, $action);
return $this;
}
public function post($uri, $action)
{
$this->addRoute('POST', $uri, $action);
return $this;
}
// 向集合添加路由
public function addRoute($method, $uri, $action)
{
$action = $this->parseAction($action);
$attributes = null;
if ($this->hasGroupStack()) { // ! empty($this->groupStack);
$attributes = $this->mergeWithLastGroup([]);
}
if (isset($attributes) && is_array($attributes)) {
if (isset($attributes['prefix'])) {
$uri = trim($attributes['prefix'], '/').'/'.trim($uri, '/');
}
if (isset($attributes['suffix'])) {
$uri = trim($uri, '/').rtrim($attributes['suffix'], '/');
}
$action = $this->mergeGroupAttributes($action, $attributes);
}
$uri = '/'.trim($uri, '/');
if (isset($action['as'])) {
$this->namedRoutes[$action['as']] = $uri;
}
if (is_array($method)) {
foreach ($method as $verb) {
$this->routes[$verb.$uri] = ['method' => $verb, 'uri' => $uri, 'action' => $action];
}
} else {
$this->routes[$method.$uri] = ['method' => $method, 'uri' => $uri, 'action' => $action];
}
}
// 将操作解析为数组格式
protected function parseAction($action)
{
if (is_string($action)) {
return ['uses' => $action];
} elseif (! is_array($action)) {
return [$action];
}
if (isset($action['middleware']) && is_string($action['middleware'])) {
$action['middleware'] = explode('|', $action['middleware']);
}
return $action;
}
//将组属性合并到动作中
protected function mergeGroupAttributes(array $action, array $attributes)
{
$namespace = isset($attributes['namespace']) ? $attributes['namespace'] : null;
$middleware = isset($attributes['middleware']) ? $attributes['middleware'] : null;
$as = isset($attributes['as']) ? $attributes['as'] : null;
return $this->mergeNamespaceGroup(
$this->mergeMiddlewareGroup(
$this->mergeAsGroup($action, $as),
$middleware),
$namespace
);
}
// 将名称空间组合并到动作中
protected function mergeNamespaceGroup(array $action, $namespace = null)
{
if (isset($namespace) && isset($action['uses'])) {
$action['uses'] = $namespace.'\\'.$action['uses'];
}
return $action;
}
//将中间件组合并到动作中
protected function mergeMiddlewareGroup(array $action, $middleware = null)
{
if (isset($middleware)) {
if (isset($action['middleware'])) {
$action['middleware'] = array_merge($middleware, $action['middleware']);
} else {
$action['middleware'] = $middleware;
}
}
return $action;
}
// 将as组合并到动作中
protected function mergeAsGroup(array $action, $as = null)
{
if (isset($as) && ! empty($as)) {
if (isset($action['as'])) {
$action['as'] = $as.'.'.$action['as'];
} else {
$action['as'] = $as;
}
}
return $action;
}