学习Slim Framework for PHP v3

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习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来处理处理请求。

 

 

  

 

 

 

 

 

  

 

以上是关于学习Slim Framework for PHP v3的主要内容,如果未能解决你的问题,请参考以下文章

学习Slim Framework for PHP v3

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

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

PHP Slim 3 Framework - 我可以在哪里放置我的控制器文件?

PHP Slim Framework REST API - 在每条路由之前验证访问令牌?

Slim Framework和Ember.js中的Access-Control-Origin