业务代码:
public function storeEntry() { $this->display('store_entry'); }
访问链接:http://lanse1993.com/store/store_entry
【问题】store_entry.html的内容会在页面渲染,但是storeEntry方法没有被调用,跟踪tp底层源码:
Dispatcher.class.php
/** * 获得实际的操作名称 */ private static function getAction($var, $urlCase = C('URL_CASE_INSENSITIVE')) { $action = ! empty($_POST[$var]) ? $_POST[$var] : (! empty($_GET[$var]) ? $_GET[$var] : C('DEFAULT_ACTION')); unset($_POST[$var], $_GET[$var]); if ($maps = C('URL_ACTION_MAP')) { if (isset($maps[strtolower(CONTROLLER_NAME)])) { $maps = $maps[strtolower(CONTROLLER_NAME)]; if (isset($maps[strtolower($action)])) { // 记录当前别名 define('ACTION_ALIAS', strtolower($action)); // 获取实际的操作名 if (is_array($maps[ACTION_ALIAS])) { parse_str($maps[ACTION_ALIAS][1], $vars); $_GET = array_merge($_GET, $vars); return $maps[ACTION_ALIAS][0]; } else { return $maps[ACTION_ALIAS]; } } elseif (array_search(strtolower($action), $maps)) { // 禁止访问原始操作 return ''; } } } if (C('ACTION_NAME_STYLE', null ,1) == 0) { $action = $urlCase ? strtolower($action) : $action; } else { $action = $urlCase ? lcfirst(parse_name(strtolower($action), 1)) : lcfirst(parse_name($action, 1)); } return strip_tags($action); }
Controller.class.php
/** * 魔术方法 有不存在的操作的时候执行 * @access public * @param string $method 方法名 * @param array $args 参数 * @return mixed */ public function __call($method, $args) { if (0 === strcasecmp($method, ACTION_NAME . C('ACTION_SUFFIX'))) { if (method_exists($this, '_empty')) { // 如果定义了_empty操作 则调用 $this->_empty($method, $args); } elseif (file_exists_case($this->view->parseTemplate())) { // 检查是否存在默认模版 如果有直接输出模版 $this->display(); } else { APP_DEBUG == false && send_http_status(404); E(L('_ERROR_ACTION_') . ':' . ACTION_NAME); } } else { APP_DEBUG == false && send_http_status(404); E(__CLASS__ . ':' . $method . L('_METHOD_NOT_EXIST_')); return; } }
配置
'ACTION_NAME_STYLE' => 0, //请求方法的风格 0不处理 无配置 值为1驼峰 'URL_CASE_INSENSITIVE' => true, // 默认false 表示URL区分大小写 true则表示不区分大小写
分析:解析路由不处理(不转为驼峰)并且不区分大小写,以为这store_entry和Store_entry解析后的实际操作名都是store_entry;当然这个方法在控制器是不存在的,就出发了父类Controller的魔术方法__call,检查到存在默认模版store_entry.html,所以直接渲染输出模版