GG资源网

WordPress架构简单剖析(wordprss主题制作教程(五):制作头部文件-header.php)

WordPress架构简单剖析

前言

最近在搭建自己的博客站点时, 选择了网站使用较多的WordPress, 随着慢慢的使用, 它灵活的插件和主题令我折服. 基本上任何想要实现的功能, 都可以在上面通过插件的形式进行添加. 无论是在访问前的缓存、访问后的统计、访问中的过滤、各种流程的修改等等, 几乎都能够以插件的形式进行修改. 我觉得这太酷了, 如果在我平常业务上能够将架构写成这样, 还有什么需求变化能难倒我?

基于这个原因, 我对WordPress进行了简单的分析, 这就是开源的好处嘛. 我从index.php文件一步步跟踪了整个请求的开始到结束. 因为能力有限, 这可能是最笨的办法了.

解析

执行流程#

index.php文件很简单, 就一句:

require __DIR__ . '/wp-blog-header.php';

而wp-blog-header.php文件呢, 也很简单:

if ( ! isset( $wp_did_header ) ) {
$wp_did_header = true;
require_once __DIR__ . '/wp-load.php';
wp();
require_once ABSPATH . WPINC . '/template-loader.php';
}

而这, 已经将WordPress的执行流程体现出来了.

1.防止重复加载#

! isset( $wp_did_header ) 判断, 是为了防止文件被重复加载的, 直接跳过

2.加载 库/主题/插件#

第二步引入了wp-load.php文件, 然后又引入了wp-config.php文件, 再然后又引入了wp-settings.php文件, 实际的加载过程, 就在wp-settings.php文件中. 此文件做了下面几件事

  1. 引入初始化文件
  2. 常量定义
  3. 引入库
  4. 加载插件
  5. 加载主题

到这里, 还没有针对当前页面数据的查询, 仅完成了初始化过程.

3.查询页面数据#

wp()函数是执行页面数据加载的方法, 会根据当前页面, 到数据库中查询需要显示的数据, 将需要展示的数据准备好.

4.页面展示#

最终引入的template-loader.php文件, 其作用是将数据进行可视化展示.

5.完成#

至此, 整个页面的展示流程就走完了. 按照这个步骤看下来, 整个流程还是比较清晰的.

但是还是没有回答最开始的问题啊, 它灵活在哪里呢? 上面只是简单描述了一下整体的加载流程, 但具体细节还没有提到.

页面展示#

WordPress加载页面的地方, 就是最后的template-loader.php这个文件了.

其根据当前页面, 加载不同的文件进行展示. 至于页面为什么这么灵活, 随便找个页面看一下就知道了. index.php:

拼图式生成页面. 可针对每一个位置进行定制, 并将其进行组装. 所以每个主题都有很高的灵活性, 可以自己设置页面, 也可以选择丢弃某些内容而不展示.

另外, HTML在加载页面的时候, 会对几个模板进行查找, 如在访问: 计算机是如何进行时间同步的 这篇文章的时候, get_single_template 方法会依次查找下面几个文件:

  • single-post-计算机是如何进行时间同步的.php
  • single-post-%e8%ae%a1%e7%ae%97%e6%9c%ba%e6%98%af%e5%a6%82%e4%bd%95%e8%bf%9b%e8%a1%8c%e6%97%b6%e9%97%b4%e5%90%8c%e6%ad%a5%e7%9a%84.php
  • single-post.php
  • single.php

若某个文件存在, 就会直接加载. 有没有悟到什么. 这玩意不就可以做缓存嘛. 但是, 不好意思, 在执行这步操作之前, 该查询的数据就已经查过了, 所以这个缓存加了等于没加, 没什么卵用.

钩子函数#

如果WordPress只是能够拼图式组装页面, 那还不够灵活, 因为只能对页面进行操作, 而无法影响执行流程. 对执行流程的影响, 就是它的各种钩子函数了. WordPress的钩子函数通过do_action和apply_filters两个方法进行调用,

看过方法add_action发现, 它就是简单的调用了add_filter方法. 也就是说这两个方法内部是同一个方法. 个人理解, do_action注重与流程的插入, 既向主流程中加入一段逻辑, 没有返回值. 而 apply_filters方法有返回值, 更注重对数据的处理吧.

在WordPress中, 随处可见各种钩子的调用, 初始化的时候、加载插件、插件加载完成、加载主题等等等等.

举个例子, 有一个缓存插件, 就是通过在添加init钩子函数, 将页面内容 echo之后, 直接执行die函数, 以达到快速返回的效果.

不过在查看源码的过程中, 有一个问题, 所有钩子函数的调用, 都是直接使用字符串调用的, 如 do_action('init'). 这种通用的变量, 不应该写个常量列表的么?

不过好在官方维护了一份钩子函数的列表, 列出了所有的钩子, 同时进行了说明并指出调用的具体地址. 需要的时候可以看一下. 我数了一下, 目前一共1470个钩子. https://developer.wordpress.org/reference/hooks/

可以说, WordPress就是通过各种钩子以及拼图式页面, 分别实现展示和流程的个性化定制. 而这个钩子函数倒也不是什么新鲜玩意, 接口的监听器、各种beforeAction afterAction等等, 在平常开发过程中也经常用到. 只是没有用到这么极致罢.

其他细节#

配置加载#

WordPress的配置是存储在MySQL中的, 而请求加载配置文件的方式是执行sql查询:

SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'

直接将表中的所有配置, 一次性读出来, 而且, 取出来的数据还不少嘞, 给你个直观感受, 我将结果保存到txt文件, 文件大小1.4mb.

如果说这个查询可以增加缓存, 或者通过配置文件引入的话, 能够省去一些消耗. 但是, 如果想通过插件的方式修改配置读取, 不好意思, 这个不可以. 因为 配置的首次读取是在调用wp_not_installed()函数时, 而此时插件还没加载呢. 如果想修改的话, 貌似只能修改源码了,

在加载配置的时候, 在请求缓存中先读了一次:

故可以预先将配置放到请求缓存中. 在调用方法wp_start_object_cache()加载缓存之后, 立刻调用了wp_cache_add( 'alloptions', $alloptions, 'options' );方法, 可以将全局配置预先放到缓存中, 实验了一下, 确实可行. 如果追求性能极致的话, 可以考虑.

配置存储#

看到数据库配置表wp_options中启用插件的值时, 我完全摸不到头脑, 存储的内容是这样的:

a:7:{i:0;s:49:"easy-table-of-contents/easy-table-of-contents.php";i:1;s:47:"simple-yearly-archive/simple-yearly-archive.php";i:2;s:30:"wp-githuber-md/githuber-md.php";i:3;s:29:"wp-mail-smtp/wp_mail_smtp.php";i:5;s:27:"wp-super-cache/wp-cache.php";i:6;s:31:"wpdiscuz/class.WpdiscuzCore.php";i:7;s:32:"xml-sitemap-feed/xml-sitemap.php";}

这这这, 这是啥? 看不懂, 但又好像能看懂. 于是我追踪了这个值的解析, 就是下面这个函数:

解析后的数据是:

{
"0": "easy-table-of-contents/easy-table-of-contents.php",
"1": "simple-yearly-archive/simple-yearly-archive.php",
"2": "wp-githuber-md/githuber-md.php",
"3": "wp-mail-smtp/wp_mail_smtp.php",
"5": "wp-super-cache/wp-cache.php",
"6": "wpdiscuz/class.WpdiscuzCore.php",
"7": "xml-sitemap-feed/xml-sitemap.php"
}

是不是一下就懂了? 存储的是通过serialize函数进行对象序列化之后的值, 于是, 弱弱的问一下, 直接存json字符串不好么?

全局变量定义#

在WordPress中到处都充斥着各种全局变量. 我在查看缓存文件的时候, 看到了这段代码:

但奇怪的是, 我全局搜索变量$wp_object_cache, 却没有找到定义的地方. 最终我一点一点找到了它定义的地方.

而这种功能风格到处都是, 如果想找到一个变量都有哪些地方使用了, 很不好找. 而且, 直接引用全局变量的方式, 也导致变量之后很难修改. 在源码中就看到了这么一个活生生的例子:

这种风格导致一个后果, 一个变量一旦定义, 就摘不掉了.

数据库查询记录#

在查看数据库查询的时候, 看到了这样的代码:

也就是说, 如果定义了SAVEQUERIES常量, 且为true, 那么就会将查询的sql记录下来. 在log_query方法中, 记录到了queries变量中.

这个操作对于数据库的调优还是比较方便的. 在配置文件中定义常量, 在最终拿到所有的sql及执行时间

总结

对于这种充斥着全局变量和钩子函数的内容, 阅读起来有一丢丢的疲惫, 经常看着看着就看丢了. 不过还是发现了很多有意思的地方.

本来是想看看它为什么这么灵活, 结果发现其实在平常的开发过程中已经用到了, 不过WordPress对一些内容的处理还是给了我一些启发.

比如这种拼图式的页面组成, 可以将页面的展示和数据处理分离. 而在开发接口的时候, 是不是也可以借鉴类似的思路. 这种方式有一个问题, 就是即使页面没有用到的数据, 在查询的时候也都查询出来了, 对于接口这种追求性能的情况, 肯定是不能忍受的. 或者可以将需要使用的数据让展示方给出配置? 不过这样的话, 耦合度又高了, 灵活度也下降了, 难搞.

不过最重要的是, 这破玩意就是我现在在用的呀, 不好好了解一下怎么行. 以后如果有定制化需求, 咱也不至于无从下手了.

wordprss主题制作教程(五):制作头部文件-header.php

一般说来我们网站的所有页面的头部和底部基本相似,所以我们可以将这些相似的代码放到一个文件中,然后在每个模板文件载入这个头部和底部文件即可,这样我们就不需要给每个模板都把头部和底部文件都写一遍,而且修改方便,改了头部文件,所有页面都会生效。

接着上一篇教程,我们在做主题文件夹content\\themes\\Aurelius下面新建一个头部文件header.php,然后将index.php中的头部代码提取(剪切)出来,写入这个文件:

  1. <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
  2. <html xmlns=\"http://www.w3.org/1999/xhtml\">
  3. <head profile=\"http://gmpg.org/xfn/11\">
  4. <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
  5. <title>Aurelius | Blog</title>
  6. <!-- Stylesheets -->
  7. <link rel=\"stylesheet\" href=\"./style.css\" type=\"text/css\" media=\"screen\" />
  8. </head>
  9. <body>
  10. <div id=\"wrapper\" class=\"container_12 clearfix\">
  11.     <!-- Text Logo -->
  12.     <h1 id=\"logo\" class=\"grid_4\">Aurelius</h1>
  13.     <!-- Navigation Menu -->
  14.     <ul id=\"navigation\" class=\"grid_8\">
  15.         <li><a href=\"contact.html\"><span class=\"meta\">Get in touch</span><br />
  16.             Contact Us</a></li>
  17.         <li><a href=\"blog.html\" class=\"current\"><span class=\"meta\">Latest news</span><br />
  18.             Blog</a></li>
  19.         <li><a href=\"index.html\"><span class=\"meta\">Homepage</span><br />
  20.             Home</a></li>
  21.     </ul>
  22.     <div class=\"hr grid_12 clearfix\">&nbsp;</div>
  23.     <!-- Caption Line -->
  24.     <h2 class=\"grid_12 caption clearfix\">Our <span>blog</span>, keeping you up-to-date on our latest news.</h2>
  25.     <div class=\"hr grid_12 clearfix\">&nbsp;</div>
由于网站搬家,部分链接失效,如无法下载,请联系站长!谢谢支持!
1. 带 [亲测] 说明源码已经被站长亲测过!
2. 下载后的源码请在24小时内删除,仅供学习用途!
3. 分享目的仅供大家学习和交流,请不要用于商业用途!
4. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
5. 本站所有资源来源于站长上传和网络,如有侵权请邮件联系站长!
6. 没带 [亲测] 代表站长时间紧促,站长会保持每天更新 [亲测] 源码 !
7. 盗版ripro用户购买ripro美化无担保,若设置不成功/不生效我们不支持退款!
8. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
9. 如果你也有好源码或者教程,可以到审核区发布,分享有金币奖励和额外收入!
10.如果您购买了某个产品,而我们还没来得及更新,请联系站长或留言催更,谢谢理解 !
GG资源网 » WordPress架构简单剖析(wordprss主题制作教程(五):制作头部文件-header.php)

发表回复

CAPTCHAis initialing...