学习Slim Framework for PHP v3 (四)

  看看官网加粗的一句话:

  At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.

  那么它是如何分发接收到的Request的呢,这几天就来研究这个事情。

  先看看为了让请求进入到index.php 需要对Apache做什么。配置如下,其实也是通常配置而已:

# DirectoryIndex: sets the file that Apache will serve if a directory

# is requested.

#

<IfModule dir_module>

#DirectoryIndex index.html

# XAMPP

DirectoryIndex index.html index.html.var index.php index.php3 index.php4

</IfModule>

  保证了访问目录是直接到index.xxx中来。

  还有在项目下有个.htaccesss,这个文件的作用是判断请求的URL满足条件否,即是否满足RewriteCond的匹配。最后如果条件满足则执行RewriteRule 的内容,这里让它跳转到index.php。

  

$app->get(‘/forbase‘, function ($request, $response, $args){
    Example\Module\Base::instance()->init($request,$response);
    return $response;
})->add(Example\MiddleWare\MyMiddleware::instance(Example\Module\Base::instance()));

  这篇先解决:get是怎么加进去的。在随后的文章里依次解决:route是怎么被调用的;route Middleware是如何加进去的。

  在App.php里有变量container。这个变量的类型是Slim\Container,而Slim\Container 继承 PimpleContainer ,据官网说这个Pimple是一个DI Container,这个还不了解。

public function __construct($container = [])
    {
        if (is_array($container)) {
            $container = new Container($container);
        }
        if (!$container instanceof ContainerInterface) {
            throw new InvalidArgumentException(‘Expected a ContainerInterface‘);
        }
        $this->container = $container;
    }
class Container extends PimpleContainer implements ContainerInterface
{
    /**
     * Create new container
     *
     * @param array $values The parameters or objects.
     */
    public function __construct(array $values = [])
    {
        parent::__construct($values);

        $userSettings = isset($values[‘settings‘]) ? $values[‘settings‘] : [];
        $this->registerDefaultServices($userSettings);
    }

 在Container构造方法中会注册相关的DefaultServices包括router,以后所有的route都存在于router中:

  

if (!isset($this[‘router‘])) {
            /**
             * This service MUST return a SHARED instance
             * of \Slim\Interfaces\RouterInterface.
             *
             * @return RouterInterface
             */
            $this[‘router‘] = function () {
                return new Router;
            };
        }

  这个$this[‘router‘]其实是调用了Pimple\Container中的 offsetSet()方法,因为Pimple\Container实现了ArrayAccess,因此$this[‘router‘]是可用的。

public function offsetSet($id, $value)
{
    if (isset($this->frozen[$id])) {
        throw new \RuntimeException(sprintf(‘Cannot override frozen service "%s".‘, $id));
    }

    $this->values[$id] = $value;
    $this->keys[$id] = true;
}

  这样的所有默认设置都存放在values这个变量里,以后拿设置从values里拿就好了。

  在app->get()时,APP类所做的工作:

      一get()/post()函数接受route创建请求。二调用app->map();三调用router->map();四设置route的container和output buffer。

上代码:

/**
 * Add GET route
 *
 * @param  string $pattern  The route URI pattern
 * @param  mixed  $callable The route callback routine
 *
 * @return \Slim\Interfaces\RouteInterface
 */
public function get($pattern, $callable)
{
    return $this->map([‘GET‘], $pattern, $callable);
}
public function map(array $methods, $pattern, $callable)
{
    if ($callable instanceof Closure) {
        $callable = $callable->bindTo($this->container);
    }

    $route = $this->container->get(‘router‘)->map($methods, $pattern, $callable);
    if (is_callable([$route, ‘setContainer‘])) {
        $route->setContainer($this->container);
    }

    if (is_callable([$route, ‘setOutputBuffering‘])) {
        $route->setOutputBuffering($this->container->get(‘settings‘)[‘outputBuffering‘]);
    }
    return $route;
}

同时router类所做的工作:

   当有get、post之类的需要加入时,会在router中的map()方法中生成新的route并且给每个route进行了编号,将这个route加入到router的routes数组中。

上代码:

/**
 * Add route
 *
 * @param  string[] $methods Array of HTTP methods
 * @param  string   $pattern The route pattern
 * @param  callable $handler The route callable
 *
 * @return RouteInterface
 *
 * @throws InvalidArgumentException if the route pattern isn‘t a string
 */
public function map($methods, $pattern, $handler)
{
    if (!is_string($pattern)) {
        throw new InvalidArgumentException(‘Route pattern must be a string‘);
    }

    // Prepend parent group pattern(s)
    if ($this->routeGroups) {
        $pattern = $this->processGroups() . $pattern;
    }

    // According to RFC methods are defined in uppercase (See RFC 7231)
    $methods = array_map("strtoupper", $methods);

    // Add route
    $route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter);
    $this->routes[$route->getIdentifier()] = $route;
    $this->routeCounter++;

    return $route;
}

  这样的一个过程之后,某个添加的route就放入到router的routes数组中了。再以后APP接收到请求后,会在routes选择合适的route来处理处理请求。

  

  

时间: 2024-12-25 09:47:54

学习Slim Framework for PHP v3 (四)的相关文章

学习Slim Framework for PHP v3 (四)--route怎么被调用的?

上一篇中分析了get()如何加入新的route的,这篇来分析route是如何被调用的. 首先,route是在routers里保存,router有在container中存放.container提供了get()方法获取里面的元素,性质类似于Set().这个性质见Slim\Container的get()和Pimple\Container的 offsetGet()方法. /**Slim/Container:**/ /** * Finds an entry of the container by its

学习Slim Framework for PHP v3 (一)

因为公司的项目用到是slim 框架,所以想把它学习一下.在公司用到是Slim2版本,现在官网已经到达 Slim3的版本了.官网地址:http://www.cnblogs.com/lmenglliren89php/. 首先按照官网的教程,安装Slim: 1.curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer 2.composer requi

学习Slim Framework for PHP v3 ( 二)

昨天说到能够成功将本地的URL通过在index.php 中添加get(pattern,clouser)路由到指定的处理类中,处理后(这里指存入数据库中),然后返回response在浏览器中显示. 昨天最后留的问题是:能不能在App的container中添加自己的key呢,今天还没有解决. 今天做的工作是:添加一个middleware,在处理完成后记录日志. Slim3.0不再像Slim2那样在每个Middleware都添加Application,所以在Middleware中获取App的数据有困难

学习Slim Framework for PHP v3 (三)

继续上一篇的问题,如何动态的添加不同的Module.添加Module是给Middleware用的,用于调用Module的写日志方法.上篇中的写法是在app->add(mv),这时的middleware是全局的.其实可以给每个route添加middleware,这个思路是通过阅读官方文档获得的,所以说文档还是要读的. 有了上面的思路之后,就可以给每个route添加middleware了.先上代码: $app->post('/homepage', function ($request, $resp

学习Slim Framework for PHP v3 (六)--route怎么被匹配的?

先标记觉得以后会用到的内容: // add route to the request's attributes in case a middleware or handler needs access to the route $request = $request->withAttribute('route', $route); 或许以后可以在Middleware中拿到route做些其他的事情. 上篇已经分析到route是在APP的__invoke()中被调用的,这里来看看怎么匹配route的

Swift学习——Swift基础详解(四)

A:小儿编程很不好! B:多半是不爱学,从看英文版开始,让你爱上编程! Type Aliases    类型重定义(typedef) Swift中重定义类型的关键字是typealias,至于怎么用,应该不必多说了,看例子: typealias AudioSample = UInt16 //定义了一个类型名称AudioSample,代表UInt16类型 var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound is now 0 Boo

Swift学习——函数的使用和分类(四)

总结了一下Swift中的函数使用一共可以分为七类 1 ---- 没有返回值,没有参数的函数 2 ---- 有参数和返回值的函数 3 ---- 使用元祖来返回多个值 4 ---- 参数是可变的 5 ---- 函数的嵌套 6 ---- 函数可以作为另一个函数的返回值 7 ---- 函数可以作为参数 具体分析如下面代码所示 // 1 ---- 没有返回值,没有参数的函数 func function1() { println("----in function1----") } //调用函数 f

学习OpenCV范例(二十四)—ViBe前景检测(二)

最近导师没给什么项目做,所以有那么一点点小时间,于是就研究起了前景检测,既然前景检测有很多种算法,那干脆就把这些模型都学起来吧,以后用到前景检测时至少还有那么几种方法可以选择,上次介绍的是GMM模型,其实GMM模型本身就是一个很不错的模型,现在也很多人在研究,并且做改进,主要是OpenCV有函数调用,用起来非常方便,当我们都在兴高采烈的讨论GMM各种好的时候,B哥不爽了,他说老子是搞前景检测的,怎么可能让你们这么嚣张,而且老子就不按照你那套路来,什么高斯模型,混合高斯模型,我统统不用,就来个简单

Migration from Zend Framework v2 to v3

Migration from Zend Framework v2 to v3 Zend Framework v2 to v3 has been intended as an incremental upgrade. We have even made efforts in the past year to provide forwards compatibility features in v2 versions of components, to allow users to prepare