/** * 利用__call方法实现一些特殊的Model方法 * @access public * @param string $method 方法名称 * @param array $args 调用参数 * @return mixed */ public function __call($method, $args) { if (in_array(strtolower($method), ['count', 'sum', 'min', 'max', 'avg'], true)) { // 统计查询的实现 $field = isset($args[0]) ? $args[0] : '*'; return $this->getField(strtoupper($method) . '(' . $field . ') AS tp_' . $method); } elseif (strtolower(substr($method, 0, 5)) == 'getby') { // 根据某个字段获取记录 $field = Loader::parseName(substr($method, 5)); $where[$field] = $args[0]; return $this->where($where)->find(); } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { // 根据某个字段获取记录的某个值 $name = Loader::parseName(substr($method, 10)); $where[$name] = $args[0]; return $this->where($where)->getField($args[1]); } elseif (isset($this->scope[$method])) { // 命名范围的单独调用支持 return $this->scope($method, $args[0]); } else { throw new \think\Exception(__CLASS__ . ':' . $method . Lang::get('_METHOD_NOT_EXIST_')); return; } }
/** * 解析模块的URL地址 [模块/控制器/操作?]参数1=值1&参数2=值2... * @access public * @param string $url URL地址 * @param string $depr URL分隔符 * @param bool $autoSearch 是否自动深度搜索控制器 * @return array */ public static function parseUrl($url, $depr = '/', $autoSearch = false) { if (isset(self::$bind['module'])) { $bind = str_replace('/', $depr, self::$bind['module']); // 如果有模块/控制器绑定 $url = $bind . ('.' != substr($bind, -1) ? $depr : '') . ltrim($url, $depr); } $url = str_replace($depr, '|', $url); list($path, $var) = self::parseUrlPath($url); $route = [null, null, null]; if (isset($path)) { // 解析模块 $module = Config::get('app_multi_module') ? array_shift($path) : null; if ($autoSearch) { // 自动搜索控制器 $dir = APP_PATH . ($module ? $module . DS : '') . Config::get('url_controller_layer'); $suffix = App::$suffix || Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : ''; $item = []; $find = false; foreach ($path as $val) { $item[] = $val; if (is_file($dir . DS . str_replace('.', DS, $val) . $suffix . EXT)) { $find = true; break; } else { $dir .= DS . $val; } } if ($find) { $controller = implode('.', $item); $path = array_slice($path, count($item)); } else { $controller = array_shift($path); } } else { // 解析控制器 $controller = !empty($path) ? array_shift($path) : null; } // 解析操作 $action = !empty($path) ? array_shift($path) : null; // 解析额外参数 self::parseUrlParams(empty($path) ? '' : implode('|', $path)); // 封装路由 $route = [$module, $controller, $action]; // 检查地址是否被定义过路由 $name = strtolower($module . '/' . Loader::parseName($controller, 1) . '/' . $action); $name2 = ''; if (empty($module) || isset($bind) && $module == $bind) { $name2 = strtolower(Loader::parseName($controller, 1) . '/' . $action); } if (isset(self::$rules['name'][$name]) || isset(self::$rules['name'][$name2])) { throw new HttpException(404, 'invalid request:' . str_replace('|', $depr, $url)); } } return ['type' => 'module', 'module' => $route]; }
protected static function parseUrl($url) { $request = Request::instance(); if (0 === strpos($url, '/')) { // 直接作为路由地址解析 $url = substr($url, 1); } elseif (false !== strpos($url, '\\')) { // 解析到类 $url = ltrim(str_replace('\\', '/', $url), '/'); } elseif (0 === strpos($url, '@')) { // 解析到控制器 $url = substr($url, 1); } else { // 解析到 模块/控制器/操作 $module = $request->module(); $module = $module ? $module . '/' : ''; $controller = $request->controller(); if ('' == $url) { // 空字符串输出当前的 模块/控制器/操作 $url = $module . $controller . '/' . $request->action(); } else { $path = explode('/', $url); $action = Config::get('url_convert') ? strtolower(array_pop($path)) : array_pop($path); $controller = empty($path) ? $controller : (Config::get('url_convert') ? Loader::parseName(array_pop($path)) : array_pop($path)); $module = empty($path) ? $module : array_pop($path) . '/'; $url = $module . $controller . '/' . $action; } } return $url; }
/** * 执行应用程序 * @access public * @return void */ public static function run($config) { // 日志初始化 Log::init($config['log']); // 缓存初始化 Cache::connect($config['cache']); // 加载框架底层语言包 if (is_file(THINK_PATH . 'Lang/' . strtolower($config['default_lang']) . EXT)) { Lang::set(include THINK_PATH . 'Lang/' . strtolower($config['default_lang']) . EXT); } if (is_file(APP_PATH . 'build.php')) { // 自动化创建脚本 Create::build(include APP_PATH . 'build.php'); } // 监听app_init Hook::listen('app_init'); // 初始化公共模块 define('COMMON_PATH', APP_PATH . $config['common_module'] . '/'); self::initModule(COMMON_PATH, $config); // 启动session if (!IS_CLI) { Session::init($config['session']); } // 应用URL调度 self::dispatch($config); // 监听app_run Hook::listen('app_run'); // 执行操作 if (!preg_match('/^[A-Za-z](\\/|\\w)*$/', CONTROLLER_NAME)) { // 安全检测 $instance = false; } elseif ($config['action_bind_class']) { // 操作绑定到类:模块\controller\控制器\操作 if (is_dir(MODULE_PATH . CONTROLLER_LAYER . '/' . CONTROLLER_NAME)) { $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . CONTROLLER_NAME . '\\'; } else { // 空控制器 $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\empty\\'; } $actionName = strtolower(ACTION_NAME); if (class_exists($namespace . $actionName)) { $class = $namespace . $actionName; } elseif (class_exists($namespace . '_empty')) { // 空操作 $class = $namespace . '_empty'; } else { throw new Exception('_ERROR_ACTION_:' . ACTION_NAME); } $instance = new $class(); // 操作绑定到类后 固定执行run入口 $action = 'run'; } else { $instance = Loader::controller(CONTROLLER_NAME); // 获取当前操作名 $action = ACTION_NAME . $config['action_suffix']; } if (!$instance) { throw new Exception('[ ' . MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . Loader::parseName(CONTROLLER_NAME, 1) . ' ] not exists'); } try { // 操作方法开始监听 $call = [$instance, $action]; Hook::listen('action_begin', $call); if (!preg_match('/^[A-Za-z](\\w)*$/', $action)) { // 非法操作 throw new \ReflectionException(); } //执行当前操作 $method = new \ReflectionMethod($instance, $action); if ($method->isPublic()) { // URL参数绑定检测 if ($config['url_params_bind'] && $method->getNumberOfParameters() > 0) { switch ($_SERVER['REQUEST_METHOD']) { case 'POST': $vars = array_merge($_GET, $_POST); break; case 'PUT': parse_str(file_get_contents('php://input'), $vars); break; default: $vars = $_GET; } $params = $method->getParameters(); $paramsBindType = $config['url_parmas_bind_type']; foreach ($params as $param) { $name = $param->getName(); if (1 == $paramsBindType && !empty($vars)) { $args[] = array_shift($vars); } if (0 == $paramsBindType && isset($vars[$name])) { $args[] = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } else { throw new Exception('_PARAM_ERROR_:' . $name); } } array_walk_recursive($args, 'Input::filterExp'); $data = $method->invokeArgs($instance, $args); } else { $data = $method->invoke($instance); } // 操作方法执行完成监听 Hook::listen('action_end', $call); if (IS_API) { // API接口返回数据 self::returnData($data, $config['default_ajax_return']); } } else { // 操作方法不是Public 抛出异常 throw new \ReflectionException(); } } catch (\ReflectionException $e) { // 操作不存在 if (method_exists($instance, '_empty')) { $method = new \ReflectionMethod($instance, '_empty'); $method->invokeArgs($instance, [$action, '']); } else { throw new Exception('[ ' . (new \ReflectionClass($instance))->getName() . ':' . $action . ' ] not exists ', 404); } } // 监听app_end Hook::listen('app_end'); return; }
/** * 设置关联查询JOIN预查询 * @access public * @param string|array $with 关联方法名称 * @return Db */ public function with($with) { if (empty($with)) { return $this; } if (is_string($with)) { $with = explode(',', $with); } $i = 0; $currentModel = $this->options['model']; /** @var Model $class */ $class = new $currentModel(); foreach ($with as $key => $relation) { $closure = false; if ($relation instanceof \Closure) { // 支持闭包查询过滤关联条件 $closure = $relation; $relation = $key; $with[$key] = $key; } elseif (is_string($relation) && strpos($relation, '.')) { $with[$key] = $relation; list($relation, $subRelation) = explode('.', $relation, 2); } /** @var Relation $model */ $model = $class->{$relation}(); $info = $model->getRelationInfo(); if (in_array($info['type'], [Relation::HAS_ONE, Relation::BELONGS_TO])) { if (0 == $i) { $name = Loader::parseName(basename(str_replace('\\', '/', $currentModel))); $table = $this->getTable(); $this->table($table)->alias($name)->field(true, false, $table, $name); } // 预载入封装 $joinTable = $model->getTable(); $joinName = Loader::parseName(basename(str_replace('\\', '/', $info['model']))); $this->via($joinName); $this->join($joinTable . ' ' . $joinName, $name . '.' . $info['localKey'] . '=' . $joinName . '.' . $info['foreignKey'])->field(true, false, $joinTable, $joinName, $joinName . '__'); if ($closure) { // 执行闭包查询 call_user_func_array($closure, [&$this]); } $i++; } elseif ($closure) { $with[$key] = $closure; } } $this->via(); $this->options['with'] = $with; return $this; }
private function parseTemplate($template) { $request = Request::instance(); $depr = $this->config['view_depr']; $controller = Loader::parseName($request->controller()); if ($controller && 0 !== strpos($template, '/')) { if ('' == $template) { // 如果模板文件名为空 按照默认规则定位 $template = str_replace('.', DS, $controller) . $depr . $request->action(); } elseif (false === strpos($template, '/')) { $template = str_replace('.', DS, $controller) . $depr . $template; } } return str_replace('/', $depr, $template) . $this->config['view_suffix']; }
public function __call($method, $args) { if ($this->query) { switch ($this->type) { case self::HAS_MANY: if (isset($this->parent->{$this->localKey})) { // 关联查询带入关联条件 $this->query->where($this->foreignKey, $this->parent->{$this->localKey}); } break; case self::HAS_MANY_THROUGH: $through = $this->middle; $model = $this->model; $alias = Loader::parseName(basename(str_replace('\\', '/', $model))); $throughTable = $through::getTable(); $pk = (new $this->model())->getPk(); $throughKey = $this->throughKey; $modelTable = $this->parent->getTable(); $result = $this->query->field($alias . '.*')->alias($alias)->join($throughTable, $throughTable . '.' . $pk . '=' . $alias . '.' . $throughKey)->join($modelTable, $modelTable . '.' . $this->localKey . '=' . $throughTable . '.' . $this->foreignKey)->where($throughTable . '.' . $this->foreignKey, $this->parent->{$this->localKey}); break; } $result = call_user_func_array([$this->query, $method], $args); if ($result instanceof \think\db\Query) { return $this; } else { return $result; } } else { throw new Exception('method not exists:' . __CLASS__ . '->' . $method); } }
/** * BELONGS TO MANY 关联定义 * @access public * @param string $model 模型名 * @param string $table 中间表名 * @param string $foreignKey 关联外键 * @param string $localKey 当前模型关联键 * @param array $alias 别名定义 * @return Relation */ public function belongsToMany($model, $table = '', $foreignKey = '', $localKey = '', $alias = []) { // 记录当前关联信息 $model = $this->parseModel($model); $name = Loader::parseName(basename(str_replace('\\', '/', $model))); $table = $table ?: $this->db()->getTable(Loader::parseName($this->name) . '_' . $name); $foreignKey = $foreignKey ?: $name . '_id'; $localKey = $localKey ?: Loader::parseName($this->name) . '_id'; return $this->relation()->belongsToMany($model, $table, $foreignKey, $localKey, $alias); }
protected static function parseUrl($url, &$domain) { $request = Request::instance(); if (0 === strpos($url, '/')) { // 直接作为路由地址解析 $url = substr($url, 1); } elseif (false !== strpos($url, '\\')) { // 解析到类 $url = ltrim(str_replace('\\', '/', $url), '/'); } elseif (0 === strpos($url, '@')) { // 解析到控制器 $url = substr($url, 1); } else { // 解析到 模块/控制器/操作 $module = $request->module(); $domains = Route::rules('domain'); if (true === $domain && 2 == substr_count($url, '/')) { $current = $request->host(); $match = []; $pos = []; foreach ($domains as $key => $item) { if (isset($item['[bind]']) && 0 === strpos($url, $item['[bind]'][0])) { $pos[$key] = strlen($item['[bind]'][0]) + 1; $match[] = $key; $module = ''; } } if ($match) { $domain = current($match); foreach ($match as $item) { if (0 === strpos($current, $item)) { $domain = $item; } } self::$bindCheck = true; $url = substr($url, $pos[$domain]); } } elseif ($domain) { if (isset($domains[$domain]['[bind]'][0])) { $bindModule = $domains[$domain]['[bind]'][0]; if ($bindModule && !in_array($bindModule[0], ['\\', '@'])) { $module = ''; } } } $module = $module ? $module . '/' : ''; $controller = Loader::parseName($request->controller()); if ('' == $url) { // 空字符串输出当前的 模块/控制器/操作 $url = $module . $controller . '/' . $request->action(); } else { $path = explode('/', $url); $action = Config::get('url_convert') ? strtolower(array_pop($path)) : array_pop($path); $controller = empty($path) ? $controller : (Config::get('url_convert') ? Loader::parseName(array_pop($path)) : array_pop($path)); $module = empty($path) ? $module : array_pop($path) . '/'; $url = $module . $controller . '/' . $action; } } return $url; }
public function testParseName() { $this->assertEquals('HelloTest', Loader::parseName('hello_test', 1)); $this->assertEquals('hello_test', Loader::parseName('HelloTest', 0)); }
/** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed */ public static function module($result, $config, $convert = null) { if (is_string($result)) { $result = explode('/', $result); } $request = Request::instance(); if ($config['app_multi_module']) { // 多模块部署 $module = strip_tags(strtolower($result[0] ?: $config['default_module'])); $bind = Route::getBind('module'); $available = false; if ($bind) { // 绑定模块 list($bindModule) = explode('/', $bind); if (empty($result[0])) { $module = $bindModule; $available = true; } elseif ($module == $bindModule) { $available = true; } } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) { $available = true; } // 模块初始化 if ($module && $available) { // 初始化模块 $request->module($module); $config = self::init($module); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); $actionName = $convert ? strtolower($actionName) : $actionName; // 设置当前请求的控制器、操作 $request->controller(Loader::parseName($controller, 1))->action($actionName); // 监听module_init Hook::listen('module_init', $request); $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); if (is_null($instance)) { throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1)); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; } elseif (is_callable([$instance, '_empty'])) { // 空操作 $call = [$instance, '_empty']; } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } Hook::listen('action_begin', $call); $data = self::invokeMethod($call); return $data; }
/** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed */ public static function module($result, $config, $convert = null) { if (is_string($result)) { $result = explode('/', $result); } $request = Request::instance(); if ($config['app_multi_module']) { // 多模块部署 $module = strip_tags(strtolower($result[0] ?: $config['default_module'])); $bind = Route::getBind('module'); $available = false; if ($bind) { // 绑定模块 list($bindModule) = explode('/', $bind); if (empty($result[0])) { $module = $bindModule; $available = true; } elseif ($module == $bindModule) { $available = true; } } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) { $available = true; } // 模块初始化 if ($module && $available) { // 初始化模块 $request->module($module); $config = self::init($module); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); $actionName = $convert ? strtolower($actionName) : $actionName; // 设置当前请求的控制器、操作 $request->controller(Loader::parseName($controller, 1))->action($actionName); // 监听module_init Hook::listen('module_init', $request); try { $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); if (is_null($instance)) { throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1)); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; if (!preg_match('/^[A-Za-z](\\w)*$/', $action)) { // 非法操作 throw new \ReflectionException('illegal action name:' . $actionName); } // 执行操作方法 $call = [$instance, $action]; Hook::listen('action_begin', $call); $data = self::invokeMethod($call); } catch (\ReflectionException $e) { // 操作不存在 if (method_exists($instance, '_empty')) { $reflect = new \ReflectionMethod($instance, '_empty'); $data = $reflect->invokeArgs($instance, [$action]); self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); } else { throw new HttpException(404, 'method not exists:' . (new \ReflectionClass($instance))->getName() . '->' . $action); } } return $data; }
/** * 自动定位模板文件 * @access private * @param string $template 模板文件规则 * @return string */ private function parseTemplate($template) { // 分析模板文件规则 $request = Request::instance(); // 获取视图根目录 if (strpos($template, '@')) { // 跨模块调用 list($module, $template) = explode('@', $template); } if ($this->config['view_base']) { // 基础视图目录 $module = isset($module) ? $module : $request->module(); $path = $this->config['view_base'] . ($module ? $module . DS : ''); } else { $path = isset($module) ? APP_PATH . $module . DS . 'view' . DS : $this->config['view_path']; } $controller = Loader::parseName($request->controller()); if ($controller && 0 !== strpos($template, '/')) { $depr = $this->config['view_depr']; $template = str_replace(['/', ':'], $depr, $template); if ('' == $template) { // 如果模板文件名为空 按照默认规则定位 $template = str_replace('.', DS, $controller) . $depr . $request->action(); } elseif (false === strpos($template, $depr)) { $template = str_replace('.', DS, $controller) . $depr . $template; } } return $path . ltrim($template, '/') . '.' . ltrim($this->config['view_suffix'], '.'); }
/** * 设置关联查询JOIN预查询 * @access public * @param string|array $with 关联方法名称 * @return $this */ public function with($with) { if (empty($with)) { return $this; } if (is_string($with)) { $with = explode(',', $with); } $i = 0; $currentModel = $this->model; /** @var Model $class */ $class = new $currentModel(); foreach ($with as $key => $relation) { $closure = false; if ($relation instanceof \Closure) { // 支持闭包查询过滤关联条件 $closure = $relation; $relation = $key; $with[$key] = $key; } elseif (is_string($relation) && strpos($relation, '.')) { $with[$key] = $relation; list($relation, $subRelation) = explode('.', $relation, 2); } /** @var Relation $model */ $model = $class->{$relation}(); $info = $model->getRelationInfo(); if (in_array($info['type'], [Relation::HAS_ONE, Relation::BELONGS_TO])) { if (0 == $i) { $name = Loader::parseName(basename(str_replace('\\', '/', $currentModel))); $table = $this->getTable(); $alias = isset($info['alias'][$name]) ? $info['alias'][$name] : $name; $this->table($table)->alias($alias); if (isset($this->options['field'])) { $field = $this->options['field']; unset($this->options['field']); } else { $field = true; } $this->field($field, false, $table, $alias); } // 预载入封装 $joinTable = $model->getTable(); $joinName = Loader::parseName(basename(str_replace('\\', '/', $info['model']))); $joinAlias = isset($info['alias'][$joinName]) ? $info['alias'][$joinName] : $joinName; $this->via($joinAlias); if (Relation::HAS_ONE == $info['type']) { $this->join($joinTable . ' ' . $joinAlias, $alias . '.' . $info['localKey'] . '=' . $joinAlias . '.' . $info['foreignKey'], $info['joinType']); } else { $this->join($joinTable . ' ' . $joinAlias, $alias . '.' . $info['foreignKey'] . '=' . $joinAlias . '.' . $info['localKey'], $info['joinType']); } if ($closure) { // 执行闭包查询 call_user_func_array($closure, [&$this]); //指定获取关联的字段 //需要在 回调中 调方法 withField 方法,如 // $query->where(['id'=>1])->withField('id,name'); if (!empty($this->options['with_field'])) { $field = $this->options['with_field']; unset($this->options['with_field']); } } $this->field($field, false, $joinTable, $joinAlias, $relation . '__'); $i++; } elseif ($closure) { $with[$key] = $closure; } } $this->via(); $this->options['with'] = $with; return $this; }
protected static function parseUrl($url, $domain) { $request = Request::instance(); if (0 === strpos($url, '/')) { // 直接作为路由地址解析 $url = substr($url, 1); } elseif (false !== strpos($url, '\\')) { // 解析到类 $url = ltrim(str_replace('\\', '/', $url), '/'); } elseif (0 === strpos($url, '@')) { // 解析到控制器 $url = substr($url, 1); } else { // 解析到 模块/控制器/操作 $module = $request->module(); $domains = Route::rules('domain'); if (isset($domains[$domain]['[bind]'][0])) { $bindModule = $domains[$domain]['[bind]'][0]; if ($bindModule && !in_array($bindModule[0], ['\\', '@'])) { $module = ''; } } else { $module = $module ? $module . '/' : ''; } $controller = Loader::parseName($request->controller()); if ('' == $url) { // 空字符串输出当前的 模块/控制器/操作 $url = $module . $controller . '/' . $request->action(); } else { $path = explode('/', $url); $action = Config::get('url_convert') ? strtolower(array_pop($path)) : array_pop($path); $controller = empty($path) ? $controller : (Config::get('url_convert') ? Loader::parseName(array_pop($path)) : array_pop($path)); $module = empty($path) ? $module : array_pop($path) . '/'; $url = $module . $controller . '/' . $action; } } return $url; }
/** * 自动定位模板文件 * @access private * @param string $template 模板文件规则 * @return string */ private function parseTemplate($template) { if (empty($this->config['view_path'])) { $this->config['view_path'] = App::$modulePath . 'view' . DS; } if (strpos($template, '@')) { list($module, $template) = explode('@', $template); $path = APP_PATH . $module . DS . 'view' . DS; } else { $path = $this->config['view_path']; } // 分析模板文件规则 $request = Request::instance(); $controller = Loader::parseName($request->controller()); if ($controller && 0 !== strpos($template, '/')) { $depr = $this->config['view_depr']; $template = str_replace(['/', ':'], $depr, $template); if ('' == $template) { // 如果模板文件名为空 按照默认规则定位 $template = str_replace('.', DS, $controller) . $depr . $request->action(); } elseif (false === strpos($template, $depr)) { $template = str_replace('.', DS, $controller) . $depr . $template; } } return $path . ltrim($template, '/') . '.' . ltrim($this->config['view_suffix'], '.'); }
/** * 获取器 获取数据对象的值 * @access public * @param string $name 名称 * @return mixed */ public function __get($name) { $value = isset($this->data[$name]) ? $this->data[$name] : null; // 检测属性获取器 $method = 'get' . Loader::parseName($name, 1) . 'Attr'; if (method_exists($this, $method)) { return $this->{$method}($value, $this->data); } elseif (!is_null($value) && isset($this->type[$name])) { // 类型转换 $type = $this->type[$name]; if (strpos($type, ':')) { list($type, $param) = explode(':', $type, 2); } switch ($type) { case 'integer': $value = (int) $value; break; case 'float': if (empty($param)) { $value = (double) $value; } else { $value = (double) number_format($value, $param); } break; case 'boolean': $value = (bool) $value; break; case 'datetime': $format = !empty($param) ? $param : $this->dateFormat; $value = date($format, $value); break; case 'timestamp': $format = !empty($param) ? $param : $this->dateFormat; $value = date($format, strtotime($value)); break; case 'json': case 'array': $value = json_decode($value, true); break; case 'object': $value = json_decode($value); break; } } elseif (is_null($value) && method_exists($this, $name)) { // 获取关联数据 $value = $this->relation()->getRelation($name); // 保存关联对象值 $this->data[$name] = $value; } return $value; }
/** * 得到完整的数据表名 Mongo表名不带dbName * @access public * @return string */ public function getTableName() { if (empty($this->trueTableName)) { $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; if (!empty($this->tableName)) { $tableName .= $this->tableName; } else { $tableName .= Loader::parseName($this->name); } $this->trueTableName = strtolower($tableName); } return $this->trueTableName; }
/** * 一对一 关联模型预查询拼装 * @access public * @param string $model 模型名称 * @param string $relation 关联名 * @param Model $result 模型对象实例 * @return void */ protected function match($model, $relation, &$result) { $modelName = Loader::parseName(basename(str_replace('\\', '/', $model))); // 重新组装模型数据 foreach ($result->toArray() as $key => $val) { if (strpos($key, '__')) { list($name, $attr) = explode('__', $key, 2); if ($name == $modelName) { $list[$name][$attr] = $val; unset($result->{$key}); } } } if (!isset($list[$modelName])) { // 设置关联模型属性 $list[$modelName] = []; } $result->__set($relation, new $model($list[$modelName])); }