Lumen开发:lumen源码解读之初始化(4)——服务提供(ServiceProviders)与路由(Routes)

前面讲了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;
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值