最近项目需要,分析了一下Wordpress的特色图像 Feature Image的上传、保存方式,这一分析觉得Wordpress的数据结构设计还真是有想法。

先简单说一下结论:

Wordpress中图像物理文件保存在 wp-content/uploads 目录下,相关信息保存在 wp_posts 表中。post_type 是 attachment,post-mime-type 是 image/png。通过 post_parent 与文章关联。

我原来以为图片信息会有单独的表存放,没想到都放在 wp_posts 中,于是分析了这样做有什么好处。

wp_posts 表

首先来看看 wp_posts 表。该表用来存放文章信息,如文章标题、正文、摘要、作者、发布时间、访问密码、评论数、修改时间、文章地址(非静态化之前的,带?和数字ID)等。这些属性都是与文章相关的,同时根据 post_type的不同,该表还能用来存储特色图像 Featured Image。

字段 含义
ID 自增唯一ID
post_author 对应作者ID
post_date 发布时间
post_date_gmt 发布时间(GMT+0时间)
post_content 正文
post_title 标题
post_excerpt 摘录
post_status 文章状态(publish
comment_status 评论状态(open
ping_status PING/Trackback状态(open/closed)
post_password 文章密码
post_name 文章缩略名
to_ping 要引用的URL链接
pinged 已经PING过的链接
post_modified 修改时间
post_modified_gmt 修改时间(GMT+0时间)
post_content_filtered 未知
post_parent 父文章,主要用于PAGE
guid 文章的一个链接。注意:不能将GUID作为永久链接(虽然在2.5之前的版本中它的确被当作永久链接),也不能将它作为文章的可用链接。GUID是一种独有的标识符,只是目前恰巧成为文章的一个链接。
menu_order 排序ID
post_type 文章类型(post/page/attachment/revision等)
post_mime_type MIME类型
comment_count 评论总数

由此可以看到,Wordpress 利用 post_type 可以在该表中存储草稿、文章、页面、附件等丰富的信息,一张表就搞定了。

wp_postmeta 表

与这张表相关联的,还有一个 wp_postmeta 表,用来存储与文章相关的元数据。这个表的表结构比较简单。

字段 含义
meta_id 元数据记录的ID。
post_id 就是元数据相关联的post,用户(user),评论(comment)的ID。
meta_key 元键(meta key)(这个值在不同的记录中经常是重复的)。
meta_value 元值(meta value)(往往是唯一的)。

如何获取特色图像 Featured Image

那么,对于一个文章,是如何来获取特色图像 Featured Image的,下面来看一下。在后台的文章编辑界面,特色图像显示在这个位置。

对应的后台代码是 wp-admin/includes/meta-boxes.php

  1. /**
  2. * Display post thumbnail meta box.
  3. *
  4. * @since 2.9.0
  5. *
  6. * @param WP_Post $post A post object.
  7. */
  8. function post_thumbnail_meta_box( $post ) {
  9. $thumbnail_id = get_post_meta( $post->ID, '_thumbnail_id', true ); //获取特色图像对应的ID
  10. echo _wp_post_thumbnail_html( $thumbnail_id, $post->ID ); //输出HTML
  11. }

继续找 get_post_meta ,在wp-includes/post.php中。

  1. /**
  2. * Retrieve post meta field for a post.
  3. *
  4. * @since 1.5.0
  5. *
  6. * @param int $post_id Post ID.
  7. * @param string $key Optional. The meta key to retrieve. By default, returns
  8. * data for all keys. Default empty.
  9. * @param bool $single Optional. Whether to return a single value. Default false.
  10. * @return mixed Will be an array if $single is false. Will be value of meta data
  11. * field if $single is true.
  12. */
  13. function get_post_meta( $post_id, $key = '', $single = false ) {
  14. return get_metadata('post', $post_id, $key, $single);
  15. }

继续找 get_metadata 在 wp-includes/meta.php 中。

  1. /**
  2. * Retrieve metadata for the specified object.
  3. *
  4. * @since 2.9.0
  5. *
  6. * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
  7. * @param int $object_id ID of the object metadata is for
  8. * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
  9. * the specified object.
  10. * @param bool $single Optional, default is false.
  11. * If true, return only the first value of the specified meta_key.
  12. * This parameter has no effect if meta_key is not specified.
  13. * @return mixed Single metadata value, or array of values
  14. */
  15. function get_metadata($meta_type, $object_id, $meta_key = '', $single = false) {
  16. if ( ! $meta_type || ! is_numeric( $object_id ) ) {
  17. return false;
  18. }
  19. $object_id = absint( $object_id );
  20. if ( ! $object_id ) {
  21. return false;
  22. }
  23. //echo $object_id . ':' . $meta_type . '-' . $meta_key . '-' . $single . '<br />';
  24. /**
  25. * Filters whether to retrieve metadata of a specific type.
  26. *
  27. * The dynamic portion of the hook, `$meta_type`, refers to the meta
  28. * object type (comment, post, or user). Returning a non-null value
  29. * will effectively short-circuit the function.
  30. *
  31. * @since 3.1.0
  32. *
  33. * @param null|array|string $value The value get_metadata() should return - a single metadata value,
  34. * or an array of values.
  35. * @param int $object_id Object ID.
  36. * @param string $meta_key Meta key.
  37. * @param bool $single Whether to return only the first value of the specified $meta_key.
  38. */
  39. $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
  40. if ( null !== $check ) {
  41. if ( $single && is_array( $check ) )
  42. return $check[0];
  43. else
  44. return $check;
  45. }
  46. $meta_cache = wp_cache_get($object_id, $meta_type . '_meta');
  47. if ( !$meta_cache ) {
  48. $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
  49. $meta_cache = $meta_cache[$object_id];
  50. }
  51. if ( ! $meta_key ) {
  52. return $meta_cache;
  53. }
  54. if ( isset($meta_cache[$meta_key]) ) {
  55. if ( $single )
  56. return maybe_unserialize( $meta_cache[$meta_key][0] );
  57. else
  58. return array_map('maybe_unserialize', $meta_cache[$meta_key]);
  59. }
  60. if ($single)
  61. return '';
  62. else
  63. return array();
  64. }

这个函数中会根据 $meta_key 和 $object_id 、$meta_type 取出特色图像对应的ID。为了避免重复读取数据库,这里用了缓存,我们可以看 update_meta_cache 这个函数。

  1. /**
  2. * Update the metadata cache for the specified objects.
  3. *
  4. * @since 2.9.0
  5. *
  6. * @global wpdb $wpdb WordPress database abstraction object.
  7. *
  8. * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
  9. * @param int|array $object_ids Array or comma delimited list of object IDs to update cache for
  10. * @return array|false Metadata cache for the specified objects, or false on failure.
  11. */
  12. function update_meta_cache($meta_type, $object_ids) {
  13. global $wpdb;
  14. if ( ! $meta_type || ! $object_ids ) {
  15. return false;
  16. }
  17. $table = _get_meta_table( $meta_type );
  18. if ( ! $table ) {
  19. return false;
  20. }
  21. $column = sanitize_key($meta_type . '_id');
  22. if ( !is_array($object_ids) ) {
  23. $object_ids = preg_replace('|[^0-9,]|', '', $object_ids);
  24. $object_ids = explode(',', $object_ids);
  25. }
  26. $object_ids = array_map('intval', $object_ids);
  27. $cache_key = $meta_type . '_meta';
  28. $ids = array();
  29. $cache = array();
  30. foreach ( $object_ids as $id ) {
  31. $cached_object = wp_cache_get( $id, $cache_key );
  32. if ( false === $cached_object )
  33. $ids[] = $id;
  34. else
  35. $cache[$id] = $cached_object;
  36. }
  37. if ( empty( $ids ) )
  38. return $cache;
  39. // Get meta info
  40. $id_list = join( ',', $ids );
  41. $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
  42. echo "SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC" . "<br />";
  43. $meta_list = $wpdb->get_results( "SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC", ARRAY_A );
  44. if ( !empty($meta_list) ) {
  45. foreach ( $meta_list as $metarow) {
  46. $mpid = intval($metarow[$column]);
  47. $mkey = $metarow['meta_key'];
  48. $mval = $metarow['meta_value'];
  49. // Force subkeys to be array type:
  50. if ( !isset($cache[$mpid]) || !is_array($cache[$mpid]) )
  51. $cache[$mpid] = array();
  52. if ( !isset($cache[$mpid][$mkey]) || !is_array($cache[$mpid][$mkey]) )
  53. $cache[$mpid][$mkey] = array();
  54. // Add a value to the current pid/key:
  55. $cache[$mpid][$mkey][] = $mval;
  56. }
  57. }
  58. foreach ( $ids as $id ) {
  59. if ( ! isset($cache[$id]) )
  60. $cache[$id] = array();
  61. wp_cache_add( $id, $cache[$id], $cache_key );
  62. }
  63. return $cache;
  64. }

关键的语句在这里

  1. SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (21) ORDER BY meta_id ASC

可以看到结果如下,_thumbnail_id 对应的就是 wp_posts 中的记录ID,从而可以取到图片对应的地址和相关信息。

本文内容基于 Wordpress 4.8版本

参考资料:

1、如何设置Wordpress的特色图像

2、WordPress数据库表及字段详解

3、理解和利用 WordPress 中的元数据(Metadata)

Wordpress中文章的特色图像Featured Image究竟存在哪里?的更多相关文章

  1. wordpress中文章发布时间不显示?用get_the_date代替the_date

    今天发现,在主题中部分地方使用the_date函数来显示文章发布的时间时,竟然发生不显示时间的情况,再仔细看了一下这些文章,有些都是经过几次修改和保存的,可能是由于the_date只是显示文章第一次发 ...

  2. 如何设置WordPress文章特色图像(Featured Image)

    WordPress的特色图像(Featured Image)是一个很方便的功能,过去为了给每篇文章设置一个缩略图,我们需要用脚本去匹配文章中的第一张或者最后一张图片,或者通过附件方式获取图片,有了特色 ...

  3. WordPress发布文章前强制要求上传特色图像

    如果你的网站需要给每篇文章设置特色图像才能达到理想的显示效果,而且允许其他用户在后台发布文章的,那么您可能需要强制要求他们给文章上传特色图像,否者就无法发布.Require Featured Imag ...

  4. 为WordPress某个文章添加额外的样式

    如需把css直接写在某文章,把下面代码放如function.php /* 为特定文章添加特定css最简单的方式. */ /*添加自定义CSS的meta box*/ add_action('admin_ ...

  5. wordpress获取文章特色图像路径函数wp_get_attachment_image_src()

    特色图像是wordpress主要的文章缩略图功能,几乎全部wordpress模板都使用或支持特色图像.今天介绍的wp_get_attachment_image_src()函数就是获取文章特色图像路径的 ...

  6. WordPress 获取文章内容页特色图像地址

    WordPress获取特色图像地址主要需要用到两个函数get_post_thumbnail_id和wp_get_attachment_image_src.下面是分别获取小.中.大.完整.指定图片规格的 ...

  7. PHP模版引擎twig wordpress中调用文章第一张图片

    wordpress当文章没有添加Featured media的时候, 就调用文章第一张图片, 调用的wordpress代码函数为: <?php echo catch_that_image(); ...

  8. WordPress获取特色图像的链接地址

    为什么要获取WordPress的特色图像呢? 这主要是因为,我们已经写好了静态模板文件,只有获取WordPress特色图像地址插入进去就可以了,非常方便. 还有就是有的时候,我们需要设置图片的宽度为1 ...

  9. 什么是WebP以及如何在WordPress中使用WebP图像

    图像通常是缓慢加载网页的最大原因之一.它们不仅减慢了加载时间,而且还可以占用服务器上的大量空间和资源.仔细选择文件类型并压缩它们有助于降低加载速度,但它们只能在图像质量受损之前进行优化.另一种选择是使 ...

随机推荐

  1. JS几种变量交换方式以及性能分析对比

    前言 "两个变量之间的值得交换",这是一个经典的话题,现在也有了很多的成熟解决方案,本文主要是列举几种常用的方案,进行大量计算并分析对比. 起由 最近做某个项目时,其中有一个需求是 ...

  2. http://localhost/ 或 http://127.0.0.1/ 报错:HTTP 404 的解决办法

    一些初次接触使用 Eclipse 工具来开发 JAVA Web 工程的开发人员,可能会对 Eclipse 和 Tomcat 的绑定产生一个疑惑. 那就是 在修改了 Tomcat 的8080端口为80后 ...

  3. Netty 实现SSL安全连接(wss://)

    原文:Netty5使用自签证书实现SSL安全连接 在客户端是https:// 协议下,使用ws:// 协议连接会报错的,得需要使用wss:// 连接.(ip连接失败时使用域名连接) netty创建服务 ...

  4. R语言编程艺术(1)快速入门

    这本书与手上其他的R语言参考书不同,主要从编程角度阐释R语言,而不是从统计角度.因为之前并没有深刻考虑这些,因此写出的代码往往是一条条命令的集合,并不像是“程序”,因此,希望通过学习这本书,能提高编程 ...

  5. 【知了堂学习笔记】java web 简单的登录

    最近皮皮潇在学习java web,刚接触了简单的东西,所以今天给大家带来一个简单的登录实现. 页面: 页面代码: <%@ page language="java" conte ...

  6. 【基础知识】Asp.Net基础三

    服务器端控件一般用于访问量不高的网站,要做到物尽其用. 服务器端控件: FIleUpload控件:向服务器上传文件 if (this.FileUpload1.HasFile) { // Path.Ge ...

  7. win10怎么修改svn的用户和密码

    win10怎么修改svn的用户和密码(一般为默认),其他的系统也差不多 方法/步骤 1.方法一: 1.双击我的电脑在c盘找到auth文件夹 C:\Users\系统帐户名\AppData\Roaming ...

  8. [ 原创 ] git使用技巧

    Git的使用--如何将本地项目上传到Github Git分支图介绍 https://www.cnblogs.com/cheneasternsun/p/5952830.html https://www. ...

  9. 关于void main()的误区

    很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的.C/C++ 中从来没有定义过void main( ) .C++ 之父 Bjarne Stroustrup 在他的主页上的 ...

  10. 关于JBoss日志中的报错Exception in thread "AWT-EventQueue-0"的解决记录

    一.前情提要 操作系统:Windows Server 2008 R2,JDK版本:1.6.0_45,应用容器:JBoss 4.2.3 GA.所部署的应用均为Web型项目,没有任何图形相关的项目. 二. ...