五分钟教你打造Vista风格按钮

眼看Windows Vista就要正式发布了,趁着这个机会咱也赶赶时髦。这是Vista的黑色任务栏按钮。所用软件为Photoshop 7。

  1. 新建一张图,前景色选灰色(作为辅助色,可随意选一种较淡的颜色),用圆角矩形工具, 设置圆角半径为 3 像素,画一个高 30 左右的矩形。

    ps-vista-button-01.png

  2. 新建图层,用矩形选择工具在按钮上部约50%的地方选择一个矩形。选区越靠上,按钮就越显得凸起。 然后按住Ctrl+Alt+Shift,单击图层面板中第一步建立的形状图层,以选中按钮的上半部。

    ps-vista-button-02.png

  3. 选择前景色 rgb(200,200,200),背景色 rgb(90,90,90),使用渐变工具由上至下在选区中填充渐变色。

    ps-vista-button-03.png

  4. 按Ctrl+Shift+I反选,再按住Ctrl+Alt+Shift单击图层面板中第一步建立的形状图层,选择按钮下半部分。

  5. 设置前景色为 rgb(24,24,24),按Alt+Del填充选区。

    ps-vista-button-04.png

  6. 按Ctrl键单击图层面板中的形状图层,然后选择减淡工具,宽度5像素,曝光度设置为50%,加亮按钮的边缘。 特别是圆角部分可以适当加大高光区。

    ps-vista-button-05.png

  7. 保持前景色为 rgb(24,24,24),选择主菜单编辑->描边,居中1像素。 然后选择前景色为rgb(200,200,200),再次选择主菜单编辑->描边,居外1像素。最后按Ctrl+D取消选区。

    ps-vista-button-06.png

效果还不错吧?最后可根据需要隐藏背景层和形状图层,输出成png格式,便于在网页上使用。

(Read More)

海底光缆修好了吗?

昨天晚上上网发现,原来几乎很慢的国内网站已经能打开了,今天又发现原来一直连不上的抓虾也能正常使用了,虽然速度稍稍慢一点。难道海底光缆已经修好了吗?

查了一下发现新浪今天凌晨发出了首期光缆修复昨日完成 20日有望连接的报道,看来的确是这条修复的光缆起了作用。另据报道,全部修复可能要到一月底,和当初的预想一样。看来工作进展不是很顺利。

(Read More)

Wordpress数据库分析: 整体结构

Wordpress的官方文档对数据库的结构描述得并不充分,索性自己来分析一下。首先从整体结构入手。 下面是2.0.5版的数据库结构图(E-R图)。为了节约篇幅,这里仅列出了主键和外键。 图中菱形表示1:n的关系,白色部分为1,黑色部分为n。

wordpress-db-er-diagram.png

Wordpress共有10个表,按照功能大致分为四类。

  • user: 用户信息,包括wp_users表和wp_usermeta表。
  • post: 文章及评论信息,包括wp_postswp_postmetawp_commentswp_post2cat以及wp_categories五个表。
  • link: 链接信息,包括wp_links表和wp_linkcategories表。
  • option: 全局设置信息,包括wp_options表。

个人认为这个数据库有两个冗余的地方。一个是wp_post2cat表中的主键rel_id,其实可以不要rel_id,而使用post_idcategory_id两列作为主键; 另一个是wp_options表,option_id列为自动增长列,仅使用该列即可作为主键,而不需要option_idblog_idoption_name三列联合做主键。

另外,表的命名规则也很有意思。基本规则总结如下:

  • 保存对象的基本属性,命名为 wp_objects,使用复数(如 wp_postswp_comments);
  • 保存对象的扩展属性,命名为 wp_objectmeta,使用单数(如wp_postmetawp_usermeta);
  • 多对多关系,命名为 wp_a2b,其中a和b分别为多对多关系两端的对象名的缩写(如wp_post2cat)。

(Read More)

SEO: 搬家,别忘了用301

301就是HTTP协议中的应答状态301 Moved Permanently。 当你的网站更换地址后,应当在原地址上写个程序返回301, 以便让访问者能够知道你更换了地址,也让搜索引擎能迅速地收录新地址。 我的blog更改地址之后,经fcicq的提醒, 使用 mod_rewrite 返回301,三天后就有100多页面被Google收录。

下面是使用各种语言返回301的方法。调试时可使用Firefox+ Tamper Data插件, 也可以用IE的ieHTTPHeaders插件。

ASP

直接调用Response.Redirect函数会返回302 Object Moved。为了返回301, 我们需要手工设置信息。

<%@ Language=VBScript %>
<%
  Response.Status = "301 Moved Permanently"
  Response.AddHeader "Location", "http://www.inspiremedia.org/"
  Response.End
%>

PHP

简单地调用 header() 函数输出头信息即可。

<?php
  header("301 Moved Permanently");
  header("Location: http://www.inspiremedia.org/");
?>

Perl

#!/usr/bin/perl -w
print "Status: 301 Moved Permanently\n";
print "Location: http://www.inspiremedia.org/\n\n";

mod_rewrite

如果你使用Apache,那么用mod_rewrite进行重定向是最简单的选择了, 只要在 httpd.conf 的全局配置或者虚拟主机配置中写一条规则即可。

RewriteEngine On
RewriteRule ^/(.*) http://www.inspiremedia.org/$1 [R=permanent,L]

注意一定要使用 [R=permanent] 选项,仅用 [R] 选项会返回 302 。

(Read More)

Wordpress性能优化

Wordpress的效率问题似乎一直是议论的热点,今天来看看其中一条SQL语句的效率。

首先将所有插件禁用,并切换为默认模板。 然后按照《WordPress执行效率问题》这篇文章的方法, 在 wp-config.php 中加入

<?php define('SAVEQUERIES', true); ?>

在模板的 footer.php 中加入

<!-- <?php var_dump($wpdb->queries); ?> -->

访问首页,即可从源代码中看到SQL语句。

执行时间最长的是这一条,花了0.02秒:

SELECT DISTINCT * FROM wp_posts  
WHERE 1=1 
  AND post_date_gmt <= '2007-01-02 07:12:59' 
  AND (
    post_status = 'publish' 
    OR
      post_author = 1 
      AND post_status != 'draft' 
      AND post_status != 'static'
  )
  AND post_status != 'attachment' 
GROUP BY  wp_posts.ID  
ORDER BY post_date DESC 
LIMIT 0, 10"

这条语句位于 class.php 的 WP_Query->&get_posts() 函数。

说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。

列名 类型 索引
ID bigint(20) PRIMARY
post_author bigint(20)
post_date_gmtdatetime
post_status enum INDEX
post_name varchar(200) INDEX

首先是关键字 DISTINCT,DISTINCT的作用是去掉重复的数据, 相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列,包含了主键列 ID, 每行数据必然不相同,因此 DISTINCT 关键字起不到任何作用, 白白浪费一次排序。

其次是 post_date_gmtpost_author 上的比较操作。wp_posts表仅有 IDpost_statuspost_name 列上有索引,对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据, 影响效率。

然后是 post_status 上的不等于的比较。对索引列使用不等于比较, 会导致数据库不能使用索引(索引只能判断等于关系)。 另外显然已经有了 post_status = 'publish' 的条件, 不必再判断 post_status != 'attachment'

最后是 GROUP BY wp_posts.ID,仍然是对一个不会重复的列进行 GROUP BY, 毫无意义。

如果不考虑功能损失,将这个 SQL 语句优化为下面这样,则仅需花费0.003秒。

SELECT * FROM wp_posts  
WHERE 1=1 
  AND post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 0, 10"

使用Apache Bench做测试,优化前平均每个请求的处理时间为 503.125ms,优化后为 478.125ms。

(Read More)

IE的box模型显示bug

box模型即由<div>等块元素的 margin、padding、border、width、height 等属性构成的显示模型, 它是CSS布局的基础。通过设置<div>的各种属性,可以得到任何想要的页面效果。

各个元素的含义如下:

box-model.gif

  • margin: box外边界到外层元素的距离,即余白
  • border: box的边界宽度。
  • padding: box内的内容到box内边界的距离,即边距
  • width: box的宽度。
  • height: box的高度。

其中有问题的就是 width 和 height 的定义。一般的浏览器将 width 和 height 定义为 除掉 margin、padding、border 之后的box内容的大小,实际上 box 所占有的面积 为定义的 width/height 再加上 margin、padding、border的大小。

(Read More)

如何修改Wordpress表前缀

Wordpress的表名前缀默认为 wp_,该值为Wordpress安装时指定,安装之后无法更改。但若不得已需要改变时,可以使用以下方法。

  • 将数据库导出。
  • 将表中的所有 wp_ 替换为 wp2_,其中 wp2_` 为新的表前缀。
  • 导入数据库。
  • 修改 wp2_options 表的数据,在第四行左右有个 wp_user_roles,将其修改为 wp2_user_roles
  • 修改 wp2_usermeta 表的数据,将所有的 wp_user_level 修改为 wp2_user_level,所有的 wp_capabilities 修改为 wp2_capabilities

如果忘记修改 wp2_optionswp2_usermeta 中的值,后台管理就无法使用。

(Read More)

data: URLs

或许这个已经不是什么新闻了。以data:开头,后面加入MIME类型和内容,即可将一个文件包含在一个URL内。包含二进制文件的格式为 data:image/gif;base64,BASE64编码。例如下面的图像文件包含了本站的图标。(请查看源代码以查看data:URLs的格式)

这个协议由RFC2397制定,目前Firefox、Opera、Konqueror、Safari都支持。IE不支持。唉,又是IE。

(Read More)

mod_rewrite防盗链

这个话题似乎是老调重弹了,也有很多人给出了相应的方法。我的方法如下:

RewriteCond %{REQUEST_URI} !^/wp-includes/images/noimage.png$ [NC]
RewriteCond %{HTTP_REFERER} !^http://[0-9a-z]+\.inspiremedia\.org/.*$ [NC]
RewriteRule \.(jpg|gif|png|zip|gz|rar)$ http://tech.inspiremedia.org/wp-includes/images/noimage.png [R,L]

主要功能位于第二行,当请求的HTTP_REFERER头不输入本站所在的域时,则执行第三行的重写规则,重定向至 noimage.png。 第二行最后的[NC]表示匹配时忽略大小写。第一行用于防止死循环。

2006-12-26

接受建议,将重写规则仅适用于 wp-content/uploads 下的文件。

RewriteCond %{HTTP_REFERER} !^http://[0-9a-z]+\.inspiremedia\.org/.*$ [NC]
RewriteRule wp-content/uploads/.*\.(jpg|gif|png|zip|gz|rar)$ http://tech.inspiremedia.org/wp-includes/images/noimage.png [R,L]

(Read More)

IP 2 Country插件

这是一个根据IP地址判断所在国家的插件。用处很多,显示评论者国家、阻挡垃圾评论等等。 其实这种插件有很多,比如IP to Country, 不过这个程序感觉一来效率不高,二来用起来也不是很方便。于是我写了这个插件,仅仅一个函数。

原理很简单,将IP地址范围保存到MySQL数据库中,然后通过SQL取出给定IP地址的数据,显示国家即可。

$ip = ip2long($ipaddr);
$sql = sprintf("SELECT country FROM ip2country WHERE ip_from<=%u AND ip_to>=%u", $ip, $ip);
$row = $wpdb->get_row("$sql");
return $row->country;

(Read More)