Dissect WordPress Themes
2006.02.02 1:05 下午 WordPress
还是想用Nat在OOS上的一段话来作为开头:
You have to give people work to do.
Create an “architecture of participation” as Tim O’Reilly says.
要想真正成功,必须能够提供一个可以供人参与的架构,Eclipse如此,Firefox亦如此。与Plugin一样,WordPress中的Theme机制也非常灵活和强大,社区贡献出的一个个漂亮的Theme都是这个良好架构下的杰作。
1)读取系统中所有可用Themes
function get_themes() ?>
这个函数用来从文件系统得到所有的Themes。首先列出’wp-content/themes’的文件夹,然后跳过’’.’、’..’、’CVS’(跳过CVS目录,这个在Xerdoc DSearch的Theme中也遇到过,因为都是采用CVS进行源码管理 ):
if ($theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS') { continue; } ?>
然后会判断每个目录中是否有Stylesheet ’style.css’文件,如果有,列为Theme候选目录,否则加入到’$wp_broken_themes’中。
接下来,就利用函数
function get_theme_data($theme_file); ?>
来从’style.css’中提取Theme的描述信息,包括’Theme Name’、’Version’、’Author’等等。同WordPress中的插件类似,这些描述信息是存在’style.css’中的。
Theme Name: WordPress Default Theme URI: http://wordpress.org/ Description: The default WordPress theme based on the famous Kubrick. Version: 1.5 Author: Michael Heilemann Author URI: http://binarybonsai.com/ ?>
第三步,需要判断命名冲突。这种情况发生的原因是:将一个Theme拷贝,然后做修改,可是Theme的Descriptor并没有修改。可见,WordPress在人性化上真是做足了功夫,值得学习。
这样,合格的Theme就读取完毕了。不合格的Theme会被放到”Broken Theme”这个Section中,需要重新进行修改才能使用。
2)更换Theme
更换Theme很简单,先来看看当Active一个Theme的时候我们所Access的URL:
http://localhost/blog/wp-admin/themes.php?action
=activate&template=sixties-datetitle&stylesheet=sixties-datetitle
同Plugin一样,Active Theme的信息(其实就是目录名称)也保存在数据库中。但是需要存两项,分别是”template”和”stylesheet”。这是为了处理Style的CSS文件与模板文件(比如index.php)放在不同目录的情况。
if (isset($_GET['template'])) { update_option('template', $_GET['template']); } if (isset($_GET['stylesheet'])) { update_option('stylesheet', $_GET['stylesheet']); } ?>
3)Theme的加载
首先看看我们访问WordPress的过程。当我们访问’http://yoursite/blog/’的时候,访问的是’index.php’文件:
define('WP_USE_THEMES', true); require('./wp-blog-header.php'); ?>
在’wp-blog-header.php’文件中,可以看到下面的重定向过程:
// Template redirection if ( defined('WP_USE_THEMES') && constant('WP_USE_THEMES') ) { do_action('template_redirect'); if ( is_feed() && empty($doing_rss) ) { include(ABSPATH . '/wp-feed.php'); exit; } else if ( is_trackback() && empty($doing_trackback) ) { include(ABSPATH . '/wp-trackback.php'); exit; } else if ( is_404() && get_404_template() ) { include(get_404_template()); exit; } else if ( is_search() && get_search_template() ) { include(get_search_template()); exit; } else if ( is_home() && get_home_template() ) { include(get_home_template()); exit; } else if ( is_single() && get_single_template() ) { include(get_single_template()); exit; } else if ( is_page() && get_page_template() ) { include(get_page_template()); exit; } else if ( is_category() && get_category_template()) { include(get_category_template()); exit; } else if ( is_author() && get_author_template() ) { include(get_author_template()); exit; } else if ( is_date() && get_date_template() ) { include(get_date_template()); exit; } else if ( is_archive() && get_archive_template() ) { include(get_archive_template()); exit; } else if ( is_comments_popup() && get_comments_popup_template() ) { include(get_comments_popup_template()); exit; } else if ( is_paged() && get_paged_template() ) { include(get_paged_template()); exit; } else if ( file_exists(TEMPLATEPATH . "/index.php") ) { include(TEMPLATEPATH . "/index.php"); exit; } } else { // Process feeds and trackbacks even if not using themes. if ( is_feed() && empty($doing_rss) ) { include(ABSPATH . '/wp-feed.php'); exit; } else if ( is_trackback() && empty($doing_trackback) ) { include(ABSPATH . '/wp-trackback.php'); exit; } } ?>
可以看到,根据访问的不同,会定向到不同的页面。比如访问首页的时候,’is_home’返回为true,这样,将会利用get_home_template(),重定向到home template。
function get_home_template() { $template = ''; if ( file_exists(TEMPLATEPATH . "/home.php") ) $template = TEMPLATEPATH . "/home.php"; else if ( file_exists(TEMPLATEPATH . "/index.php") ) $template = TEMPLATEPATH . "/index.php"; return apply_filters('home_template', $template); } ?>
在’wp-setting.php’中,可以找到’TEMPLATEPATH’的定义:
define('TEMPLATEPATH', get_template_directory()); ?>
get_template_directory()的定义为:
function get_template_directory() { $template = get_template(); $template_dir = get_theme_root() . "/$template"; return apply_filters('template_directory', $template_dir, $template); } ?>
get_template则是从数据库中取出现在使用的Theme,再加上Theme Root的路径,即可得到我们选择的Theme的路径。
function get_template() { return apply_filters('template', get_settings('template')); } ?>
因此,这样就定位到所选择Theme的目录,并访问相应的文件。
4)Template的模式
其实对于一个能够提供Theme的程序而言,在程序的构架上必须要实现数据和表现的分离。通常我们所说的MVC(Model、View、Controller)架构就是这个意思。
在WordPress中,是这样来实现数据和实现的分离的。
XHTML。用Div等用来表现数据,CSS来描述这些数据的表现形式,用这种方式来实现数据和表现的分离;
在程序内部,采用Template来进行数据展现。
以 ‘Default’ Theme为例:
<p id="content" class="narrowcolumn"> <p class="post" id="post-<?php the_ID(); ?><p>"> <h2><a href="http://blog.raidybor.com/wp-admin/%3C?php%20the_permalink%28%29%20?%3E" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"></a></h2> <small> <!-- by <?php the_author() ?> --></small> <p class="entry"></p> <p class="postmetadata">Posted in <strong>|</strong> |'); ?></p> <p class="navigation"> <p class="alignleft"></p> <p class="alignright"></p> <h2 class="center">Not Found</h2> <p class="center">Sorry, but you are looking for something that isn't here.</p> ?>
“get_header”和”get_footer”分别用来得到该页的Header和Footer,其实就是两个DIV块儿。Post的主体同样是一个大的Div(
<di d=" content " class="narrowcolumn">
),在该Theme的CSS中即可以看到对这个DIV的表现定义,包括字体、背景颜色、边距等等。
.narrowcolumn { float: left; padding: 0 0 20px 45px; margin: 0px 0 0; width: 450px; }
Post的内容由”have_posts()”, “the_post()”, “the_ID()”得到,具体见此,风格同样定义在CSS文件中。