51

codeIgniter的多主题、静态文件及端口号的问题

 4 years ago
source link: https://www.tuicool.com/articles/yiqeUbr
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

问题描述

这段时间在用php写一个cms应用消磨时间。框架选型用了CodeIgniter,这个框架整体上还是挺让人中意的——只是稍嫌不够灵活,需要做些额外的工作。

这些额外的工作中让人比较费心的是路径相关的问题:

  1. 多主题的路径问题
  2. 静态文件的路径问题
  3. 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 ( ) 方法中将主题路径添加到原来的视图路径上。

代码如下:

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配置的)路径:

    /**
     * 获取网站根路径(含视图路径)
     */
    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就是这样的:

http://127.0.0.1/buffalo/user/themes/default/

然后在MY_Loader重写的views()方法中填上一个表示base_url的变量:

    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 变量,当访问静态资源的时候就可以拿来用了:

比如,我这里的一段程序:

	<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 ,修改下相关的逻辑:

     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,就这样了。

######


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK