kn007的个人博客
♥ You are here: Home > 软件与网络 > php > 分享我的CDN钩子函数

分享我的CDN钩子函数

by | 184 Comments

提醒:本文最后更新于 3040 天前,文中所描述的信息可能已发生改变,请仔细核实。

20131101174108这段时间是忙碌的。新的一个月,总要写篇文章的,本来想放音乐的,但是觉得那些音乐,留在双十一放比较好,给个预告词:情殇。

言归正传,关于CDN的选择,我只知道七牛和又拍云。

关于七牛我是推荐给普通人的,因为他们大多是国内终端用户,追求的也是免费,并且七牛能一站式解决非结构化数据管理,对于用户来说,只要有我的函数(我即将分享的),直接跟那些卫生巾的效果一样,在平时操作完全木有感觉,却确确实实使用了。(省去用户上传文件到镜像服务器的步骤,只需转发地址即可)代表案例有weico+、csdn、豌豆荚等(除了csdn还算有点名气。。。)

又拍云呢,我只是推荐那些有钱的金主(不花钱不爽)和一些确实有需要的人们,又拍云在节点上和稳定程度(响应解析下载多方面对比),是比七牛好,不过其实大多时候其实两者也不分上下,不过又拍云的管理方式上,相对多样化,它可以有像七牛一样的镜像服务(需申请),也可以针对式存储图像空间,抑或是纯静态文件空间等等,除了第一种,其他的都要自行上传,或者利用API,另可定制做方案空间(详细可浏览其官网查看解决方案,或直接联系客服)。话说API相对成熟,也可以直接提要求。很多优点吧,普通人用不上的优点。属于收费服务,不贵。很便宜。代表案例有知乎、唱吧、天天动听、多看阅读、one一个(腾讯出品)、百姓网等。。(都是大客户)而且,而且,你会有个服务专员,可爱漂亮的妹子。。

CDN工作示例:
kn007cdn55e736d12f2eb9389ea637fcd4628535e4dde71191ef4fc8
接下来就是运用CDN时候,你需要替换那些(静态)文件的地址,手工太麻烦了,说实在的。。。一些简单函数(比如最初的七牛镜像插件),可能并不能对所有链接进行钩子,而且可能会出错。如何用个稍微进阶的函数来解决这些问题,请看如下:

<?php

/*
Build by kn007
*/

define('FocusCDNHost','https://kn007.net');//The blog's web address.
define('FocusCDNRemote','http://kn007.b0.upaiyun.com');//The new URL to be used for rewriting.
define('FocusCDNIncludes','wp-content,wp-includes');//Directories to include in static file matching.
define('FocusCDNExcludes','.php|.xml');//Excludes something from being rewritten if one of the above strings is found in the match.
define('FocusCDNRelative','');//Check this if you want to have links like <wp-content/abc.png> rewritten - i.e. without your blog's domain as prefix.

function do_cdnrewrite_ob_start() {
$rewriter = new FocusCDNRewriteWordpress();
$rewriter->register_as_output_buffer();
}
add_action('template_redirect', 'do_cdnrewrite_ob_start');

class FocusCDNRewriteWordpress extends FocusCDNRewrite
{
function __construct() {
$excl_tmp = FocusCDNExcludes;
$excludes = array_map('trim', explode('|', $excl_tmp));

parent::__construct(
FocusCDNHost,
FocusCDNRemote,
FocusCDNIncludes,
$excludes,
!!FocusCDNRelative
);
}
public function register_as_output_buffer() {
if ($this->blog_url != FocusCDNRemote) {
ob_start(array(&$this, 'rewrite'));
}
}

}

class FocusCDNRewrite {
var $blog_url = null;//String: the blog's URL
var $cdn_url = null;//String: URL of a CDN domain
var $include_dirs = null;//String: directories to include in static file matching, comma-delimited list
var $excludes = array();//Array: strings which indicate that a given element should not be rewritten (e.g. ".php")
var $rootrelative = false;//Boolean: if true, modifies root-relative links

function __construct($blog_url, $cdn_url, $include_dirs, array $excludes, $root_relative) {
$this->blog_url = $blog_url;
$this->cdn_url = $cdn_url;
$this->include_dirs = $include_dirs;
$this->excludes = $excludes;
$this->rootrelative = $root_relative;
}

protected function exclude_single(&$match) {
foreach ($this->excludes as $badword) {
if (stristr($match, $badword) != false) {
return true;
}
}
return false;
}

protected function rewrite_single(&$match) {
if ($this->exclude_single($match[0])) {
return $match[0];
} else {
if (!$this->rootrelative || strstr($match[0], $this->blog_url)) {
return str_replace($this->blog_url, $this->cdn_url, $match[0]);
} else {
return $this->cdn_url . $match[0];
}
}
}

protected function include_dirs_to_pattern() {
$input = explode(',', $this->include_dirs);
if ($this->include_dirs == '' || count($input) < 1) {
return 'wp\-content|wp\-includes';
} else {
return implode('|', array_map('quotemeta', array_map('trim', $input)));
}
}

public function rewrite(&$content) {
$dirs = $this->include_dirs_to_pattern();
$regex = '#(?<=[(\"\'])';
$regex .= $this->rootrelative
? ('(?:'.quotemeta($this->blog_url).')?')
: quotemeta($this->blog_url);
$regex .= '/(?:((?:'.$dirs.')[^\"\')]+)|([^/\"\']+\.[^/\"\')]+))(?=[\"\')])#';
return preg_replace_callback($regex, array(&$this, 'rewrite_single'), $content);
}

}

?>

该函数参考七牛镜像插件、w3tc插件等,放置于functions.php即可工作,有5个自定参数,分别为本地地址、远程地址、目录钩子、排除关键字、相对网址支持。具体应该不用多说吧?如果你有不明白的可以留言给我。

使用了该函数,你即可轻松使用cdn服务,告别手工修改(本来我认为也不会有人手工修改,大多利用插件。但据我所知,小天同学和大发同学就是一个个文件替换关键字的,我服了)

转载请注明转自:kn007的个人博客的《分享我的CDN钩子函数

donate
有所帮助?

Comments

184 Comments立即评论
  1. LV1回复

    加了ssl之后就用不了国内免费的cdn了,全不支持https,心很累 :x

    1. MOD回复

      @呵呵: 怎么会,七牛又拍不都有么

    2. LV1回复

      @kn007: 好像去年年底,七牛就不支持镜像加速了,又拍我一直都以为是支持的,直到几天前他们客服告诉我cdn不支持,图片文件神马的才行

    3. MOD回复

      @呵呵: 一直用文件空间。我自己写了自动上传AI,后续文章提到

    4. LV1回复

      @kn007: 没找到啊,你把链接发给我学习学习呗

    5. MOD回复

      @呵呵: 我是没发出来。。。没共享。。后续文章还没发。。

    6. LV1回复
  2. 回复

    哥们,用了你这个,确实很犀利。感谢分享。

    我无意中发现个问题,用define('FocusCDNExcludes','.php|.xml')这种排除的方式,貌似会把wp-content|wp-includes 中的某些ajax请求都干掉。

    比如我有个评论是ajax请求,请求的php文件在theme里面,这个会把主题里面的ajax.php类似这样的异步请求都换为cdn的url。

    我换了个方式:
    define('FocusCDNExcludes','.js|.css|.png|.jpg|.jpeg|.gif|.ico');

    protected function exclude_single(&$match) {
    foreach ($this->excludes as $badword) {
    if (stristr($match, $badword) == true) {
    return false;
    }
    }
    return true;
    }

    这样就好了。

    1. MOD回复

      @宅女吧: 正常是不会,你单纯这样说,我无法再现。
      不过解决了就好

  3. 我用的是阿里云的oss和cdn,感觉也还不错。

    1. MOD回复

      @街头诗人: 挺快的,ocs、rds和oss不错

  4. 回复

    貌似在php7下失效了

    1. MOD回复

      @neveta: 我还没升级到php7。没时间。
      如果可以,把wp-config.php的debug打开,看下是什么原因,然后发给我。

    2. MOD回复

      @neveta: 解决了么?我直接用预编译的php7的执行,没有问题啊。

    3. 回复

      @kn007:

      嗯,还没空搞呢,暂时用qiniu的钩子代码替代了,有空再看看:)

    4. MOD回复

      @neveta: 嗯,好的,我在PHP7测试是没问题的,在命令行环境下。

    5. MOD回复

      @neveta: PHP7下没问题,我试了。。

  5. 回复

    您好,因为代码用的早,在网上搜的,后来没有找到作者,就分享了,非常抱歉,我已经增加了作者,如果有其他要求还请告知,我会在收到消息第一时间更改

    1. MOD回复

      @自由草: 客气了,也非常感谢。
      不好意思,最近心情不好,有点愤青了。
      语气不善之处,还望见谅。

  6. 还是插件来的方便一些,不过代码应该效率更高一些了!现在七牛插件集成的东西太多了! :smile:

    1. MOD回复

      @明月登楼: 嗯,我这个简单实用

  7. 这个可以有

    1. MOD回复

      @荒野無燈: 欢迎试用

    2. MOD回复

      @荒野無燈: 听说github封你账号了,默哀。。。看来有时间我也要换个地可能。。。
      V2有点乱,看你之前star的是通过接口找回来了。代码有备份问题不大,应该还好。。

    3. @kn007: 谢谢。 已经通过接口找回来了。但是仓库全没了。重新同步一次,头也大。
      我现在其实主要用bitbucket, 私有仓库,从来不会出问题。
      另外,由于这次事件,加开通了gitlab和国内的几家。

    4. MOD回复

      @荒野无灯: 客气了,只希望commit记录在,要不有时候找问题有点麻烦。。
      回头我也要备份一下。。。

icon_wink.gificon_neutral.gificon_mad.gificon_twisted.gificon_smile.gificon_eek.gificon_sad.gificon_rolleyes.gificon_razz.gificon_redface.gificon_surprised.gificon_mrgreen.gificon_lol.gificon_idea.gificon_biggrin.gificon_evil.gificon_cry.gificon_cool.gificon_arrow.gificon_confused.gificon_question.gificon_exclaim.gif