成航先森 成航先森

成都航院计算机系一个学生的个人博客

 

随便看看:

分段图 anylinkaria2CDNkeepalivedLinuxmysqlnginxpycharmpythonredisrsyncUEditorWordPressWordPress插件七牛九价体育部信息志愿服务队光猫免流全体例会向党组织靠拢团学会学习部宣传部影视相关心理部成都航院报社招生信息教学资源文艺部毕业就业流量活动生活杂谈社会实践部站长经历系部介绍系部动态纪检部组织部经验分享老师腾讯云资源下载路由器轻松时刻高考录取分数线

标签:WordPress插件

修复anylink增加Redis缓存后存在的bug

脚本编程, WordPress技巧修复anylink增加Redis缓存后存在的bug

标签:, , | 4 条评论 | 2022-04-04

先森最近更新了一篇文章,发布后先森自己没有去看,今天去看了一眼,结果突然发现这篇文章中所有的外链没有自动转成内链。以前优化SEO的时候,看到的优化建议基本都有不要直接跳转到外链,会导致权重降低,所以先森一直都有用anylink这个插件来实现这个功能。对于anylink这个插件,先森的使用体验还是非常好的,之前一共还发过三篇博文:WordPress为anylink插件外链跳转添加漂亮的跳转页面WordPress:WPJAM BASIC插件与anylink冲突WordPress优化:为anylink插件增加缓存既然发现了问题,那么就得解决问题,正好是清明节放假期间,托疫情的福先森哪里也不好去,所以来会会这个bug。排查过程首先,出现没有转内链的文章只有先森最新发布的那一篇,之前的文章都是正常的。1、怀疑缓存可能是CDN有缓存,先森将本机hosts改成源站,直接访问源站,测试依旧正常,pass。除了CDN,先森WordPress还有缓存,先森用的是插件wp-super-cache进行缓存。先森清理了插件缓存后,问题依旧;然后想是不是插件有问题,直接将wp-super-cache插件停用了,问题依旧。2、怀疑anylink插件排除了缓存的问题,先森又想是不是anylink插件自己出了什么问题,先森将anylink插件停用后再启用,发现问题依旧,插件运行问题pass。然后先森考虑是不是插件在本篇文章的执行有问题,开debug看一看。先森在WordPress的wp-config.php中打开了dubug:define( 'WP_DEBUG', true );define( 'SAVEQUERIES', true );先森开debug主要是想看本篇文章中的SQL查询,所以在后台开启了Debug Queries插件,结果开启后并没有看到anylink的查询,然后先森想到了为anylink添加redis缓存这篇文章中,已经将相关的SQL查询优化了,这样debug确实已经看不到去MySQL的查询了。此时先森已经开始怀疑是不是当时优化有什么bug了,但还是需要先确认一下是不是MySQL、Redis数据库有问题。3、怀疑数据库有问题先森的MySQL是云数据库,Redis是部署在源站本机的。MySQL运行肯定没有问题, 不然就不只是外链有问题了;Redis检查后发现也是正常运行的。先森再去看anylink的MySQL表,发现wp_al_urls表里是有出问题这篇文章的外链转内链对应表的,这就奇怪了,到这里MySQL的问题排除了,先森就怀疑是自己之前的优化存在问题了。4、怀疑优化存在BUG先森本来想直接在redis里查有问题文章的缓存,但是redis的key太多了,先森已经忘了key是什么规则了,所以就先去研究了一下anylink的代码,先搞清楚之前先森的优化。首先确认到,先森优化的是插件的classes/al_filter.php文件,优化了getAllLnks()和get_slug_by_url()这两个类中的函数,增加了先查redis缓存,没有再查数据库并将结果存到redis的代码。修改的部分这两个函数先森研究了一下,get_slug_by_url()这个函数是用在把留言者的链接转换成内链的,所以出现问题的不可能是这个函数,那只能是getAllLnks()这个函数了。getAllLnks()这个函数保存缓存的key是‘getAllLnks:’开头的,后面跟的是文章的id,先森就去redis查相关key。应该是redis的key不支持冒号,所以实际存储的key是‘getAllLnks-’开头的。先森发现有问题的文章ID是1968,所以它的key是‘getAllLnks-1968’,先森先查的是正常文章的key,查出来是一大堆的内容,而查到1968就发现明显有问题:getAllLnks有问题这个key的内容简直就没有内容,按逻辑来想起码有两个内容:外链地址、内链地址,将这个key删除,然后重新访问有问题的文章,发现外链就已经自动转为内链了,此时再来查redis的key查询结果,正常多了:getAllLnks正常结果至此,问题已经临时得到了解决,但是原因还需要分析一下。出现bug的原因一开始,先森以为这个问题原因是anylink在管理员登录时不会处理外链,先森预览文章被缓存了,但是找了一圈anylink的代码,没有找到判断管理员是否登录的代码,所以应该不是这个原因。好好想了一下,发现bug的原因应该是这个:当文章还在编辑的过程中,预览文章,由于此时文章还没有外链,所以数据库查询结果为空,但是这个空结果被先森的代码保存到Redis中了,由于Redis的缓存没有设置过期或到期时间未到,先森也没有设置redis缓存更新,导致后续anylink插件来查询这篇文章的外链时一直是空的。解决方案问题原因找到了,就好解决了,先森想到了两个解决方案:方法1:管理员登录时anylink不处理链接方法2:文章发布、变更时更新anylink的缓存第一种方法,管理员登录时,尤其是正在编辑文章时,预览文章不会造成错误的key被redis缓存。但此方法还是有bug,管理员未来更新文章时新增了其他外链,此时由于Redis已经缓存了这篇文章的外链查询情况,如果改缓存未过期,新增的外链在文章中会出现未被转换的情况。且这种方法容易造成管理员视角和访客视角不同,先森用的其它插件有类似设定,实际使用中会让人比较头疼,所以先森不太希望使用这种方式进行修复。相较而言,第二种方法就要合理的多,只要文章有变动,那就把anylink该文章的redis缓存删了,有人访问该文章时再缓存。实现也比较简单,在自己的主体function.php最后加一个publish_post钩子,实现这个需求:/** * 更新或发布文章清理Redis缓存 * 增加时间:2022-04-04 12:43:00 * By:https://www.capjsj.cn/ */function Clean_Redis($post_ID){ wp_cache_delete( 'getAllLnks:'.$post_ID );}add_action('publish_post', 'Clean_Redis', 0);来测试一下,在管理后台随便更新了一篇已发布的文章,发布前查询该文章的redis缓存,刷新后再去查询,该文章的key已经查不到数据了。测试hook删除redis缓存2020年埋下的bug终于在2022年被修复了,还好期间先森新发布的文章只有2021两篇(有点惭愧),且不涉及外链,所以影响不大。按理说也会影响到旧文章的更新,但是先森最近几年对博客这边的关注实在太少,影响着实不大。无论怎样,写代码还是的考虑周到一点,还好先森不是程序员,只是一枚小运维。

WordPress优化:为anylink插件增加缓存

WordPress技巧WordPress优化:为anylink插件增加缓存

标签:, , , | 2 条评论 | 2020-11-24

先森最近在梳理网站的代码,想办法为网站加速,主要从代码、软件、网络层面进行优化,这一切都是从网站切换到HTTPS开始的。先森已经连续观察了多日的CDN了,目前也就到了查缺补漏的阶段了。先森还将整个网站目前备份到了另一台服务器,将网站在本地解析到这台服务器上,开始了对代码的检查。开启了debug,把大的一些问题都处理了,然后也把主题的代码理了一遍,并且网站也加上了Redis缓存。但是先森发现,即使加上了Redis,有时候网页打开生成时间还是得一秒多,先森就很纳闷,一直想搞明白到底是什么情况。排查工具很早以前,先森就在主题的footer.php末尾,添加了下面的代码,以便于登录之后可以看到当前网页的查询次数,生成时间:<?php if (is_user_logged_in()){    echo "<pre>".get_num_queries().'次查询,用时';    timer_stop(3);    echo '秒</pre>';?>这个代码网络上到处都是,相信很多人都添加的有。先森网站加Redis之前,网页的查询次数都是150+次,生成时间2-3秒,甚至更多。用上之后减少到50+次,但是有时还是会需要1秒多,让先森百思不得其解。然后先森把主题代码该优化的都优化后,查询次数30+次,生成时间降到1秒左右,但是先森还是不太满足,所以想看看到底是执行了哪些查询,然后就在网上找到了这段代码,和上面的有些类似。首先需要先在WordPress的根目录配置文件wp-config.php中添加保存查询的代码:define('SAVEQUERIES', true);然后也是在footer.php的网页最后部分添加打印代码:<?phpif (current_user_can('administrator')){    global $wpdb;    echo "<pre>";    print_r($wpdb->queries);    echo "</pre>";}?>但是先森添加后看了一下,差点当场去世,这样打印出来的是一个很大的多维数组,看的人眼花缭乱,重点是太长了还显示不全。先森将打印复制出来,拿到NotePad++里面打开,依旧显得很乱。查询的打印不过大概看了一下,大数组的每一个键值表示一个查询,然后一个查询数组了,第一个值是执行的SQL,第二个值是使用的时间,第三个值是调用的代码位置。其实可以用循环做一个网格,让前端显示看着方便一点,但是先森很懒,网上看了一下,有插件可以做到相关功能,且不用修改wp-config.php,即Debug Queries,所以先森就懒得自己写了,直接装了一个来进行排查。需要注意的是,Debug Queries很久没有更新了,安装可能会报错,不过还是可以正常使用的。其实Debug Queries介绍页也推荐使用Debug Objects插件,但是先森试了一下Debug Queries可以用,也就懒得再试另一个插件了。排查问题工具准备好了,先森就来好好排查到底是哪里查询比较慢了。插件装好了,再去看打印出来的查询信息,就比较清晰了。先森对比了一下,大部分的查询都是0.00x秒的,就是几毫秒的,但是只要涉及到wp_al_urls的查询,就会是即时甚至上百毫秒。wp_al_urls的查询先森看了一下,这个表是插件anylink的,这个插件主要是将网站上的外链全都转化成内链,点击后可以跳转到外链。对于anylink,先森这里也发过两篇相关的文章:WordPress为anylink插件外链跳转添加漂亮的跳转页面WordPress:WPJAM BASIC插件与anylink冲突这个插件先森也是从建站伊始就在用了,是一个很好用的插件,但没有想到这个插件会出现慢查询。通过上面的截图可以看到,对wp_al_urls的查询条件是网站链接,看了一下数据库,这个SQL是为了去拿到内链的slug记录:anylink获取slug这里去查的,实际上是网页正文里的外链、各位评论大佬的网址对应的内链地址。先森看了一下这个表,没想到竟然有10M的大小,接近10万条数据,而且这里查询的是al_origURL字段,先森看了一下,这个字段是没有索引的。解决问题对于MySQL的查询,先森能想到的优化方法就是加索引,所以先森直接就操作加索引,但是报错了:给al_origURL字段加索引报错看报错是跟字段格式有关的,看了一下这个字段的类型是mediumtext的,这个字段是存URL的,有些URL非常的长,如果该varchar的话,可能会出问题,varchar最长255个字符。网上找了一阵子解决方案,都是说text相关的类型无法加索引。先森本来就对数据库索引什么的不太了解,所以只能放弃这条路。先森还能想到的办法,就是看下这个查询的代码,想办法把结果存到Redis上缓存起来。至于怎么找到实际执行的代码,先森看了一下,直接找调用的最后一段就可以了。找到慢查询的调用代码可以看到,两个SQL实际上是一样的,查的是同个网址,结果执行的时间竟然都比较长,所以确实得把结果缓存起来。为了优化代码,先森把整个网站都作为了一个PhpStorm里的一个项目,不得不说一个好的IDE工具写起代码来是真的舒服。直接全局搜索,寻找get_slug_by_url这个函数,顺利找到了代码所在。搜索get_slug_by_url函数这里有两个结果,第一个是原本的函数,已经被先森注释起来了,第二个是先森改了之后的。可以看到这个函数就是调用$wpdb来执行SQL语句,将得到的结果再返回一下。函数比较简单,也很利于先森修改。然后先森又找了一下WordPress如何添加缓存,结果找到一下,发现非常简单。WordPress操作缓存WordPress 为我们提供了使用对象缓存的函数,方便我们使用对象缓存。wp_cache_add() :添加数据到缓存中,如果数据已存在,返回 flasewp_cache_set() :添加数据到缓存中,如果数据已存在,会覆盖数据wp_cache_get() :获取缓存中的数据,如果数据不存在,返回 falsewp_cache_delete() : 从缓存中删除数据wp_cache_replace() :替换缓存中的数据,类似 wp_cache_set,但是如果数据不存在,不自动添加wp_cache_flush():清除所有缓存如果没有装redis缓存插件,上面的这些函数是在./wp-includes/cache.php里。如果装了Redis Object Cache等插件,就会自动增加一个./wp-content/object-cache.php文件,这些函数也会存在于这个文件中,用于存入缓存。WordPress 对象缓存使用使用示例$result = wp_cache_get( 'my_result' );if ( false === $result ) {    $result = $wpdb->get_results( $query );    wp_cache_set( 'my_result', $result );}对anylink的get_slug_by_url函数改造有了上面这个案例,先森为anylink的函数增加缓存就很方便了。示例很简单,get_slug_by_url函数本身也简单,所以改造后如下:public function get_slug_by_url( $url ) { $arr_slug = wp_cache_get( $url ); if ( false === $arr_slug ) { global $wpdb; $arr_slug = array(); $arr_slug = $wpdb->get_row($wpdb->prepare( "SELECT * FROM " . ANYLNK_DBTB . "  WHERE al_origURL = %s", $url ), ARRAY_A); wp_cache_set( $url, $arr_slug ); } return $arr_slug;}因为示例和函数太契合了,所以这个函数几乎就和示例结构一样。首先去Redis获取缓存数据,获取不到就去MySQL查询,查到后再存到Redis。2022年4月4日更新:此代码存在亿点点bug,修复参考此文章:修复anylink增加Redis缓存后存在的bug检查效果代码修改后,同步到测试服务器,访问了两次之前访问的页面,查询次数和用时都降下来了。然后看到查询次数还是有33次,其中有部分是查询wp_al_urls_index这个表的,虽然速度不慢,但是次数比较多,先森重复上面的方法也修改了一下相关函数,最终效果如下图:最终效果查看Redis的keys上面改造的代码中,是拿url地址去做的key名称,那么先森也来看下缓存数据在Redis里的情况:redis的缓存上面改造的代码比较简陋,直接拿的URL做的key名称,如果URL比较短还好,如果长的话就可能出现问题,key名称其实可以做一下长度限制。提示:Redis最好不要使用默认端口6379,除非安全做的非常好。使用Redis时注意以下几点:1、一定要配置强密码;2、安全组、防火墙一定要最小范围放通Redis端口,即针对指定IP放通访问;3、尽量不要使用默认端口。因为Redis而导致服务器中木马病毒的保障,先森这边经常遇到。总结先森以前以为给WordPress配上Redis很麻烦,实际使用发现真香,建议有能力的朋友都上一下,毕竟生命不止,折腾不息。本文最主要的还是记录一下排查网页查询慢的过程和解决方法,希望能够给其他朋友提供思路。

CDN后用Ajax动态提交、显示文章阅读量,cookies避免重复刷新

WordPress技巧CDN后用Ajax动态提交、显示文章阅读量,cookies避免重复刷新

标签:, , | 16 条评论 | 2017-08-29

上篇文章解决了WordPress加入CDN后“非插件浏览次数统计”浏览次数不刷新问题,同时留下了两个未解决的问题:1.按F5可无限制刷新文章访问量,并影响数据库效率;2.只解决了后台不更新问题,前台显示还是得等CDN刷新后才能更新。那么这篇文章就是为了解决以上两个问题。问题分析第一个问题,先森想到的解决方法是用JS代码创建cookies,如果cookies存在就不在更新后台的统计量。第二个问题,直接让ajax获取后台的访问量,修改前台显示的访问量就行了。一开始,先森配置的让ajax多传一个参数,是判断cookies是否存在的,存在为1,不存在为0。若cookies不存在,则后台访问量统计就+1,并返回数据库中的浏览量并+1。若cookies存在,则后台不增加访问数量,直接返回数据库中的浏览量并+1,如此访客刷新也不会增加访问量了。但是这样还是存在会在后台查询数据的问题,查询多了对数据库也是一种负担。先森之前没有意识到这个问题,结果还是晚上睡觉前反思发现了,且也琢磨除了一个更好的解决方法。直接在JavaScript代码中加判断,如果cookies已存在,则直接不向后端服务器发数据。这样一来,前端再怎么刷新,也停留在CDN的层面上。那么要实现这种效果,就需要先实现不向后端服务器发送数据,也能获取到当前文章的访问量。解决方法很简单,第一次获取访问量时,将后端服务器返回的访问量直接写入cookies,下次刷新时,直接从cookies中读取访问量。另外,还有一个地方需要解释一下,cookies的过期时间。如果cookies时间太长了的话,那么未免还是会损失一些访问量,所以先森就没有设置cookies的过期时间,保持默认。cookies的默认过期为关闭浏览器,先森觉得,这样一来还是比较合理的。同时,一个访客,可能并不会只打开本站一篇文章就关闭,打开多篇文章时,每篇文章的访问量是不一样的,需要从cookies中获取的话,cookies的名称就必须不一样。不然访问打开其他文章,看到了访问量都是同一个数值。解决方法就是,已“固定值+文章ID”的方式,确定cookies名称的唯一。效果实现上一篇文章中,先森是模仿通用的评论ajax提交的处理方式,自建了一个类似的php。但这样可能有点不安全,也有点麻烦,所以先森还是研究着将php代码部分放进了主题的functions.php。首先还是在footer.php中添加ajax的代码,注意需要将前台显示访问量的标签ID或class名称改成自己的。<script type= "text/javascript" > function GetCookie(sName) {    var arr = document.cookie.match(new RegExp("(^| )"+sName+"=([^;]*)(;|$)"));    if(arr !=null){return unescape(arr[2])};    return null;}var postviews_cook=GetCookie("postviews<?php the_ID();?>");  if ( postviews_cook == null ){$.ajax({ type:'POST', url: "<?php echo admin_url('admin-ajax.php');?>" , data:"postviews_id=<?php the_ID();?>&action=postviews",cache:false,success: function(postviews_count){ $("#views").text('阅读:' + postviews_count + ' 次');document.cookie="postviews<?php the_ID();?>=" + postviews_count;} });   }  else{$("#views").text('阅读:' + postviews_cook + ' 次');}; </script><?php endif ; ?>然后直接在自己主题的functions.php中添加下面的代码:/** 缓存时更新浏览量-有缓存* //www.capjsj.cn/ajax_cookies_views.html*/function postviews_cache(){    if( empty( $_POST['postviews_id'] ) ) return;        $post_ID = $_POST['postviews_id'];        if( $post_ID > 0 ) {                $post_views = (int)get_post_meta($post_ID, 'views', true);/*if( !defined( 'WP_CACHE' ) || !WP_CACHE ){ 以前的错误代码*/if( defined( 'WP_CACHE' ) && WP_CACHE ){ //如果wp-config.php开启缓存    update_post_meta($post_ID, 'views', ( $post_views + 1 ));}                echo ( $post_views + 1 );                exit();        }}add_action( 'wp_ajax_nopriv_postviews', 'postviews_cache' );add_action( 'wp_ajax_postviews', 'postviews_cache' );2018年06月07日更新:感谢网友@鱼鱼 在评论区指出的BUG,以前写上面的代码的时候参考了wp-postviews插件wp-postviews.php里面的代码,结果学艺不精,只看了上半截,忽略了下半截。错误的代码竟然用了近1年的时间没发现,还发布在这里误人子弟,实在羞愧。上面的代码中,错误的代码依然留存着,只是注释了,修改的方法有两种,第一种是上面那样,第二种则是将10-12行的if段改为下方模式(这种就是wp-postviews插件的写法):if( defined( 'WP_CACHE' ) && WP_CACHE ) //如果wp-config.php没有开启缓存    return;                             //退出(中止函数的运行)    update_post_meta($post_ID, 'views', ( $post_views + 1 ));注意,如果网站的WordPress只加入了CDN,没有使用缓存插件的话,需要将上面代码改成下面的,也就是删除开启缓存判断:/** 缓存时更新浏览量-无缓存* //www.capjsj.cn/ajax_cookies_views.html*/function postviews_cache(){    if( empty( $_POST['postviews_id'] ) ) return;        $post_ID = $_POST['postviews_id'];        if( $post_ID > 0 ) {                $post_views = (int)get_post_meta($post_ID, 'views', true);                update_post_meta($post_ID, 'views', ( $post_views + 1 ));                echo ( $post_views + 1 );                exit();        }}如果想使用有缓存的版本,想要开启网站缓存,可以选择安装缓存插件,或者直接在网站根目录的wp-config.php中,加入下面这行代码:define('WP_CACHE', true);如果网站没有加入CDN,也没有使用缓存插件,那么有两个选项:1、Ctrl + D 保存本页到书签,待文章变成静态页面后再拿出来看看;2、Ctrl + W 关闭本页,因为除非你要研究代码,本页对你没有什么价值,看看更多该看的吧。总结对于本文的解决方案有什么意见和建议,希望能够在下方评论栏中提出来,先森觉得还有能够改进的地方,但一人之力实在有些相形见绌。ajax是个很实用的东西,可能还有更多可以使用的地方,先森也得好好想想。

解决WordPress加入CDN后“非插件浏览次数统计”浏览次数不刷新问题

WordPress技巧解决WordPress加入CDN后“非插件浏览次数统计”浏览次数不刷新问题

标签:, , | 6 条评论 | 2017-08-25

不知道多少人和先森一样,在最初接触wordpress的时候,被网上的各类教程灌输了“能用代码版,就不用插件”的概念。先森就本着这个概念,在文章的访问量的时候,先森就找的代码版。网上提供的代码版浏览次数统计功能的文章,名称都差不多,类似“WordPress非插件添加文章浏览次数统计功能”这种比比皆是。先森应该是在wordpress大学看到的教程,关于教程先森就不再赘述了。本文主要解决的是,开启CDN后,用这种代码版访问量统计的方式浏览次数不再刷新的问题,如果想结合着来使用的话,统计代码部分可以去wordpress大学看《WordPress非插件添加文章浏览次数统计功能》这篇文章。浏览次数问题分析先森其实很早就意识到,开启CDN后,其实浏览量不是不刷新,而是只在首次缓存的时候才会增加一次。因为只有第一次访问的时候才会执行php,缓存后就直接访问的html了,所以就不会增加统计了。所以解决问题的方式,是让html也能统计到浏览次数,先森认知中的方法就只有一个:ajax。然而当初先森虽然知道问题原因,知道解决方式,但奈何先森代码能力不强,当时没能解决。先森始终认为,一个问题如果死活解决不了,那么就先放放,过段时间再反顾可能就会发现,这个问题根本就不是事。当然,这个时间可能就有点久了,起码就ajax这个问题,先森等了一两年。。。。先森想到的用ajax更新浏览次数的方法就是,使用ajax提交文章的ID给后方的php,后方的php接收到文章ID后,将该文章的浏览次数+1。效果实现先森研究了一晚上,发现要解决还是挺简单的。又是研究几小时,分享几分钟,心塞。首先,在footer.php中添加ajax的代码,注意url的地址要改为自己的php路径:<?php if  (is_singular()) : ?>  <!-- ajax post view -->  <!-- ajax post view -->  <script type= "text/javascript" >$.ajax({ type:'POST', url: "//www.capjsj.cn/wp-content/themes/*/*.php" ,   /*此处需要修改为自己的php路径*/data: { "postviews_id" : "<?php the_ID();?>" } });   </script><?php endif ; ?>接收数据的php代码很简单,参考了评论的comments-ajax.php的头部,禁止直接访问,然后加上了几行更新浏览量的代码。将下面内容保存到一个php文件中,放入自己的wordpress主题里面,将该php的访问链接加入到上面的url中:<?php//禁止直接访问本phpif ( 'POST' != $_SERVER['REQUEST_METHOD'] ) {        header('Allow: POST');        header('HTTP/1.1 405 Method Not Allowed');        header('Content-Type: text/plain');        exit;}require( dirname(__FILE__) . '/../../../wp-load.php' );nocache_headers();$post_ID = $_POST['postviews_id'];$post_views = (int)get_post_meta($post_ID, 'views', true);update_post_meta($post_ID, 'views', ($post_views+1));?>如此一来,即使加入了CDN,文章页面变成了静态页面,后台也会更新访问次数了。总结这样仅仅是解决了文章页面被缓存后,浏览次数无法被统计到的问题,但是还并不完善。上面的功能实现之后,你会发现,每一次刷新浏览次数都会加一,如果有人一直按着F5,那么增加的浏览次数就有点恐怖了。这样还会增加服务器的负担,像先森这种把网站放在阿里云虚拟主机的,若负载过量还会直接关停,被人这样搞的关机先森就哭了。所以,下篇文章先森会分享使用cookies来限制访问次数无限增加的问题。另外,除了访问量持续增加的问题,还有一个地方可以优化。既然ajax能够异步提交数据,那么能不能动态的修改文章中的浏览次数呢?答案是肯定的,先森也会在下一篇文章中更新。关于上面的问题,请查看下一篇文章:CDN后用Ajax动态提交、显示文章阅读量,cookies避免重复刷新

WordPress:WPJAM BASIC插件与anylink冲突

WordPress技巧WordPress:WPJAM BASIC插件与anylink冲突

标签:, | 4 条评论 | 2017-02-20

很久没有管过博客了,最近发现博客里的跳转链接全都失效了,点击只能跳转到首页。通过审查元素查看,是从末尾不加斜杠的链接301跳转到加个斜杠的链接。无论如何,结局就是跳转失败了。周末一个闲着无事,就想着解决一下这个问题。通过漫长的排除,发现问题是安装了WPJAM BASIC插件的问题,停用了之后跳转链接就正常了。WPJAM BASIC插件不得不吐槽一下水煮鱼,之前用这WPJAM七牛镜像存储,有一天发现可以升级了,随手就点了升级,结果升级后发现,要启用这个插件,还需要另外装一个WPJAM BASIC。然后装了发现启动不了,后来看报错是插件里的函数和先森主题的函数冲突了,先森注释了自己主题里的函数后,插件可以启动了。因为先森有保留函数来源的习惯,所以先森检查那个冲突函数发现,这TM就是从水煮鱼网站拷贝的函数。这个插件果然是各种功能的集合,但总有一种强制消费的感觉,隐隐让人不爽。anylink这个插件先森自建立博客以来就一直在用了,用着已经习惯了,虽然有代码版但也不想去弄了,觉得还是有操作页面的比较实用。先森更是用anylink与张戈博客的跳转美化界面做了结合,还专门发布了一篇文章:WordPress为anylink插件外链跳转添加漂亮的跳转页面所以,先森对于anylink这个插件是非常难以抛弃的。但是很棘手的是,为什么WPJAM BASIC插件会与anylink插件起冲突,如何解决。而先森已经在七牛图片处理样式的正确使用方式一文中提到,主题已经添加了七牛CDN代码版。经测试取消启用WPJAM BASIC插件后,对博客使用七牛并不会产生什么问题,所以,只能抛弃WPJAM BASIC了。

手动集成最新版百度UEditor编辑器插件到WordPress

WordPress技巧手动集成最新版百度UEditor编辑器插件到WordPress

标签:, | 23 条评论 | 2016-08-17

有朋友让教下怎么使用ueditor官方的进行手动集成为WordPress插件,先森就花了点时间研究了一下,现在把方法发布出来。ueditor编辑器文件准备1、首先需要下载一些文件,首先是下载官网最新的UEditor编辑器,现在最新的是1.4.3.3版。进入如下链接,下载PHP版:UEditor官方下载地址选择PHP版本下载2、下载百度UEditor编辑器插件1.4.3.1 For WordPress,我们需要用到一些里面的文件:百度网盘:链接: http://pan.baidu.com/s/1c1bKhNy 密码: sd46下载之后,分别解压,这时候就有了如下文件:当前拥有的文件手动集成其实手动集成的方法非常简单,只需复制下文件,修改个文件名即可。1、第一步,把“\Ueditor编辑器1.4.3.1 for wordpress 4.0插件\ueditor”文件夹内“main.php”和“ueditor.class.php”复制到“ueditor1_4_3_3-utf8-php”文件夹中:复制文件2、第二步,将“ueditor1_4_3_3-utf8-php”文件夹中的“utf8-php”文件夹重命名为“ueditor”:文件夹重命名3、第三步,将“ueditor1_4_3_3-utf8-php”文件夹中的文件打包为zip压缩包,手动集成最新版百度UEditor编辑器插件到WordPress就完成了,从WordPress后台上传插件启用就可以使用了:文件打包BUG修复先森发现,这样直接上传之后,后台编辑框的高度只有80px,非常不利于编辑。编辑器高度修改编辑框的高度很简单,直接在WordPress后台->插件->编辑,选择UEditor,编辑并更新ueditor.config.js中的第93行,将前面的双斜杠注释删掉,后面的高度数值改为想要的高度(建议值:500px):后台编辑编辑更新之后,再看编辑器的效果如下(高度为320px):修改效果总结虽然步骤简单,但若还是不想亲自操作的话,也可以下载先森编译好的最新版:百度网盘下载 链接: http://pan.baidu.com/s/1c2Biu9E 密码: chxs(成航先森)另外,先森只是实现了手动集成的效果,其他可能出现的BUG还没有发现或测试,如有疑问,欢迎发表评论。

给WordPress版UEditor编辑器增加四个彩色美化框自定义按钮

WordPress技巧给WordPress版UEditor编辑器增加四个彩色美化框自定义按钮

标签:, | 13 条评论 | 2016-06-25

其实本文着重介绍的不是彩色美化框,而是如何给百度UEditor编辑器增加自定义按钮。关于什么是彩色美化框,看过先森前文《WordPress默认TinyMCE编辑器增加彩色美化框自定义按钮》应该都知道的。其实也没什么,也就是给引用来的文字段加一个更明显的样式,就像下面这样。这是一个绿色提示框这种美化框,各位站长应该经常能见到,或许你也希望能给自己的WordPress上添加这种美化框。前文已经介绍过如何在WordPress默认的TinyMCE编辑器上添加,那么今天再来介绍下如何在百度UEditor编辑器上添加按钮了。注:本文中会增加4个按钮,代表着4中颜色的美化框。如果还没有安装百度UEditor编辑器,可以点击下载百度UEditor编辑器插件1.4.3.1 For WordPress前期准备1.添加短代码编辑WordPress主题目录下的functions.php文件,添加如下代码并保存:/**美化框的短代码*/function toz($atts, $content=null){return '<blockquote id="sc_notice">'.$content.'</blockquote>'; }  add_shortcode('v_notice','toz');  function toa($atts, $content=null){return '<blockquote id="sc_error">'.$content.'</blockquote>'; }  add_shortcode('v_error','toa');  function toc($atts, $content=null){return '<blockquote id="sc_warn">'.$content.'</blockquote>'; }  add_shortcode('v_warn','toc');  function tob($atts, $content=null){return '<blockquote id="sc_tips">'.$content.'</blockquote>'; }  add_shortcode('v_tips','tob');这个短代码的作用是,在编辑器中输入如下短代码后,在前台打开文章时,会把这些短代码变为上面我们定义的blockquote标签:编辑器中的短代码2.CSS美化将css代码放入主题的style.css文件中或其他地方:/*彩色美化框*/#sc_notice { color: #7da33c; background: #ecf2d6 url('images/sc/sc_notice.png') -1px -1px no-repeat; border: 1px solid #aac66d; overflow: hidden; margin: 10px 0; padding: 15px 15px 15px 35px;width: 98%; }#sc_warn, .post-password-form { color: #ad9948; background: #fff4b9 url('images/sc/sc_warn.png') -1px -1px no-repeat; border: 1px solid #eac946; overflow: hidden; margin: 10px 0; padding: 15px 15px 15px 35px;width: 98%; }#sc_error { color: #c66; background: #ffecea url('images/sc/sc_error.png') -1px -1px no-repeat; border: 1px solid #ebb1b1; overflow: hidden; margin: 10px 0; padding: 15px 15px 15px 35px;width: 98%; }#sc_tips {color: #7da33c;background: #ecf2d6 url('images/sc/sc_tips.png') -1px -1px no-repeat;border: 1px solid #aac66d;padding: 15px 15px 5px 35px;margin: 10px 0;width: 98%;overflow: hidden;}CSS代码中有4个图标链接,请将链接改为你保存的位置图标素材下载:链接: http://pan.baidu.com/s/1bo3ziCB 密码: chxs(成航先森)只有前期准备是对WordPress主题的代码添加,后面的步骤都是在UEditor编辑器插件的代码修改了。UEditor添加按钮本文参考:百度UEditor官方-UEditor二次开发-增加一个普通按钮(上)(下)百度UEditor官方-API文档第一步:添加按钮位置在/wp-content/plugins/ueditor/ueditor目录中,找到ueditor.config.js文件打开,找到ueditor.config.js文件中的toolbars参数,增加'v_notice', 'v_error', 'v_warn', 'v_tips'字符串,为了方便区分,我们可以在这四个字符串前加上一个'|'竖线。添加效果如图:第一步:添加按钮位置第二步:注册按钮实例还是在/wp-content/plugins/ueditor/ueditor目录中,找到ueditor.all.js文件打开,直接定位到大概第649行,有个数组如下:e="undo redo formatmatch bold italic underline fontborder touppercase tolowercase strikethrough subscript superscript source indent outdent blockquote pasteplain pagebreak selectall print horizontal removeformat time date unlink insertparagraphbeforetable insertrow insertcol mergeright mergedown deleterow deletecol splittorows splittocols splittocells mergecells deletetable drafts"在数组中的最后按格式添加第一步中的v_notice v_error v_warn v_tips四个字符串,添加效果如下:第二步:注册按钮实例这时候清空缓存刷新下页面,看看工具栏的对应位置是否出现了四个个自己定义的按钮呢?如下图所示:新增的4个按钮由于此时未设置对应按钮的图片样式,所以会显示默认的“B”字符。要想让其显示成自己需要的图标样式,接着按照下面的步骤动手吧。第三步:更改图标首先是更改图标为默认图标的方法。找到UEditor编辑器插件目录中的themes/default/ueditor.css文件,末尾增加一条样式定义:.edui-for-v_notice .edui-icon {    background-position: -700px -40px;}完成后刷新浏览器,可以看到此时第一个图标已经显示为如下图所示:第三步-修改图标此处的样式定义了showmsg图标在UEditor默认的精灵Icon图片(themes/default/images/icons.png)中的位置偏移。如需更改成另外图标,只需添加图标到该图片文件中,然后设置偏移值即可。先森已经将图标添加到icons.png图片中了(下图右侧),大家只需要将下图用新窗口打开,去掉图片链接后面的问号及参数另存,重命名后替换themes/default/images/icons.png图片即可:icon图标文件对应的,在themes/default/ueditor.css文件中添加的代码如下:.edui-for-v_notice .edui-icon {    background-position: -830px 0px;}.edui-for-v_error .edui-icon {    background-position: -830px -20px;}.edui-for-v_warn .edui-icon {    background-position: -830px -40px;}.edui-for-v_tips .edui-icon {    background-position: -850px 0px;}这时候,重新刷新浏览器,应该就可以看到如下效果了:更改图标的最终效果第四步:定义按钮事件处理方法到此为止,在UI层面已经完成了一个工具栏图标的显示,但是我们发现点击按钮之后毫无反应。那是必然的,我们还必须为该按钮绑定属于它自己的事件处理方法。实质上,此时一个默认的事件处理方法已经被UEditor绑定到按钮上了,只不过由于我们还没有定义该方法的具体内容,所以点击之后无任何变化。下面我们就来定义该方法的具体内容:再回到到ueditor.all.js文件,在521行(并不固定于521行,只要在其附近的一个分号后面另起一行即可)后另起一行,然后在该文件中输入如下代码:UE.commands['v_notice'] = { execCommand : function(){ var range = this.selection.getRange();        range.select();        var txt = this.selection.getText(); if (txt == ''){this.execCommand('insertHtml','绿色提示框:输入文字');} else{this.execCommand('insertHtml',''+txt+'');}    }};UE.commands['v_error'] = { execCommand : function(){ var range = this.selection.getRange();        range.select();        var txt = this.selection.getText(); if (txt == ''){this.execCommand('insertHtml','红色提示框:输入文字');} else{this.execCommand('insertHtml',''+txt+'');}    }};UE.commands['v_warn'] = { execCommand : function(){ var range = this.selection.getRange();        range.select();        var txt = this.selection.getText(); if (txt == ''){this.execCommand('insertHtml','黄色提示框:输入文字');} else{this.execCommand('insertHtml',''+txt+'');}    }};UE.commands['v_tips'] = { execCommand : function(){ var range = this.selection.getRange();        range.select();        var txt = this.selection.getText(); if (txt == ''){this.execCommand('insertHtml','灰色提示框:输入文字');} else{this.execCommand('insertHtml',''+txt+'');}    }};添加后代码中如下图:定义按钮事件处理方法这时候刷新浏览器,点击按钮,应该可以看到以下效果(图中先森是手动换行):按钮功能效果代码解释:UE.commands['v_notice']这个表示注册一个命令。execCommand : function(){}execCommand是UEditor执行命令的通用接口。var range = this.selection.getRange();        range.select();        var txt = this.selection.getText();这一串是百度UEditor的ue.selection.getText();或者说是editor.selection.getText();命令的使用方法,其作用是获得当前选中的文本。因为添加了这个命令,所以使用按钮的时候,可以先将文字写好,然后选中后点击按钮。但遗憾的是选中的文字只能是纯文本,如果有链接或其他样式,选中后点击按钮也会变成纯文字。本来先森研究了半天也没搞懂editor.selection.getText();命令的使用方法,还是要多谢平平深度文件搜索软件,先森通过其深度搜索功能,在ueditor文件夹内搜索“selection.getText()”,这才找到了使用实例。然后if和else是为了判断是否选中了文本,最核心的其实就是下面这行代码:this.execCommand('insertHtml','灰色提示框:输入文字');这行代码就是插入HTML代码,代码内容为“[ v_tips]灰色提示框:输入文字[ /v_tips]”。更多功能命令,请查看UEditor官方文档和API文档。第五步:添加鼠标移上按钮时的提示其实到此为止,给UEditor添加按钮的功能已经完全实现了,但是我们还缺少一个不是那么重要的功能,也就是当鼠标移到按钮上的时候给出的提示。在标准版本里面,其实第一步里面就已经可以添加提示了,但是WordPress for UEditor插件用的是zh-cn这种自动多语言配置,所以我们还需要在翻译文件中添加提示语言。打开/wp-content/plugins/ueditor/ueditor/lang/zh-cn目录,打开zh-cn.js文件。在labelMap数组中添加4个对应提示:'v_notice':'绿色提示框', 'v_error':'红色提示框', 'v_warn':'黄色提示框', 'v_tips':'灰色提示框'添加后zh-cn.js内代码应该如下图:添加鼠标移上按钮时的提示到这里,给WordPress版UEditor编辑器增加四个彩色美化框自定义按钮就完全实现了。修改版下载可能有些小伙伴看了上文已经头大了,喜欢折腾的可以跟着折腾一番,如果实在不会折腾的,先森也把为写本教程制作出来的WordPress版UEditor编辑器插件分享给大家:百度云网盘下载:链接: http://pan.baidu.com/s/1i5i4M4P 密码: chxs(成航先森)写在最后本文一是提供一个给UEditor编辑器添加按钮的方法,而是添加彩色美化框的方法。先森觉得,有了添加按钮的方法最为重要,有了方法之后我们可以自定义更多方便的按钮。先森接下来想做的就是添加下载链接的按钮,让前台的下载链接显得更美观,不像上面那样光秃秃的一个链接。至于彩色美化框,先森觉得选中后会是链接什么的被过滤掉实在是个不小的BUG,所以希望未来能将其攻克,也希望有朋友能提供更好的代码,先森的JavaScript实在太差。

挺实用的一键填写WordPress评论中用户信息代码生成工具

WordPress技巧挺实用的一键填写WordPress评论中用户信息代码生成工具

标签:, | 7 条评论 | 2016-06-24

很早以前就在张戈博客那里看到了这么一个工具,当时觉得没有什么用,但后来才知道是自己不知道怎么用。工具的用途是工具的价值体现。在正确的地方,使用正确的工具,就显得工具非常有实用价值。张哥发出这个工具是为了解决网站开启CDN后,评论者的用户信息不能被保存,每次都要重现填写的困境。因为是站在了巨人的肩膀上,所以先森很方便的用cookie的方法解决了用户信息不能被保存的问题,所以当时对这个工具不是很在意。但是先森在参加培训的时候的电脑都有还原卡,到各个博客去评论的时候都需要重新填写自己的信息,就算是复制粘贴也太麻烦了,所以就想起了这个工具。工具介绍这个工具很简单,只需要将自己的昵称、邮箱地址、站点信息在下面填写好后,点击生成代码,即可得到一串属于自己的代码。一键填写WordPress评论中用户信息代码生成工具使用然后将下面生成的链接拖到书签栏即可保存书签,使用的时候直接在需要填写的页面单击该书签即可。老版的浏览器可以右键链接保存为书签,或者直接Ctrl+D打开一个新建书签的页面,自定义书签名称,将生成的代码粘贴进网址栏即可。昵称(必须):邮箱地址(必须):站点:拖拽下面的链接到您的书签工具栏或者右键单击链接把它添加到您的收藏夹中可创建一个快速填写WP评论者信息的快捷方式。快速填写WP评论信息工具源码如果你也想要在你的博客中添加这样一个工具,如果你也想弄一个这样的工具,只需要将以下代码粘贴到博客相应页面即可(TinyMCE编辑器需文本模式,UEditor编辑器需HTML模式):<script type="text/javascript">(function($){ $(document).ready(function() { $('.code_result').hide(); $('#generate_code').click(function(){ var re = /^[0-9a-zA-Z]+([\.\-\_][0-9a-zA-Z]+)*@[0-9a-zA-Z]+([\.\-][0-9a-zA-Z]+)*.[a-zA-Z]+$/; if($('#commenter_author').val() == '') { $('#commenter_author').css('border', 'solid 1px #ff0000'); $('#commenter_author').focus(); } else if(!re.test($('#commenter_email').val())) { $('#commenter_email').css('border', 'solid 1px #ff0000'); $('#commenter_email').focus(); } else { var commenter_code = 'javascript:document.getElementById(\'author\').value = \''+$('#commenter_author').val()+'\'; document.getElementById(\'email\').value = \''+$('#commenter_email').val()+'\'; document.getElementById(\'url\').value = \''+$('#commenter_url').val()+'\'; void(0)'; $('#wp_commenter_code').html(commenter_code); $('.code_result>a').attr('href', commenter_code); $('.code_result').show(); } }); $('#cheon_code_generator input').keyup(function() { $(this).css('border', 'solid 1px #000000'); }); });})(jQuery);</script><div id="cheon_code_generator" style="padding:10px;"><p>昵称(必须):<br /><input type="text" value="" name="commenter_author" id="commenter_author" style="border:solid 1px #000;"></p><p>邮箱地址(必须):<br /><input type="text" value="" name="commenter_email" id="commenter_email" style="border:solid 1px #000;"></p><p>站点:<br /><input type="text" value="" name="commenter_url" id="commenter_url" style="border:solid 1px #000;"></p><p><textarea cols="40" rows="10" name="wp_commenter_code" id="wp_commenter_code" style="border:solid 1px #000;"></textarea></p><p><input type="button" value="生成代码" id="generate_code" style="cursor: pointer;border:solid 1px #000;"></p><p class="code_result" style="display:none;">拖拽下面的链接到您的书签工具栏或者右键单击链接把它添加到您的收藏夹中可创建一个快速填写WP评论者信息的快捷方式。<br /><a href="#">快速填写WP评论信息</a></p></div>注:该工具只适合于WordPress博客程序创建的网站。如果要适用其他博客,需对JS代码中对应的ID进行修改。

通过研究CDN缓存登录信息问题对WP Super cache的一些新的领悟

WordPress技巧通过研究CDN缓存登录信息问题对WP Super cache的一些新的领悟

标签:, | 11 条评论 | 2016-04-13

先森之前也发文提到过,网站已经接入百度云加速,开启了全站缓存。先森使用了两天之后,感觉很不错,就把体验的结果写了一篇文章发布了。但是突然又发现,先森终于用到了让很多站长头疼的动态数据的问题。先森发现,CDN开启网页HTML缓存之后,一篇文章在没有缓存的情况下,如果第一次访问是先森自己访问的,那CDN缓存的时候,就会把先森登录后显示的界面缓存下来。也就是访客访问的时候,会显示“内容管理”、“登出”、评论框会显示先森的头像,前面两个因为没有登录,所以点击之后也没有用,但是评论框显示先森的头像的时候,没有更改昵称和邮箱的选项,当访客写好评论提交的时候会提示“请输入昵称和邮箱”。先森的网站本来评论就少,这样一来岂不是更收不到评论了。动态判断内容被缓存为了解决这个问题,暂时又没找到合适的解决方法,只得把CDN的缓存HTML给关了。在找解决方法的时候,先森又回头研究WP Super Cache,这次对WP Super Cache又有了新的领悟,所以赶紧写篇文章记录一下。对WP Super Cache新的领悟1.WP Super Cache有两种缓存机制WP Super Cache 设置->内容里面,点击列出所有已缓存的文件网页会刷新出一个显示框,里面有“最新的 WP-Cached 文件”和“最新的 Super Cached 文件”。之前先森以为都是没有什么区别,或者说没弄明白有什么区别。WP Super Cache的两种缓存经过一番研究终于搞明白,WP Super Cache缓存的内容有两种,一种是对已知用户的,一种是对未知用户的。这两种缓存文件放置的位置和格式都不相同。其实这一点,先森也发现WordPress大学中,倡萌早有提及。倡萌的介绍比先森自己写的更规范易懂,但先森也发现有些描述也与现在的插件不吻合了,所以先森自己重新引用整理一下,让先森自己和更多的人看明白:WP Super Cache 缓存机制有两种,WP Cache 和 Super Cache。WP Cache 缓存时,会在你的“wordpress 安装文件夹/wp-content/cache/”文件夹下生成一系列wp-cache-xxxxxx.php格式的文件。而且先森发现,每个不同的已知用户即使他们访问同一个页面,都为单独的为他们缓存一个新的文件,因为他们的昵称、邮箱、网址是不同的;为已知用户缓存Super Cache 缓存时,则在你的“wordpress 安装文件夹/wp-content/cache/supercache/”文件夹下生成对应每一篇文章或者标签等的目录。名称为xxx.html,取决于你的文章ID是怎么设置。目录下面就是静态的 index.html 文件。为未知用户缓存当你一个访问者来的你的站点,他没有登录或者也没有留言,这样他得到是一个在 WordPress cache 文件夹下的 supercache 子文件夹下的纯静态文件,其实你都可以自己到上面的 supercache 目录下去查看同样的永久链接的 HTML 文件的备份。如果要判断一个页面是否已经被缓存了,在页面中右键查看该页面的源代码,最后一行会有“Cached page generated by WP-Super-Cache+缓存时间”这行字,就像下面这行代码一样:<!-- Dynamic page generated in 0.840 seconds. -->    <!-- Cached page generated by WP-Super-Cache on 2016-04-13 17:48:08 -->而如果你开启了压缩页面,缓存会多一行如下代码:<!-- Compression = gzip -->判断网页是否被WP Super Cache缓存2.WP Super Cache高级设置杂项中的两个设置的作用搞明白了WP Super Cache的两种缓存机制之后,加上CDN缓存HTML出现的问题,先森又对WP Super Cache高级设置里,杂项的两个设置的作业有了领悟。两个杂项设置的作用上图红框中的两个设置,以前先森不知道这两个设置所对应的情景是怎样的,现在终于有所感悟了。“不要为已知用户缓存”的作用。很明显,开启之后,在“wordpress 安装文件夹/wp-content/cache/”文件夹下就不会生成一系列wp-cache-xxxxxx.php格式的文件了。在开启CDN缓存HTML文件后,缓存期内,谁第一个访问一个页面,后来者显示的都是他打开后显示的页面。所以即使继续为已知用户缓存,他们也访问不到为他们单独缓存的界面。因此,勾选这个选项就很有必要了。“让已知用户匿名使他们浏览的内容是缓存文件”的作用。上面也说了,开启CDN缓存HTML文件后,缓存期内,谁第一个访问一个页面,后来者显示的都是他打开后显示的页面。而产生这个问题的原因,就是WordPress会记住评论者的信息,这些人就成为了WP Super Cache中的已知用户,他们在打开文章的时候,会自动填上昵称、邮箱等内容。而勾选了这个选项之后,这些已知用户访问页面的时候,会强制匿名,让他们也成为未知用户。其实勾选这两个设置之后,基本能解决CDN缓存昵称、头像的问题,但是这样也导致了已知用户们每次访问都会重新输入一系列信息,对用户体验非常之不好。对于这一点,先森也大致找到了解决方法,等研究好了再分享出来。2016年4月22日更新针对CDN缓存问题,先森将近期的解决方法更新上来,有兴趣的朋友可以去看看:用cookie解决网站开启CDN缓存之后已知用户头像昵称被缓存等系列问题用cookie记住用户信息后隐藏信息输入框,优化用户体验用cookie记住用户信息后ajax实现实时显示Gravatar头像并实时缓存到本地3.缓存的机制这一点的名字可能很多人会没看懂,其实先森是自己进入了一个牛角尖,没有对缓存的机制彻底领悟。先森一直在想,WP Super Cache是怎么做到让访客访问的"www.域名.com/*.html"加载的内容变成“www.域名.com/wp-content/cache/supercache/*.html”的呢?也就是怎么让页面的内容直接访问到缓存的内容。开始先森在想,是不是301跳转什么的,先森记得有个什么隐形跳转,就是链接不变,内容变了。后来先森想明白了,WP Super Cache会将规则写入.htaccess中,用这个规则进行访问缓存文件。可能有人会对这第三点感到很不屑,但是先森觉得自己弄明白了一件事,还是非常高兴的。

WordPress彻底解决百度UEditor插件在历史文章中给图片带来的拉伸问题

WordPress技巧WordPress彻底解决百度UEditor插件在历史文章中给图片带来的拉伸问题

标签:, , | 0条评论 | 2016-03-19

先森很早就发现,手机端查看本站文章,文章里的图片会产生拉伸问题,即图片不是等比例缩放,而是高度或宽带其中一个自适应了,另一个保持不变。这就让图片看起来很长或很宽,很影响用户体验。而产生问题的原因,经过先森查明,发现是WordPress上安装的编辑器插件百度UEditor。先森曾经找到了解决新增的文章不再产生拉伸问题的方法,而对曾经发布的文章中的图片,则束手无策了。毕竟,如果历史文章少,还好一个一个的改回来。但先森已经发布了近两百篇文章,一篇一篇的改,太麻烦了。关于怎么使新增文章的图片不再受到该问题影响的方法,有同样问题的可以去看看:解决方法:解决使用百度UEditor编辑器后移动端图片被拉伸问题先森发现,不仅仅是移动端,PC端的图片其实也有影响,但影响基本不大,不像移动端那么容易被发现。先森文章中的图片都是被七牛裁剪过的,固定宽度为500px,高度随宽度自适应,并且还加上了水印。就是这个水印,让先森在查看历史文章的时候,发现了UEditor对PC端的影响。图片有明显的拉伸感(点击图片后按F查看原图)通过上面的水印,可以看出,整张图片有明显的拉伸感。而罪魁祸首,就是图片<img>标签中的样式代码:style="width: 766px; height: 291px;"而现实在右边,将这段样式设置注释后,图片就好看多了:图片恢复正常(点击图片后按F查看原图)近日,先森研究七牛的时候,发现了MySql的结构化查询语言对处理文章中出现的问题特别有帮助,所以先森就想试试用SQL语言来解决图片拉伸的问题。接着先森就开始着手研究消除图片<img>中的style样式代码了。因为每张图片的高度设置都不一样,所以代码中肯定要用通配符。百度一下,说MySql中百分号“%”是统配一个或多个字符,果断把以前常用的替换代码修改了一下,拿去执行:update `qdm********_db`.`wp_posts` set post_content=replace(post_content,'style="width: %px; height: %px;"','')执行过后,清除缓存,文章刷新,发现并没有什么卵用。结果百度replace函数,结果网上说这个函数并不能使用通配符。再找解决办法,百度谷歌了半天,也只找到一个类似的,但是却还是有些差别。没办法,先森只有开始了研究代码之路。认识MySql代码首先是replace函数。REPLACE(str,from_str,to_str)返回字符串str中所有出现的字符串from_str替换为字符串to_str。from_str虽然不支持使用通配符,却可以使用别的函数的返回值。也就是,我们可以用别的函数,通配出变化中的的“style”的高和宽。先森在解决类似问题的文章中认识了两个函数,CONCAT和SUBSTRING_INDEX。大写的函数单词可能会看着比较蛋疼,虽然大小写并不会影响小型数据处理。但是代码在执行的时候,都会先把小写转换为大写,再进行执行。所以在写代码的时候,直接用大写会减少执行的时间。当然,这是闲话了。关于这两个函数的作用,首先是CONCAT。CONCAT(str1,str2,...)--例:CONCAT(成航,先森,...)最后生成“成航先森”返回的字符串参数连接的结果。也就是将str1、str2等各段都合并起来。然后是SUBSTRING_INDEX。SUBSTRING_INDEX(str,delim,count)--例:SUBSTRING_INDEX('www.capjsj.cn', '.', 1)  会输出“www”返回的子字符串str计数前出现的分隔符DELIM。如果计数是正的,左侧的最后一个分隔符(从左边算起)的一切被返回。如果计数为负,一切向右侧的最后一个分隔符(计数从右侧)将被返回。 SUBSTRING_INDEX()执行区分大小写的匹配时搜索DELIM。这个比较难理解,但是自己把上面的例子拿到数据库命令窗口去多试几遍就明白了。整理思路认识了上面的三个函数,该怎么使用呢?我们可以逆推。最终要实现的,是将下面的代码在表中注删掉:style="width: 766px; height: 291px;"这个可以使用REPLACE函数,但是这个函数不能使用通配符。所以需要将“width: 766px; height: 291px”用别的函数通配出来。这里可以用SUBSTRING_INDEX函数,以style后面的两个双引号为分隔符,将中间的“width: 766px; height: 291px”提取出来。接着在用CONCAT函数将“width: 766px; height: 291px”前面的style="和后面的双引号连接合并到一起,这样就将整个“style="width: 766px; "text-indent: 2em;">则解决方法为:提取-->合并-->替换。测试代码先说明,先森很囧的用SUBSTRING_INDEX把数据库给毁了,因为错误的执行了一行代码,所有的图片都没有了。又没办法撤销。所以把数据库从备份还原了,还好先森在3月16号才备份了一次数据库,17号只发布了4篇文章,影响不大。但就算这样,先森把网站还原也用了近一个小时。所以备份很重要啊,尤其是要对数据库进行数据处理之前。先森吃了亏,再进行操作的时候就小心翼翼的了。不敢直接拿数据库动刀,只敢一点点的用测试代码。复制了一整串受影响的<img>标签,先森开始了测试。<img title="成都航院正校门" alt="成都航院正校门" src="http://img.capjsj.cn/ueditor/php/upload/image/20150622/1434945153483522.jpg" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">由于先森的图片增加了七牛裁剪代码,所以代码看着特别长,所以下文先森就在代码中不写图片链接了,反正不影响测试。首先,我们需要从上面的标签中提取图片的内置宽高设置。而真正执行的时候,需要搜索的对象是整个表,所以先森用分隔符是“style="width: ”,以避免别的style。需要用SUBSTRING_INDEX函数,先森用的代码是:SELECT SUBSTRING_INDEX('<img title="成都航院正校门" alt="成都航院正校门" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">','style="width: ',-1);上面的代码拿到数据库命令窗口去执行:第一次执行的结果(点击图片后按F查看原图)我们可以看到输出的结果是:766px; height: 291px;">而这个结果正是所有被搜索对象的分隔符后面所有内容,也就是如果搜索对象是全文的话,这段代码会输出分割符后面所有的内容,包括图像标签以外文章正文。所以这肯定是还不行的。所以我们需要上面的输出结果再用SUBSTRING_INDEX函数再提取一次。这次还需要加上上面的代码,也就是:SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('<img title="成都航院正校门" alt="成都航院正校门" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">','style="width: ',-1),'"',1);第二次执行的结果(点击图片后按F查看原图)经过两次的提取后,我们就得到了需要通配符匹配的结果:766px; height: 291px;既然能够匹配出最麻烦的地方了,接下来也就简单了。下面我们把需要用来搜索的地方用CONCAT函数链接起来。代码:SELECT CONCAT('style="width: ',SUBSTRING_INDEX(SUBSTRING_INDEX('<img title="成都航院正校门" alt="成都航院正校门" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">','style="width: ',-1),'"',1),'"');第三次执行的结果(点击图片后按F查看原图)经过复杂的提取和拼凑后,我们得到了需要用来搜索的部分:style="width: 766px; height: 291px;"既然得到了需要用来搜索的部分,在上面的函数外面再套上REPLACE函数就可以了:SELECT REPLACE('<img title="成都航院正校门" alt="成都航院正校门" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">',CONCAT('style="width: ',SUBSTRING_INDEX(SUBSTRING_INDEX('<img title="成都航院正校门" alt="成都航院正校门" width="766" height="291" border="0" vspace="0" style="width: 766px; height: 291px;">','style="width: ',-1),'"',1),'"'),'');第四次执行的结果(点击图片后按F查看原图)我们看上图,可以看到,图片<img>标签中,内置的样式代码已经成功的替换成无了,也就删除了。当然,到这里,先森都还是测试,能不能成功还要看最后真正的替换。执行代码通过上面一系列的测试,我们终于可以配置出最终的代码了:update wp_posts set post_content=REPLACE(post_content,CONCAT('style="width: ',SUBSTRING_INDEX(SUBSTRING_INDEX(post_content,'style="width: ',-1),'"',1),'"'),'')最终代码执行结果(点击图片后按F查看原图)可以看到,共影响了396行,当然并不是代表着修改了396篇文章。检验结果的时候来了,到后台删除所有缓存,到前台打开一些最早发布的文章,一查看,OK,成功的将内置style给删除了。先森无奈的发现,该方法如果文章中有设置不同宽高的两张及以上图片,则只会其中其中一张。如果图片的宽高数据完全相同,才会全部替换成功。研究各种语言还真是辛苦,还好先森各种语言以前都还多多少少有所学习,以及还好不会用到汇编语言。

官方微信
返回顶部