2008-07
20
PHP+MySQL八大动态Web应用实战

豆瓣上的介绍, 购买此书: 当当, 卓越, ChinaPub, 蔚蓝

这本书是今年二月份翻译的,两个人合作,用了一个半月的时间翻译+校对,虽然进度安排比较紧,但总算是按时交了稿,翻译的质量也还说得过去。

上周接到博文视点的消息,说这本书已经出版了,样书已经寄出来了。不过我还没收到,估计下周就能收到样书了吧。到网上查了查,发现各大书店已经开始卖了。

这本书的内容主要是面向PHP初学者的,但正如作者在前言中所述,这本书不会教你PHP和MySQL的基础知识,而是通过实际的项目进行讲解,在项目进展的过程中逐步地讲授需要的知识。个人认为这种方法要比教科书的好得多。我们在实际工作中学习也与之类似,不会有人去一步步手把手地教你怎样学习,都是直接将新人投入到项目中,在项目中磨砺。

书中介绍了八个实际可用的项目,除了基本的PHP和MySQL之外,还有较为新颖的Ajax、较高深的PEAR等内容。初学者通过这些项目可以切实地体会到PHP的方便性,而稍有基础的人则可以将书中的例子直接拿来,简单修改后即可直接放在网站上使用。当然,如果你已经是PHP高手,那么能从此书中学到的内容就有限了。

当然,本书自身也有一些不足之处,或许是因为作者精于技术但不善表达的缘故,书中一些概念的解释不太容易理解。加之我们英文水平有限,许多原文中的俗语都无法精确翻译出来,也影响了原文意思的表达。还望读者在阅读的过程中,借助Google、百度等搜索引擎,主动去查找那些难以理解的概念。另外,我们尽最大的努力保持翻译结果符合原意,但难免有疏漏之处,希望读者能够指出。


2007-01
05

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

wordpress-db-er-diagram.png

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

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

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

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

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

2007-01
02

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 表的结构(省略无关列)。

列名类型索引
IDbigint(20)PRIMARY
post_authorbigint(20)
post_date_gmtdatetime
post_statusenumINDEX
post_namevarchar(200)INDEX

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

其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和 post_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。


2006-10
01

mysql 从版本 4.1 起增加了多国语言字符集功能。 数据在插入到数据库或者从数据库中取出时,mysql会自动进行字符集变换。 在创建数据库时必须要指定数据库字符编码,而客户端在连接mysql时也必须要指定客户端字符编码。 假设数据库字符编码utf8,而客户端字符编码gb2312, 那么执行select时mysql会将字符串从 utf8 转换成 gb2312, 而在执行 insert、update等时会将客户端输入的数据从 gb2312 转换成 utf8。

WordPress的数据使用 UTF-8 编码,因此在 mysql-5.0中创建数据库时应当将字符集指定为 utf8。 遗憾的是 php 等脚本语言不会自动设置客户端字符编码,因此mysql会选择默认的 latin1 , 这样在执行 select 时mysql会将数据从utf-8转换到latin1,造成乱码现象。

解决方法就是在执行 mysql_connect 之后执行以下语句

mysql_query("SET NAMES utf8");

使用phpMyAdmin-2.8.0.2完整的升级方法如下:

  1. 从原有的数据库中导出表结构和数据。
  2. 在mysql-5.0中创建数据库,设置字符校对为 utf8_general_ci。
  3. 向数据库中导入数据,导入时设置数据编码为utf8。
  4. 修改 wp-includes/wp-db.php,在wpdb类的wpdb函数中(57行前后)添加以下内容。
    function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
        $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword);
        ......
        $this->query("SET NAMES utf8");          // 添加这一行
        $this->select($dbname);
    }
mysql-5-update.png

2006-09
23

下载并安装 httpd 2.2。

$ tar xjvf httpd-2.2.3.tar.bz2
$ cd httpd-2.2.3/
$ ./configure --enable-rewrite --enable-so
$ make
$ sudo make install

下载并安装 mysql-3.23

$ sudo tar xzvf mysql-3.23.58-pc-linux-i686.tar.gz -C /usr/local/mysql
$ sudo groupadd mysql
$ sudo useradd -d /usr/sbin -s /bin/false -g mysql mysql
$ sudo chown -R mysql.mysql /usr/local/mysql
$ cd  /usr/local/mysql
$ sudo ./scripts/mysql_install_db
$ sudo cp support-files/mysql.server /etc/init.d/mysql
$ /etc/init.d/mysqld start

下载并安装 php 5.1.6。

$ sudo apt-get install flex bison libxml2-dev
$ tar xjvf php-5.1.6.tar.bz2
$ cd php-5.1.6/
$ ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-gd
                  --with-gettext --with-mysql --with-zlib-dir=/usr/lib 
                  --with-mysql=/usr/local/mysql