问题描述
这段时间在用php写一个cms应用消磨时间。框架选型用了CodeIgniter,这个框架整体上还是挺让人中意的——只是稍嫌不够灵活,需要做些额外的工作。
这些额外的工作中让人比较费心的是路径相关的问题:
- 多主题的路径问题
- 静态文件的路径问题
- site_url()提供的路径中端口号的问题
前两个问题,我觉得和CodeIgniter的定位有关:这个框架似乎是将自己定位为轻量级模板,适合用来开发小型应用,所以没有将多主题纳入设计方案。既然框架在设计之初就没有打算兼容多主题,官方对静态文件的处理方案(就是将其全部放在一个指定的目录下)也没什么好奇怪的了。
至于第三个问题,则是在解决前两个问题时遇到的一个惊喜:我的机器上的80端口已经被占用了,所以在开发时给apache分配了8082端口,不过在调用site_url()方法或redirect()方法时发现会跳转到“ http://127.0.0.1/xxx ”这样的路径上——ci将端口抹去了。
另外,需要说明下,目前使用的ci版本是:3.1.10 。
解决方案
针对每个问题说下解决方案。
多主题的路径问题
对多主题的路径,我的解决方案是在Loader层进行处理:创建MY_Loader
类并重写view()
方法,在view()
方法中将主题路径添加到原来的视图路径上。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Loader extends CI_Loader { /** * 视图页信息增强 * * @param $view string 要加载的视图页 * @param $vars array 视图页参数 * @param $return bool 是否有返回值 * @return object|string 加载的视图页内容 */ public function view($view, $vars = array(), $return = FALSE) { $theme = 'default'; $view = 'themes/' . $theme . '/' . $view; return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return)); } } |
这里的主题名称我用了硬编码,当然也可以选择通过配置文件或数据库获取。
静态文件的路径问题
对于静态文件,难点是如何将之和视图文件放在同一个主题目录下,并且可以方便的访问。
我的思路是直接把主题的根路径提供出来。
获取主题路径还得在Loader层完成。首先要获取网站$view_folder
(在index.php配置的)路径:
1 2 3 4 5 6 7 8 9 10 11 |
/** * 获取网站根路径(含视图路径) */ private static function base_url() { $base_url = get_instance()->config->base_url(); $view_path = rtrim(VIEWPATH, DIRECTORY_SEPARATOR); $idx = strrpos($view_path, DIRECTORY_SEPARATOR); $view_folder = substr($view_path, $idx + 1); return $base_url . $view_folder . '/'; } |
比如我目前正在写的项目,它的base_url就是这样的:
1 |
http://127.0.0.1/buffalo/user/themes/default/ |
然后在MY_Loader重写的views()方法中填上一个表示base_url的变量:
1 2 3 4 5 6 7 |
public function view($view, $vars = array(), $return = FALSE) { $theme = 'default'; $view = 'themes/' . $theme . '/' . $view $vars['base_url'] = self::base_url(); return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return)); } |
这样所有的视图页都能得到一个指向主题根路径的$base_url
变量,当访问静态资源的时候就可以拿来用了:
比如,我这里的一段程序:
1 2 3 |
<link href="<?= $base_url ?>/static/imgs/favicon.ico" rel="icon"> <link href="<?= $base_url ?>/static/css/bootstrap.min.css" rel="stylesheet" type="text/css" media="all"> <link href="<?= $base_url ?>/static/css/style.css" rel="stylesheet" type="text/css" media="all"> |
默认路径端口号的问题
关于前面提到的端口号的问题,出在CodeIgniter对系统根路径的解析上。
对此有一个比较简单的解决方法:就是在application/config/config.php中配置“base_url”变量。添加了这个配置后,CodeIgniter就不会再尝试自己解析系统根路径了。我不太喜欢这种方案,因为这会大大降低写出来的产品的灵活性。
还有一个方案就是修改CodeIgniter解析系统根路径的代码。我最后就是使用了这种方法,但也有些顾虑:这种修改势必会对升级CodeIgniter版本造成影响。还是说下这种修改是怎么实现的吧,相关的代码在system/core/Config.php中,找到构造方法__construct
,修改下相关的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if (isset($_SERVER['SERVER_ADDR'])) { if (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE) { $server_addr = '[' . $_SERVER['SERVER_ADDR'] . ']'; } else { $server_addr = $_SERVER['SERVER_ADDR']; } $server_port = 80; if (isset($_SERVER['SERVER_PORT'])) { $server_port = $_SERVER['SERVER_PORT']; } $base_url = (is_https() ? 'https' : 'http') . '://' . $server_addr . ($server_port === 80 ? '' : ':' . $server_port) . substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME']))); } |
其实也是蛮简单的。OK,就这样了。
######
发表评论