背景

早晨碰到一个有关base_url()的小问题,遂追源码一通,如有错误请及时提出,共同进步

小问题,html中用到了<base>来指定基本url,加载如a、img、link、form会方便一点
手上项目前人这么写的

<base href="<?=base_url()?>assets/" target="_self">
<link href="global/plugins/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>

当时就想着为什么不写成

<base href="<?=base_url('assets')?>" target="_self">

然后资源就404了。印象中从哪看的base_url后会默认有/
然后就有了下面的了。


过程

1.base_url()有两个定义的地方,Core/config中,helpers/url_helper
          sublime-snipping
          
2.url_helper关键代码

if ( ! function_exists('base_url'))
{
    function base_url($uri = '', $protocol = NULL)
    {
        //这里有点乱,结论就是加载到core/config中    
        return get_instance()->config->base_url($uri, $protocol);
    }
}

         
3.core/Config关键代码

class CI_Config {
   
    public function __construct()
    {
        $this->config =& get_config();

        //自动设置base_url的值如果用户没提供
        if (empty($this->config['base_url']))
        {
            //正则匹配,如端口是8080就走这里
            if (isset($_SERVER['HTTP_HOST']) && preg_match('/^((\[[0-9a-f:]+\])|(\d{1,3}(\.\d{1,3}){3})|[a-z0-9\-\.]+)(:\d+)?$/i', $_SERVER['HTTP_HOST']))
            {
                $base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST']
                    .substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
            }
            else
            {
                //默认走这里
                $base_url = 'http://localhost/';
            }

            $this->set_item('base_url', $base_url);
        }
        log_message('info', 'Config Class Initialized');
    }
    
    //设置配置
    public function set_item($item, $value)
    {
        $this->config[$item] = $value;
    }
}

多说一下,$_SERVER['HTTP_HOST'],

'HTTP_HOST'
当前请求头中 Host: 项的内容,如果存在的话。

Http请求包头默认为

Host: localhost

接着说,我们的application/config中默认是这样的

$config['base_url'] = '';

过了config构造函数后

$config['base_url'] = 'http://localhost/';

接着追,core/Config.php

    public function base_url($uri = '', $protocol = NULL)
    {
        $base_url = $this->slash_item('base_url');
        //过了slash_item()返回的值还是http://localhost/
        //一般不带协议,默认http
        if (isset($protocol))
        {
            $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
        }

        return $base_url.ltrim($this->_uri_string($uri), '/');
        //返回的是指向一个资源的,排除了文件夹情况
    }
    
    public function slash_item($item)
    {
        if ( ! isset($this->config[$item]))
        {
            return NULL;
        }
        elseif (trim($this->config[$item]) === '')
        {
            return '';
        }
        //这时候config['base_url']值为http://localhost/
        return rtrim($this->config[$item], '/').'/';
        //rtrim — 删除字符串末端的空白字符,第二个参数为指定想要删除的字符列表
        //防止原始字符串后有多个//////,只保留一个
    }

  protected function _uri_string($uri)
    {
         //用户config文件中 $config['enable_query_strings'] = false
         
        if ($this->item('enable_query_strings') === FALSE)
        {
            //如果是数组,分解
            if (is_array($uri))
            {
                $uri = implode('/', $uri);
            }
            //去掉字符串两端的/,
            //我自己之前最常见问题
            //如 echo base_url('a/b/'),显示http://localhost/a/b
            return trim($uri, '/');
        }
        elseif (is_array($uri))
        {
            return http_build_query($uri);
        }

        return $uri;
    }    

总结

  走了这一遭,明白了一些碰见过的常见小问题

  <img src="<?php echo base_url().'/a/b'?>">

当时不解为什么base_url()后会加/,并且也没把url传参入函数只是单独拼接,uri还是当参数传入好


em0t
758 声望23 粉丝

Talk is cheap, show me the code


引用和评论

0 条评论