前情提要

前面我们分析了插件列表,看到 html 部分,我们看到了请求的url 包含 action 我们这篇就分析这里。

正文开始

在做到插件启用相关部分的时候。发现了一个链接,

1
http://typecho.test/index.php/action/plugins-edit?activate=HelloWorld&_=a05deb76f571cfb798d3904cc6cecf77

这块我就比较好奇了,为什么跟首页部分的不太一样吗,难道是又包装了一层?我们从路由分发来看一下。

1
2

array(6) { ["url"]=> string(22) "/action/[action:alpha]" ["widget"]=> string(9) "Widget_Do" ["action"]=> string(6) "action" ["regx"]=> string(32) "|^/action/([_0-9a-zA-Z-]+)[/]?$|" ["format"]=> string(10) "/action/%s" ["params"]=> array(1) { [0]=> string(6) "action" } }

可以看到,这个路由,匹配了 action 开头的 url,执行的组件是 Do,参数是一个action。具体路由的分析请看前几篇文章。

我们看下 Do 的执行部分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public function execute()
{
    /** 验证路由地址 **/
    $action = $this->request->action;

    //兼容老版本
    if (empty($action)) {
        $widget = trim($this->request->widget, '/');
        $objectName = 'Widget_' . str_replace('/', '_', $widget);

        if (preg_match("/^[_a-z0-9]$/i", $objectName) && Typecho_Common::isAvailableClass($objectName)) {
            $widgetName = $objectName;
        }
    } else {
        /** 判断是否为plugin */
        $actionTable = array_merge($this->_map, unserialize($this->widget('Widget_Options')->actionTable));

        if (isset($actionTable[$action])) {
            $widgetName = $actionTable[$action];
        }
    }

    if (isset($widgetName) && class_exists($widgetName)) {
        $reflectionWidget =  new ReflectionClass($widgetName);
        if ($reflectionWidget->implementsInterface('Widget_Interface_Do')) {
            $this->widget($widgetName)->action();
            return;
        }
    }

    throw new Typecho_Widget_Exception(_t('请求的地址不存在'), 404);
}

先获取 请求的 action ,这个值是从构造组件的时候传递过来的,

1
$widget = Typecho_Widget::widget($route['widget'], NULL, $params);

$params 这个值就会传入到 request 的构造中,看下面

1
$requestObject = new Typecho_Request();$requestObject->setParams($request);

具体大家可以追一下代码就了解了。

通过判断 action 是否为空来决定 widgetname,判断的部分大家可以自己看一下。

紧接着,会去用反射相关的方法去调用具体的逻辑。

反射我们会单独找一篇文章去说明。对了,还有一个判断,是会这个组件是否实现了 Widget_Interface_Do 接口。

下期预告

这篇比较短,但是不乱,所以可以说是很简洁了,下篇我们继续在插件查遍看看还有什么要说的。