昨天说到能够成功将本地的URL通过在index.php 中添加get(pattern,clouser)路由到指定的处理类中,处理后(这里指存入数据库中),然后返回response在浏览器中显示。

  昨天最后留的问题是:能不能在App的container中添加自己的key呢,今天还没有解决。

  今天做的工作是:添加一个middleware,在处理完成后记录日志。

  Slim3.0不再像Slim2那样在每个Middleware都添加Application,所以在Middleware中获取App的数据有困难,同时向container中加入key的难题也没有解决呢。所以我的思路是这样:

  1.APP class 只用来添加middleware、启动router;

  2.将router注册为相关业务处理的Moduel;

  3.Moduel中含有实现日志记录的类;

  4.在Middleware中指定所对应的类。

  

  其实我还有一个疑问即middleware的__invoke()方法是何时执行的。追踪代码,发现在添加middleware时有这样一段代码如下:

protected function addMiddleware(callable $callable)
{
echo 'add middle ware'; if ($this->middlewareLock) {
throw new RuntimeException('Middleware can’t be added once the stack is dequeuing');
} if (is_null($this->stack)) {
$this->seedMiddlewareStack();
} $next = $this->stack->top();
$this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) {
$result = call_user_func($callable, $req, $res, $next);
if ($result instanceof ResponseInterface === false) {
throw new UnexpectedValueException(
'Middleware must return instance of \Psr\Http\Message\ResponseInterface'
);
} return $result;
}; return $this;
}

   这段代码中重要的是这两句:

      $next = $this->stack->top();

      $this->stack[] = function();
   这个stack[]即添加到middleware stack中,但是这个function ()是个重要的东西,也就是所谓的依赖注入。有趣在什么地方的呢,就是现在整个函数是不执行的,如果要执行的就是执行了middleware的__invoke()方法。而什么时候执行呢,逻辑上说就是到当前middleware顺序的时候进行执行,在代码上既 app->run()中调用。它调用的是middle stack 的top元素,有代码为证:

public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res)
{
if (is_null($this->stack)) {
$this->seedMiddlewareStack();
}
/** @var callable $start */
$start = $this->stack->top();
$this->middlewareLock = true;
$resp = $start($req, $res);
$this->middlewareLock = false;
return $resp;
}

  在 $start($req,$res)的时候,那个匿名函数function就会执行,自定义middleware的__invoke()就被执行了。

  这里应该是依赖注入的概念,现在还不是很明白,后面需要好好学习下。

  这算对源码的一些理解。

  根据上面4个方面的思路,设计中有的两点是:

    1.以Module为主体,将Log、DB等需要的lib加入到module中;
        2.在Midllerware中设定Module,调用Module的方法如写日志.
   在Module 中加入Log,DB是好用的,但是在Middleware中加入Module不可以用,原因在于Middleware先于module注册,注册时关联的module是NULL的,在后面执行的时候就找不到module,各种方法不存在的错误。
$app->add(Example\MiddleWare\MyMiddleware::instance());

$app->post('/homepage', function ($request, $response, $args) use ($app) {
Example\Module\Replace::instance($request,$response)->excute();
return $response;
});

  既然这样的话,那就先让Module存在即实例化module;然后在注册middleware的时候指定module,这样不会报错,对Module 和Middleware 修改代码如下:

/***
* Module
**/
public function init($request,$response){
$this->request = $request;
$this->response = $response;
$this->excute();
}
public abstract function excute();
/**
* Middleware
*/
self::$middleWare = is_null(self::$middleWare)?new MyMiddleware($module):self::$middleWare;
return self::$middleWare;
} public function __construct($module){
$this->module = $module; }

   然后在index.php中,添加middleware和router,代码如下:

$repModule = Example\Module\Replace::instance();
$app->add(Example\MiddleWare\MyMiddleware::instance($repModule)); $app->post('/homepage', function ($request, $response, $args) use ($repModule) {
$repModule->init($request,$response);
return $response;
});

  这样,在Middleware中完成LogWrite的功能就算实现了,但是问题来了,这里过早的指定了Module和Middleware,如果在注册其他router时不能动态的更改Module。这样不算好!

  有没有其他更好的方法呢,框架里很多匿名函数(Clouser)。是不是能有Clouser的办法解决呢?

  Module在Middleware中动态指定的问题需要解决。或者能用App做些什么,暂时没思路。

 

  

学习Slim Framework for PHP v3 ( 二)的更多相关文章

  1. 学习Slim Framework for PHP v3 (四)--get()是怎么加进去的?

    看看官网加粗的一句话: At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate ...

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

    上一篇中分析了get()如何加入新的route的,这篇来分析route是如何被调用的. 首先,route是在routers里保存,router有在container中存放.container提供了ge ...

  3. 学习Slim Framework for PHP v3 (三)

    继续上一篇的问题,如何动态的添加不同的Module.添加Module是给Middleware用的,用于调用Module的写日志方法.上篇中的写法是在app->add(mv),这时的middlew ...

  4. 学习Slim Framework for PHP v3 (七)--route middleware怎么被add进来的?

    上两篇中分析了route是怎么被加进来的,以及如何被匹配的.这篇说一下route middleware是如何被加进来的,即add进来的.index.php的代码如下: $app->get('/f ...

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

    先标记觉得以后会用到的内容: // add route to the request's attributes in case a middleware or handler needs access ...

  6. WCF学习之旅—TcpTrace工具(二十六)

    止文(WCF学习之旅—TcpTrace工具(二十五))介绍了关于TcpTrance的一种使用方式,接下来介绍第二种使用方式. 三.通过ListenUri实现基于tcpTracer的消息路由 对于路由的 ...

  7. Java学习-039-源码 jar 包的二次开发扩展实例(源码修改)

    最近在使用已有的一些 jar 包时,发现有些 jar 包中的一些方法无法满足自己的一些需求,例如返回固定的格式,字符串处理等等,因而需要对原有 jar 文件中对应的 class 文件进行二次开发扩展, ...

  8. Qlik Sense学习笔记之Mashup开发(二)

    date: 2019-01-26 11:28:07 updated: 2019-01-26 11:28:07 Qlik Sense学习笔记之Mashup开发(二) 1.Mobile SPA UI Fr ...

  9. 学习Coding-iOS开源项目日志(二)

    继续前篇:<学习Coding-iOS开源项目日志(一)>,接着本第二篇<学习Coding-iOS开源项目日志(二)>讲解Coding-iOS开源项目. 前言:作为初级程序员,想 ...

随机推荐

  1. arm_cm4.c关于kinetis的修改

    /***********************************************************************/ /* * Initialize the NVIC t ...

  2. Eclipse和Android Studio中的DDMS使用时什么不同?

    http://www.jb51.net/softjc/454131.html Eclipse和Android Studio中的DDMS使用时什么不同? 相信很多经常开发Android应用的朋友应该都接 ...

  3. zTree实现基本树

    zTree实现基本树 1.实现源代码 <!DOCTYPE html> <html> <head> <title>zTree实现基本树</title ...

  4. 将博CMS安全分析报告-橘皮书

    一.使用IBM的AppScan和Acunetix应用程序漏洞扫描将博CMS5.5,得出一些漏洞.         此番扫描大小共23种类型问题,其中高危漏洞有三个,中危漏洞9个,低级漏洞11个.注意这 ...

  5. Swift学习笔记十四

    Deinitialization 当类的实例对象即将要被释放时,会立即调用deinitializer,通过deinit关键字来定义deinitializer,和initializer一样,它也只存在于 ...

  6. Mysql权限控制 - 允许用户远程连接

    Mysql为了安全性,在默认情况下用户只允许在本地登录,可是在有此情况下,还是需要使用用户进行远程连接,因此为了使其可以远程需要进行如下操作: 一.允许root用户在任何地方进行远程登录,并具有所有库 ...

  7. Android程序开发0基础教程(一)

    程序猿学英语就上视觉英语网 Android程序开发0基础教程(一)   平台简单介绍   令人激动的Google手机操作系统平台-Android在2007年11月13日正式公布了,这是一个开放源码的操 ...

  8. MySQL错误:Can't connect to MySQL server (10060)

    转自:http://database.51cto.com/art/201107/274565.htm 当远程连接MySQL数据库的时候显示Can't connect to MySQL server ( ...

  9. /bin/bash: line 0: fg: no job control一般解决方法

    測试版本号:CDH5.0,(Hadoop2.3) 在使用windows调用Hadoop yarn平台的时候,一般都会遇到例如以下的错误: 2014-05-28 17:32:19,761 WARN or ...

  10. oc-15-匿名对象

    /** 匿名对象 1.访问成员变量--->只能给成员变量设置值,只能成功1次,每次都是新的对象. 2.调用方法时类似类方法: 跟类方法区别:匿名对象创建对象了,开辟空间了. */ #import ...