精通WordPress设计与开发:第5章 理解循环

➤理解循环的流程以及可以在哪里使用它
➤使用循环确定显示内容
➤用不同粒度的访问数据来定制循环
➤使用模板标签
➤理解全局变量及其与循环处理的关系
➤循环之外的工作

循环指的是WordPress如何决定在你访问的页面上显示什么内容(帖子、页面或自定义内容)。循环可以显示单个内容或一组帖子和页面,然后通过循环遍历内容显示;因此它被称为循环。

循环是WordPress默认显示文章的方式。循环根据一组参数从MySQL数据库中选择帖子,这些参数通常由访问你的WordPress网站的URL决定。例如,在默认情况下,主页可能会以逆时间顺序显示所有博客文章。通过URL(如http://example.com/category/halloween/)
访问的一个类别页面只显示分配到该类别的博客文章,在本例中是归入万圣节类别的文章。归档页面只显示以该特定月份和年份为日期的博客文章。WordPress将帖子的几乎所有参数映射到一个选择变量中,为同样多的改变循环内容选择算法的提供了基础。自定义内容显示是非常容易的,在本章你可以彻底的了解到当访问一个网站的链接时WordPress将一个URL转换成什么。

本章讨论主循环如何工作,在哪里可以使用循环,以及循环的逻辑流。它还介绍了如何使用WordPress中许多不同的函数和数据访问方法来定制循环。也将讨论维护当前状态的全局变量以及在循环之外的工作。

理解循环

理解Loop函数将帮助你理解如何控制它。控制循环来准确地显示你想要的内容将是你在开发WordPress网站中最常用的技能之一。循环是每个WordPress主题的核心,能够定制显示内容为WordPress的外观和操作打开了一扇门。

理解循环有助于分解WordPress生成页面内容的步骤:

  1. URL将与WordPress安装中的现有文件和目录进行匹配。如果文件存在,它将被web服务器加载。WordPress实际上并没有参与这个决定;这取决于你的web服务器和WordPress创建的.htaccess文件来决定URL是由web服务器处理的还是被转换为一个WordPress内容查询。这在第二章关于永久链接的讨论中已经讨论过了。
  2. 如果URL没有加载WordPress核心文件,则必须对其进行解析,以确定要加载什么内容。web服务器通过index.php加载WordPress核心来开始循环的设置。例如,当访问一个特定的标签页面(如http://example.com/tag/bacon)
    时,WordPress将确定你正在查看一个标签并加载相应的模板,选择使用该标签保存的文章,并为该标签页面生成输出。
  3. URL-to- content - selection的转换魔术发生在WordPress在早期创建的WP_Query对象中的parse_query()方法中。WordPress首先将URL解析为一组查询参数,这些参数将在下一节中描述。来自URL的所有查询字符串都被传递到WordPress中以确定要显示的内容,即使它们看起来像格式化好的路径名。如果你的站点使用的是漂亮的永久链接,这些永久链接中斜杠之间的值仅仅是查询字符串的参数。例如,http://example.com/tag/bacon与http://example.com?tag=bacon相同,它传递一个值为bacon的标签查询字符串
  4. 然后WordPress将规范的查询参数转换为MySQL数据库查询,以检索内容。这里的主要工作是WP_Query对象中的get_posts()方法,本章稍后将介绍该方法。get_posts()方法接受所有这些查询参数,并将它们转换为SQL语句,最终在MySQL数据库服务器上调用SQL字符串并提取所需的内容。然后,从数据库返回的内容保存在WP_Quer对象中,以便在WordPress循环中使用,并缓存以加快在执行另一个数据库查询之前对相同文章的其他引用。
  5. 一旦检索到内容,WordPress就会设置所有的is_conditional标签,比如is_home()和is_page()。这些设置是基于URL解析,执行默认查询的一部分,你可以考虑可能需要重置这些标记的情况。
  6. WordPress根据查询的类型和返回的帖子数量(例如,一个帖子或一个类别查询)从你的主题中选择一个模板,然后将查询的输出传递给默认调用的循环。

循环可以针对不同的网站目的定制。例如,一个新闻站点可能使用Loop来显示最新的新闻标题。企业目录可以使用Loop按名称的字母顺序显示本地企业,或者总是在显示的每个页面的顶部放置有关赞助企业的帖子。一个电子商务网站可能会使用这个循环来显示加载到网站上的产品。在WordPress中定制循环时,可能性是无限的,它可以让你完全控制选择的内容和显示的顺序。

从查询参数到SQL

一旦建立了查询参数(通过反汇编读者提供的URL或通过在自定义循环中显式地设置它们),WP_Query对象的get _posts()方法将这些参数转换为数据库查询的SQL。虽然你可以通过查询参数对内容的类型、选择和排序进行很好的控制,但WordPress核心也提供了过滤器,允许你更细粒度地更改生成的SQL以对内容选择和分组的控制。

SQL查询的基本格式是:SELECT fields FROM table WHERE conditions。“fields”是想要返回的数据库列;通常不需要修改查询的这一部分。WHERE子句中指定的“条件”将更改返回的帖子的顺序、分组和数量。如果你通过检查WP_Query对象的请求字段来转储生成的SQL查询,你将看到SQL的WHERE部分包含1=1作为第一个查询有条件的。如果没有其他内容选择参数,则1=1确保在没有其他WHERE子句的情况下生成的SQL不会出现语法错误;MySQL中的SQL优化器知道如何忽略1=1。

“Table”不仅仅是MySQL数据库中包含所有post数据的“posts”表;它还可以引用两个或多个表的SQL JOIN语句,在这些表中,你需要基于分层元数据选择posts。WordPress可以很容易地在一篇文章上放置多个标签,或者将一篇文章放在多个类别中,但关系数据库并不擅长管理这些层次或网络关系。正如你在第6章看到的,WordPress数据模型使用多个表来
管理这些复杂的关系,但是这使得诸如“查找所有标记为bacon的帖子”这样的查询更加难以执行。

例如,选择标记bacon的文章,一个SQLJOIN需要首先找到bacon在元数据分类,建立一个中间态表,在内存表的帖子标记bacon,然后选择那些id同时出现在中间态表和WordPress的内容表的文章。数据库爱好者称之为“笛卡尔积”或两个或多个表的内连接这对于描述查询复杂度和乘法级的内存消耗是准确的。

在第8章,将深入研究插件以及它们是如何附加到WordPress core中的过滤器和动作回调插入点上的。在生成SQL请求的过程中,有许多过滤器被调这是用来为插件作者提供后期绑定和明确的SQL执行控制能力。例如,考虑一个插件,它基于自定义post元数据和在单独的数据库表中维护的上下文来更改post的选择内容。

插件将使用posts_join过滤器重写join子句,添加另一个表和字段匹配子句以进一步扩展选择集。如果你想了解SQL生成的核心细节:大多数从查询到请求的解析是在wp‐includes/query.php中完成的,而JOIN的大部分工作是在wp‐includes/taxonomy.php中完成的。

关于SQL生成的最后一点:WordPress在构建规范url方面做得非常好,也就是说引用特定文章的方式只有一种。众所周知,搜索引擎认为http://example.com/bacon和http://example.com/2012/bacon为不同的页面,即使他们引用相同内容。WordPress core中的部分URL解析函数试图清理并将URL重定向到它们的规范形式;相同的函数还会尽一切努力返回一些相关内容,而不是404页面。这样设计的结果是,如果试图通过名称加载页面却没有返回任何内容,WordPress将在包含帖子名称的WHERE子句中插入一个LIKE修饰符。例如,如果用户提供了URL http://example.com/2015/lecter,但您没有以“Lecter”为标题的帖子,则LIKE子句将匹配任何以“Lecter”开头的帖子,例如“Lecter Fish IPA Review”。规范的URL和“like name”匹配是复杂的URL重写和意图解析迷宫的一部分,这是试图产生好的用户体验,而不是一个恼人的404错误。

理解WordPress中的内容

在详细研究循环之前,了解WordPress中不同类型的内容是很重要的。默认情况下,WordPress定义了两种类型的内容:帖子和页面。我们将在第6章看到,所有内容类型都存储在同一个MySQL表中,并通过它们的“post类型”进行区分。自从WordPress 2.9发布以来,你可以定义你自己的自定义文章类型,这基本上就是WordPress的自定义内容。例如,你可以有一个自定义事件文章类型来在WordPress中注册事件。

在本章中,内容被称为“帖子”,但重要的是要记住,帖子(post)可以是WordPress中的任何类型的内容。

将循环放在上下文中

循环是主题的核心,它控制内容的显示方式。它是MySQL数据库数据和访问者浏览器中呈现的HTML之间的连接。基本上,任何一个帖子或页面被显示的地方,WordPress都会使用这个循环。这可以是一个单一的文章或页面,一个循环的文章,或具有不同显示选项的一系列循环。

大多数WordPress主题都有页眉、页脚和侧边栏元素。图5-1显示了如何将循环直接放置在这些元素的中间,创建你的网站内容区域。你的网站的一部分通常是动态的,会随着你的浏览而改变。

 

 

默认情况下,在WordPress主题模板文件中使用循环。自定义循环可以在主题模板文件的任何地方创建,如图5-2所示。自定义循环也用于插件和小部件。循环可以在WordPress的任何地方使用,但是根据使用地点的不同创建自定义循环的方法是不同的,每种构造的潜在副作用也会有所不同。

多重循环可以在主题模板文件中使用。自定义循环可以在你的页眉、侧边栏、页脚和网站的主要内容区域创建。在您的网站上没有限制可以显示循环的数量。记住,Loop实际上是选择内容的数据库查询,然后是对所选内容进行迭代以显示内容。默认的循环使用访问URL的上下文来进行选择,但是你可以对WordPress内容数据库进行微调和制作查询来实现任意数量的内容管理进程。

下一节将介绍循环的基本流程控制和提供的用于定制在循环中处理内容时显示方式的WordPress模板函数。用这些基础知识武装你。你将探索建立基于手工裁剪这些查询参数的自定义循环。

循环的流程

循环使用一些标准编程条件语句来确定显示什么以及如何显示。循环中的第一个语句是if语句,用于检查是否存在任何文章,因为你可能没有任何带有指定类别或标记的文章。如果存在内容,则使用while语句来初始化Loop,并遍历需要显示的所有postsor页。最后,调用_post()函数来构建post数据,使其他WordPress函数可以访问它。一旦生成了帖子数据,就可以以你喜欢的任何格式显示Loop内容。下面是一个最小的Loop示例。这个例子提供了循环正常运行所需的唯一元素:

<?php
if ( have_posts() ) :
	while ( have_posts() ) :
		the_post();
		//loop content (template tags, html, etc)
	endwhile;
endif;
?>

这是PHP代码,所以它需要被包围在标签中。这是最简单形式的循环。如果你想知道数据库查询的输出是怎么交给这个简单的循环没有变量作为参数传递时,答案就在于全局变量$wp_quer,这是一个WP_Query实例,这个简单循环例子引用了这个实例。实际上,它是Loop的默认查询动作。注意,在调用这个默认循环时,WordPress已经在默认查询对象中调用了get _ posts()方法来为正在查看的URL构建适当的内容列表,在本例中,循环负责显示该帖子列表。稍后,你将了解如何使用结构查询来对后选择进行精细控制,但现在可以假设数据库的繁重工作已经完成,并且当循环被调用时,结果已经存储在$wp_quer中。

在WordPress中运行循环有一些非常简单的要求。我们分解这个例子,看看循环的不同部分:

if ( have_posts() ) :

这一行检查是否有任何文章或页面将显示在您正在查看的当前页面上。如果存在文章或页面,下一行将执行:

while ( have_posts() ) :


前面的while语句开始循环,本质上是循环遍历要在页面上显示的所有帖子和页面,直到没有更多的帖子和页面。当存在要显示的内容时,循环将继续。
一旦显示了所有内容,while循环将结束。have_ posts()函数只是检查正在处理的posts列表是否已经耗尽,或者没有开始的条目。

the_post();

接下来,调用the_post()函数来加载所有post(帖子)数据。这个函数必须在循环中调用,以便正确设置post数据。反过来调用_post()调用setup_postdata()函数来设置每一篇文章的元数据,比如循环中显示的内容的作者和标签,以及文章本身的内容。这个数据被分配给一个全局变量每次循环迭代时,此数据都被分配给一个全局变量。具体地说,调用_post()会产生一个副作用,即设置全局变量$post,这些变量被后面描述的大多数模板标记所使用,然后进入列表中的下一篇文章。设置post数据还需要对来自WordPress数据库的原始内容应用适当的过滤器。WordPress按照用户输入的方式存储用户编辑过的内容,所以如果用户添加了一个短代码,例如在文章结尾添加一个谷歌的AdSense项目,短代码就会存储在数据库内容中。当post设置完成后,会调用将短代码转换为JavaScript块的插件,以及其他修改原始post内容的注册插件。你将在第8章看到插件机制,但是现在,重要的是注意WordPress查询对象中的原始post数据和最终呈现的过滤后内容之间的区别。

//loop content


这是放置所有Loop模板标签的地方,以及你想在Loop中显示的任何额外代码。这将在本章后面详细讨论。

endwhile;
endif;

endwhile和endif调用结束循环。放置在这两行之后的任何代码都将显示在页面的底部,在所有帖子都显示之后。如果循环中没有要显示的内容,还可以放置一个else子句来显示消息。在主题模板文件中,Loop通常被HTML标记包围着。下面的代码显示了WordPress附带的Twenty Fourteen主题中的循环结构:

<div id="main-content" class="main-content">
<?php
	if ( is_front_page() && twentyfourteen_has_featured_posts() ) {
	// Include the featured content template.
	get_template_part( 'featured-content' );
	}
?>

	<div id="primary" class="content-area">
		<div id="content" class="site-content" role="main">
		<?php
			if ( have_posts() ) :
				// Start the Loop.
				while ( have_posts() ) : the_post();
				/*
				* Include the post format-specific template for the content.
				If you want to
				* use this in a child theme, then include a file
				called called content-___.php
				* (where ___ is the post format) and that will be used
				instead.
				*/
			
				get_template_part( 'content', get_post_format() );
				endwhile;
				// Previous/next post navigation.
				twentyfourteen_paging_nav();
			else :
				// If no content, include the "No posts found" template.
				get_template_part( 'content', 'none' );
				endif;
		?>
	</div><!–– #content ––>
	</div><!–– #primary ––>
	<?php get_sidebar( 'content' ); ?>
</div><!–– #main-content ––>

注意最小的Loop元素是如何存在的它被HTML标记包围着。这是一个普通的主题模板文件将如何利用循环结构的示例。HTML元素可以改变,但Loop元素保持不变。通过模板标记来定制显示内容的样式,并选择要包含在页面组成中的帖子元数据。

模板标签

WordPress主题模板中用于显示Loop内容的PHP函数称为模板标签。这些标签用于显示关于网站和内容的特定数据。这允许你的在你的网站上自定义内容的显示的方式和位置。

例如,_ title()模板标签在循环中显示文章或页面的标题。使用模板标记的主要好处是你不需要了解PHP代码就可以使用它们。

WordPress中有许多不同的模板标签。有些模板标记必须在Loop中,而其他标记可以在主题模板文件的任何地方使用。注意在上下文中模板标签指的是用于提取发布数据以供显示的WordPress函数;模板文件是控制如何显示特定内容类型的内容的主题元素。模板文件包含由模板标签组成的循环。关于WordPress中可用的更新模板标签列表,请访问http://codex.wordpress.org/Template_Tags。

常用模板标签

模板标记有很多,但通常你只会在循环中使用少量标记。下面是循环中最常用的模板标记。这些模板标记将返回并显示列出的post数据。

➤the_permalink() -显示你帖子的URL。
➤the_title() -显示帖子的标题。
➤the_ID() -显示你帖子的唯一ID。
➤the_content() -显示帖子的完整内容。
➤the_excerpt()-显示帖子的摘录。如果在Post编辑屏幕上填写了摘录字段,将使用它。如果没有,WordPress会自动从你的帖子内容中生成一个简短的摘录。
➤the_time() -显示你的帖子发表的日期/时间。
➤the_author()——显示帖子的作者。
➤the_tags()-显示贴在帖子上的标签。
➤the_category()-显示分配到该类别的帖子。
➤edit_post_link() -显示一个编辑链接,只有当你登录并允许编辑文章时才会显示。
➤comment_form() -为你的帖子显示一个完整的评论表单。

要了解模板标记是如何工作的,只需将任何模板标记放置在循环中并查看结果。下面的示例显示了两个不同模板标签的值:

<?php
	if ( have_posts() ) :
		while ( have_posts() ) :
		the_post();
	?>
	<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	<br />
	<?php
		the_content();
		endwhile;
	endif;
?>

正如所看到的,你的文章标题显示了链接到每个文章的永久链接。文章的内容直接显示在文章标题的下方。

标签参数

大多数模板标记都有参数,可以添加这些参数来修改返回的值。例如,_content()模板标签有两个参数。第一个参数允许你像这样设置更多的链接文本:

<?php the_content( 'Read more', false ); ?>

你的帖子内容将正常显示,但当遇到  标签,WordPress将自动添加文本阅读更多,这将链接到整个博客文章。第二个参数决定在查看全文时是否再次显示预告段。默认值是false,所以预告片将在两个地方显示。

WordPress中 more 标签允许你在你的网站上显示一个定义好的预告片。例如,你可以显示第一段内容,而当访问者点击链接查看完整的博客文章时,才显示完整的博客文章。为了做到这一点,你可以放置 标签在HTML视图的内容中想要中断发生的地方。在可视化编辑器中,有一个按钮用于插入More标记。

你还可以向支持参数的任何模板标记发送多个参数。例如,模板标签_ title()接受三个参数:$before, $after和$echo。下面的代码通过设置_title()标签中的$before 和 $after 参数来装饰H1标签

<?php the_title( '<h1>', '</h1>' ); ?>

你也可以在WordPress源代码中查看实际功能。post模板函数位于wp‐includes/post-template.php中。快速搜索_title()函数将引导你找到_title()标记的确切函数。你还可以使用Codex来详细描述正在使用的模板标记,在本例中为http://codex.wordpress.org/Template_Tags/the_title

定制循环


在循环控制流的讨论中提到,数据选择主要是WP_Query对象的get_posts()方法的工作。在大多数情况下,如果你想构建一个自定义循环,你要构建自己的WP_Query对象并显式地引用它。或者,你可以使用更低级的query_ posts()和get _ posts()函数(不要与WP_Query对象中的同名方法混淆)来操作默认的传递到循环中的查询输出。query_posts()和get_ posts()都使用WP_Query类来检索内容。你要检查的最后一个方法是pre_get_posts回调函数。该回调函数在查询变量对象创建之后但实际查询运行之前调用。后面你将了解各种方法,并讨论应该(和不应该)在何处以及如何使用它们,但是让我们先讨论如何构建自定义查询对象。

WP_Query对象

一旦WordPress收到一个要web服务器解析的URL,它就开始分解URL中的元素,并将它们转换为数据库查询的参数。下面是操作自己的WP_Query时发生的更多细节。

WP_Query是一个在WordPress中定义的类,可以很容易地创建自己的自定义循环。query_posts()和get_posts()都使用WP_Query类来检索WordPress内容。当你使用query_posts()时,全局变量$wp_query被用作WP_Query的实例,使$wp_query成为若干操作的默认数据存储。自定义循环可以用在你的主题模板文件的任何地方,以显示不同类型的内容;它们必须构建在WP_Query变量的不同实例上。

当创建一个新的WP_Query对象时,它将使用一些默认函数进行实例化,这些函数用于构建查询、执行查询以获取帖子以及从URL中解析参数。然而,你也可以使用这些内建的对象方法来构造你自己的参数字符串,创建自定义循环来提取你在循环中那个点时所需要的任何特定内容。下面是一个自定义循环的例子,它显示你的网站上的最新帖子:

<?php
$myPosts = new WP_Query( 'posts_per_page=5' );while ( $myPosts-
>have_posts() )
: $myPosts->the_post();
?>
<!–– do something ––>
<?php endwhile; ?>

与在基本循环中使用更简单的have_posts()和_post()调用不同,自定义循环调用新创建的WP_Query对象$myPosts的方法。这里显示的显式调用和默认的have_posts()调用在功能上是等价的;例如,have_posts()只是调用$wp_query‐>have_posts()使用全局查询变量作为默认查询,这个全局变量也就是解析web服务器交给WordPress的URL时生成的查询变量。

从用于调用WordPress的URL进入默认循环;还有一个额外的步骤,使用查询对象的parse _ query()方法获取URL并将其解析为一个适当的查询字符串。

当您构建自己的自定义循环时,您可以显式地设置想要控制查询的参数。下面是查询函数内部发生的更多细节:

  • 通过函数$myPosts‐>get_posts()将参数转换为SQL语句调用$myPosts‐>query(),然后对MySQL数据库执行查询并提取所请求的内容。
  • 查询调用设置条件标记同样重要如is_home()和is_single(),这些标记取决于显示的页面类型和该页面的内容数量。
  • 这个查询返回的帖子数组被WordPress缓存,这样以后对同一个查询的引用就不会产生额外的数据库查询。

构建强大的自定义循环的关键是将内容选择条件映射到正确的查询参数集中。

创建自定义查询

参数用于定义在循环中返回什么内容,无论是自定义循环还是改变主循环。在创建循环时,了解哪些参数可以帮助定义将要显示的内容是非常重要的。
在创建自定义循环时,可以使用许多不同的、有时令人困惑的参数来更改内容的输出。

通过使用&号分隔参数名称和值,还可以在每次查询中设置多个参数。有关可用参数的详细列表,请访问http://codex.wordpress.org/Class_Reference/WP_Query#Parameters。
下面几节将介绍一些更常用的参数。

帖子(post)参数

要显示的帖子的数量和类型最明显的,有时也是最常用的参数选择:
➤p=2 -通过post ID加载一篇文章。
➤name=my‐slug -基于post slug加载帖子(permalink tail)。
➤post_status=pending -根据帖子状态加载帖子。例如,如果您选择只查看草稿,则使用post_status=draft。
➤ignore_sticky_posts -排除第一个返回的sticky posts。sticky posts总是排在贴子列表的最前面,与为查询设置的其他参数无关。你可以有多个sticky posts,它们在引起对新闻公告的注意、突出显示更改或以其他方式吸引读者的注意时很有用,该参数允许将它们从列表顶部的优先级槽中删除。
➤post_type=post -根据类型加载文章。如果你只想查看页面(page),而不是帖子(post),post_type=page将检索它们。这个参数允许特殊目的的循环根据自定义文章类型来选择内容,具体将在第7章看到。
➤posts_per_page=5 -每页加载的文章数量。这是默认值。要显示所有帖子,将此参数设置为-1。
➤offset=1 -加载前跳过的文章数量

页面(page)参数

控制Pages选择的参数类似于posts的参数:
➤page_id=5 -通过ID加载一个单独的页面。与帖子ID和用户ID一样,页面ID也可以在仪表板中找到,只需将鼠标悬停在页面上,查看浏览器底部显示的URL。
➤pagename=Contact -通过名称加载页面,在这种情况下一般是联系人页面。
➤pagename=parent/child -通过slug加载一个子页面,或者slug的层次结构(也就是路径)。

类别、标签和作者参数

帖子还可以根据它们被放置的类别、应用到帖子的标签或作者信息进行分类:
➤cat=3,4,5 -根据类别ID加载帖子。
➤category_name=About Us -基于类别名称加载帖子。请注意,如果一篇文章属于多个类别,它将显示在每个类别的选择中。
➤tag=writing -根据标签名称加载帖子。
➤tag_id=34 -根据标签ID加载帖子。
➤author=1 -根据用户ID加载帖子。
➤author_name=brad -根据作者的名字加载帖子。
➤author__in & author__not_in -根据用户ID加载帖子。

时间和日期参数

建立文章存档和通过网站主页上的日历提供内容视图的关键是根据时间顺序选择内容,它的参数:
➤monthnum=6——6月份发布的所有帖子。
➤day=9——在一个月的第9天发布的帖子。
➤year=2015——2015年新增的职位。

排序和自定义字段参数

你还可以更改排序参数和排序顺序。如果你正在构建一个在线索引,并希望显示按字母顺序排列的帖子列表,那么按月和作者设置查询帖子的参数,但按标题排列结果。自定义字段参数允许你根据帖子元数据查询帖子。

➤orderby=title -排序帖子的字段。
➤order=ASC -定义order为升序或降序。
➤meta_key=color -通过自定义字段名加载帖子。
➤meta_value=blue -根据自定义字段值加载帖子。必须与meta_key参数一起使用。
➤meta_query -用于更高级的自定义字段(元数据)查询。

全部组合在一起

现在来看一些使用参数的例子。下面的例子使用$myPosts‐>query()函数,该函数来自本例中创建的$myPosts自定义查询对象,用来选择自定义循环中显示的内容。根据帖子ID显示帖子:

$myPosts = new WP_Query( 'p=1' );

显示5个最新的帖子,跳过第一个帖子:

$myPosts = new WP_Query( 'posts_per_page=5&offset=1' );

显示从今天开始的所有帖子:

// display all posts from the current date
$today = getdate(); // get todays date
$myPosts = new WP_Query('year=' .$today["year"].'&monthnum='.$today["mon"].'&day='.$today["mday"] );

显示2015年10月31日以来的所有帖子:

$myPosts = new WP_Query( 'monthnum=10&day=31&year=2015' );

显示所有的帖子从类别ID 5带 bacon标签:

$myPosts = new WP_Query( 'cat=5&tag=bacon' );

显示所有带有bacon标签的帖子,不包括类别ID 5的帖子:

$myPosts = new WP_Query( 'cat=-5&tag=bacon' );

显示所有贴子的写或读标签:

$myPosts = new WP_Query( 'tag=writing,reading' );

显示所有贴子与标签写和读和tv:

$myPosts = new WP_Query( 'tag=writing+reading+tv' );

使用一个名为color的值为蓝色的自定义字段显示所有帖子:

$myPosts = new WP_Query( 'meta_key=color&meta_value=blue' );

在页面中添加循环

如果你的自定义Loop需要分页(导航链接),则需要采取一些额外的步骤。分页目前只设计用于$wp_query全局变量;也就是说,它在默认循环中工作,需要一些技巧使它在自定义循环中工作。你需要欺骗WordPress,让它认为你的自定义查询实际上是$wp_query,以便分页工作。

<?php
$temp = $wp_query;
$wp_query= null;
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$wp_query = new WP_Query( 'posts_per_page=5&paged='.$paged );
while ( $wp_query->have_posts() ) : $wp_query->the_post();
?>
	<h2>
	<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</h2>
	<?php the_excerpt(); ?>
<?php endwhile; ?>

首先,必须将原始的$wp_query变量存储到临时变量$temp中。接下来,将$wp_query设置为null以完全清除它。这是WordPress中可以覆盖全局变量值的少数几个场景之一。现在将新的WP_Query对象设置为$wp_query变量,并通过调用对象的query()函数来执行它,以为你的自定义循环选择posts。注意添加到查询末尾的$page变量。它使用get_query_var()函数存储当前页面,这样WordPress就知道如何显示导航链接。现在显示你的页面导航链接:

<xmp>
<div class="navigation">
	<div class="alignleft"><?php previous_posts_link( '&laquo; Previous' );
?></div>
	<div class="alignright"><?php next_posts_link( 'More &raquo;' ); ?></div>
</div>
</xmp>

最后,你需要重置$wp_ query回它原来的值:

<?php
$wp_query = null;
$wp_query = $temp;
?>

现在的自定义循环将基于返回的内容会包含适当的分页。

使用pre_get_posts 回调函数


pre_get_posts 回调允许你修改WordPress网站上的任何循环查询。通常,这个回调是修改WordPress主循环的首选方法。pre_get_posts回调函数通过引用接受全局的WordPress查询,这使它能够在运行查询之前修改查询变量。简而言之,这个回调函数使得在调用数据库检索内容之前很容易修改一个WordPress Loop。

使用pre_get_ posts钩子时,通常会将代码放在主题的functions.php文件中。让我们看一个pre_get_ posts的例子:

function prowp_exclude_category( $query ) {
if ( $query->is_home() && $query->is_main_query() && ! is_admin() ) {
     $query->set( 'category_name', 'halloween' );
}
}
add_action( 'pre_get_posts', 'prowp_exclude_category' );

在前面的例子中,你正在修改主WordPress循环,使其只在主页上显示万圣节类别中的帖子。如你所见,该示例使用条件来验证查询仅在主页上修改而不是仪表板。

使用条件函数可以让你只在WordPress的特定区域修改循环。一个常见的例子是修改WordPress搜索结果。默认情况下,WordPress搜索包括文章和页面。
让我们假设你只希望在搜索结果中返回帖子:

function prowp_search_filter( $query ) {
	if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
	$query->set( 'post_type', 'post' );
	}
}
add_action( 'pre_get_posts', 'prowp_search_filter' );

pre_get_ posts回调函数过滤了一个WP_Query对象,这意味着你可以用WP_ Query做任何事情,你也可以用set()函数用pre_ get _ posts做任何事情。这包括本章前面回顾过的所有Loop参数。想了解更多关于pre_get_ posts回调的信息,请访问Codex页面http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts。

使用query_posts( )

通过为循环指定适当的参数集,可以完成大量的定制工作。虽然WP_Query对象是从WordPress数据库中提取内容的最通用的机制,但是你还会遇到其他更底层的方法。
query_posts()函数能够方便地修改默认的WordPress循环返回的内容。具体来说,可以在默认数据库查询执行后修改$wp_query返回的内容,微调查询参数,并使用query_posts()重新执行查询。以这种方式调用query_posts()的缺点是,之前从默认查询缓存的结果将被丢弃,因此使用这种快捷方式会导致数据库性能下降。query_posts()函数应该直接放在循环开头的上方:

query_posts( 'posts_per_page=5&paged='.$paged );
if ( have_posts() ) :
	while ( have_posts() ) : the_post();
		//loop content (template tags, html, etc)
	endwhile;
endif;

这个例子告诉WordPress只显示5个帖子。
显式调用quer posts()会覆盖为循环提取的原始帖子内容。这意味着在使用query posts()之前希望返回的任何内容都不会返回。例如,如果传递给WordPress的URL是一个类别页面http://example.com/category/zombie/,那么在query_ posts()被调用后,没有一个zombie类别的帖子会出现在帖子列表中,除非有一个帖子是在最近的第5个帖子中。当将查询字符串传递给query _ posts()时,会显式地覆盖URL解析和默认处理所建立的查询参数
为了避免丢失原来的Loop内容,你可以使用全局变量$query_string保存解析后的查询参数:

// initialize the global query_string variable
global $query_string;
// keep original Loop content and change the sort order
query_posts( $query_string . "&orderby=title&order=ASC" );

在前面的例子中,你仍然可以看到所有zombie类别的帖子,但它们将按字母顺序升序排列。此技术用于修改原始的Loop内容而不丢失原始内容。

还可以将所有query_posts()参数打包到一个数组中,从而更容易管理。下面是一个在WordPress中使用数组$args来存储参数值的例子:

$args = array(
'posts_per_page' => 1,
'post__in' => get_option( 'sticky_posts' )
);
query_posts( $args );

如果没有发现sticky帖子,则将返回最新的帖子。query_posts()函数仅用于修改主页面的Loop。它不创建额外的自定义循环。如果你想对默认查询做一点更改—例如,向每个显示的页面添加特定类别或标记的帖子—那么query _ posts()方法是一个快捷方式。然而它并非没有副作用或警告:

  • Query_posts()修改了全局变量$wp_query,并有其他副作用。它不应该被多次调用,也不应该在循环中使用。该示例显示了在处理post之前对query_posts()的调用,即将额外参数添加到查询字符串中,但在循环开始逐步遍历返回的处理列表之前。多次调用query_posts(),或在循环内部调用,可能导致主循环不正确或者显示非预期的内容。
  • Query_posts()会取消全局$wp_query对象的设置,这样做可能会使条件标签的值无效,如is_page()或is_home()。遍历整个WP_Query实例化对象将适当地设置所有条件标记。例如,,你可能会发现通过快捷方式已经向一个选择添加了内容,而找到的默认查询只包含一篇文章,因此is_single()不再有效。
  • 调用query_posts()将执行另一个数据库查询,使来自第一次默认查询的所有缓存结果无效。它会导致你执行的数据库查询数量至少翻倍,并且每次返回MySQL都会导致性能下降;另一方面,当你到达默认循环时默认查询已经运行,所以如果你正在构建一个完全自定义的主循环,那几乎没有机会绕过它。

使用get_posts( )

与query_posts()类似,还有一个更简单的替代访问函数get_posts(),用于检索原始post数据。你会看到get_posts()用于管理页面生成一个特定类型的页面列表,或者它可能是一个插件中使用为一组文章获取所有原始数据并检查模式,如常见的术语,标签,或外部链接,丢弃的目的内容后快速消化。它的目的不是面向用户的内容显示,因为它关闭了大部分在一般的WP_Query方法中完成的查询处理和过滤。

具体来说,get_posts()缺少的是设置所有全局数据以使模板标签反映当前的post数据的能力。一个主要的问题是,不是所有的模板标签都可以使用get_posts()。要解决这个缺陷,你需要调用setup_postdata()函数来填充在循环中使用的模板标记。下面的例子展示了如何使用get_posts()检索单个随机帖子

<?php
$randompost = get_posts( 'numberposts=1&orderby=rand' );
foreach( $randompost as $post ) :
	setup_postdata( $post );
?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php the_content(); ?>
<?php endforeach; ?>

使用get_posts()时,将注意到另一个主要区别——返回的值是一个数组。foreach循环代码用于循环遍历数组值。这个示例只返回一个帖子,但是如果返回了多个帖子,就会循环遍历每个帖子。然后调用setup_postdata()函数来填充模板标记的数据。记住你也可以使用数组设置get _ posts()形参:

<?php
$args = array(
	'numberposts' => 1,
	'orderby' => rand
);
$randompost = get_posts( $args );

虽然你可能看到使用get_posts()或query_posts()结构的旧代码,但WP_Query是首选的方法,它是自定义循环语法的核心。然而有时你会想要通过get_posts()提供的快速访问来生成额外的上下文或数据,以便在循环或插件中进一步定制。

在WordPress中使用循环时,理解在什么时候使用什么循环方法是很重要的。当更改页面上的主查询时,应该使用pre_get_posts回调函数。WP_Query对象应该用于主题模板和插件中的所有次级循环。

重置查询

当自定义主循环或创建自定义循环时,在完成后重置循环数据是一个好主意。WordPress提供了两个不同的函数来处理这个问题:wp_ reset _postdata()和wp_reset_query()

重置post数据的第一个方法是wp_reset _ data()。这个函数实际上将全局$post变量恢复到主查询中的当前post。当使用WP_Query创建自定义循环时,这是首选的方法。

例如,假设在主题的header.php文件中有以下自定义循环:

<?php
$myPosts = new WP_Query( 'posts_per_page=1&orderby=rand' );
// The Loop
while ( $myPosts->have_posts() ) : $myPosts->the_post();
	?><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br
/><?php
endwhile;
?>

这将在你的主题标题中显示一个随机的帖子。这段代码会更改页面上其他循环的主要查询对象,原始查询数据将不可用。这可能会在主题的主要循环上产生意外的结果。要解决这个问题,在你的自定义循环之后直接调用wp_reset_postdata(),如下所示:

$myPosts = new WP_Query( 'posts_per_page=1&orderby=rand' );
// The Loop
while ( $myPosts->have_posts() ) : $myPosts->the_post();
?>
<?php
endwhile;
// Reset Post Data
wp_reset_postdata();

调用这个函数将把$post变量恢复到查询当前post时的状态。这样将消除正在查看的页面的主查询中的任何奇怪之处。重置post数据的第二种方法是wp_reset_query()函数。有时,你可能会遇到页面级条件标签在自定义循环创建后被使用的问题。条件标签允许你在wordpress的不同页面上运行不同的代码——例如,使用条件标签is_home()来确定你是否正在查看博客主页面。正如“使用query_posts()”一节中所指出的,这个问题是由潜在的根据数据库查询的原始值在设置条件标记后更改数据库查询的输出导致。要解决这个问题,需要调用wp_reset_query()。这个函数将正确地恢复原始查询信息,包括在URL解析过程中早期设置的条件标记。参考以下例子:

<?php query_posts( 'posts_per_page=5' ); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
	<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br />
<?php endwhile; endif; ?>
<?php
if( is_home() && !is_paged() ):
	wp_list_bookmarks( 'title_li=&categorize=0' );
endif;
?>

执行此代码将返回最新的5篇文章,然后是保存在你的WordPress链接管理器中的链接。会遇到的问题是is_home()条件标签不会被正确解释,这意味着你的链接会显示在每个页面上,而不仅仅是主页。要修复这个问题,你需要在循环下面直接包含wp_reset_query()



<?php query_posts( 'posts_per_page=5' ); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
	<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br />
<?php endwhile; endif; ?>
<?php wp_reset_query(); ?>
<?php
if( is_home() && !is_paged() ):
	wp_list_bookmarks( 'title_li=&categorize=0' );
endif;
?>

现在你已经正确地恢复了你的循环实例的WP_Query对象,条件标签is_home()将跟随你的链接只显示在你的网站的主页上。在循环中使用query_posts()之后添加wp_reset _query()是一个很好的方法,以确保以后不会遇到问题。wp_reset_query()函数实际上调用wp_reset_postdata(),但是它执行了一个额外的步骤。这个函数在重置前实际上会销毁前一个查询。简而言之,wp_reset_query()应该总是在query_posts()循环之后使用,而wp_reset_postdata()应该在WP_Query或get_posts()自定义循环之后使用。

多个loop

循环可以在你的主题和插件中多次使用。这使得在WordPress网站的多个地方显示不同类型的内容变得很容易。也许你想在网站的每个页面下面显示你最近的博客文章。您可以通过创建更复杂的循环来多次遍历文章列表,或者生成多个要循环的文章数组来实现这一点。

嵌套循环

嵌套循环可以结合主循环和单独的WP_Query实例在主题模板中创建。例如可以创建一个嵌套的Loop来根据post标签显示相关的帖子。下面是一个在主循环中创建嵌套循环的示例,以显示基于标签的相关文章:

<?php
if ( have_posts() ) :
	while ( have_posts() ) :
		the_post();
		//loop content (template tags, html, etc)
		?>
		<h1><a href="<?php the_permalink(); ?>"><?php the_title();
?></a></h1>
		<?php
		the_content();
		$tags = wp_get_post_terms( get_the_ID() );
		if ( $tags ) {
			echo 'Related Posts';
			$tagcount = count( $tags );
			for ( $i = 0; $i < $tagcount; $i++ ) {
				$tagIDs[$i] = $tags[$i]->term_id;
		}
		$args=array(
			'tag__in' => $tagIDs,
			'post__not_in' => array( $post->ID ),
			'posts_per_page' => 5,
			'ignore_sticky_posts' => 1
		);
		$relatedPosts = new WP_Query( $args );
		if( $relatedPosts->have_posts() ) {
			//loop through related posts based on the tag
			while ( $relatedPosts->have_posts() ) :
			$relatedPosts->the_post(); ?>
			<p><a href="<?php the_permalink(); ?>">
				<?php the_title(); ?></a></p>
			<?php
		endwhile;
}
}
endwhile;
endif;
?>

此代码将正常显示所有帖子。在主循环中,检查是否有其他文章包含与主文章相同的标记。如果是,则显示与之匹配的最新5个帖子为相关帖子。如果没有匹配的帖子,相关的帖子部分将不显示。

Multi‐Pass Loops

rewind_posts()函数用于重置post查询和循环计数器,允许你使用与第一次循环相同的内容进行另一次循环。在你完成第一个循环之后直接放置这个函数调用。下面是一个处理主循环内容两次的例子:

<?php while ( have_posts() ) : the_post(); ?>
	<!–– content. ––>
<?php endwhile; ?>
<?php rewind_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
	<!–– content ––>
<?php endwhile; ?>

高级查询

你也可以在循环中执行更高级的查询。我们构造一个循环,它将使用meta _ compare参数比较自定义的字段值:

$args = array(
'posts_per_page' => '-1',
'post_type' => 'product',
'meta_key' => 'price',
'meta_value' => '13',
'meta_compare' => '<=' ); $myProducts = new WP_Query( $args ); // The Loop while ( $myProducts->have_posts() ) : $myProducts->the_post();
?>
<?php
endwhile;
// Reset Post Data
wp_reset_postdata();

如你所见,meta_compare参数用于显示所有价格的元值小于或等于(<=) 13的产品。meta_compare形参可以接受各种比较操作符,比如!= ,  > , >= ,  < ,  <= , 以及默认值=对于更复杂的元数据查询,使用meta_query参数。现在可以对前面的示例进行扩展。除了返回价格小于或等于13的产品条目外,你还可以只返回蓝色的产品:

$args = array(
	'post_type' => 'product',
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => 'blue',
			'compare' => '='
		),
		array(
		'key' => 'price',
		'value' => '13',
		'type' => 'numeric',
		'compare' => '<='
		)
	)
);
$myProducts = new WP_Query( $args );
// The Loop
while ( $myProducts->have_posts() ) : $myProducts->the_post();
	?><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br
/><?php
endwhile;
// Reset Post Data
wp_reset_postdata();

注意,meta_query接受一个参数数组。在本例中,数组中的第一项是一个用于验证产品是蓝色的数组。第二个参数是一个数组,用于验证产品价格是否小于或等于13。使用元查询参数创建的循环可以非常强大。这是创建复杂网站的一个重要工具。
复杂的基于日期的查询可以使用date_query参数创建。让我们来看一个例子:

$args = array(
	'date_query' => array(
		array(
			'after' => array(
				'year' => '2015',
				'month' => '6',
				'day' => '1'
				),
			'before' => array(
			'year' => '2015',
			'month' => '8',
			'day' => '31'
			),
		'inclusive' => true
		),
	)
);
$my_posts = new WP_Query( $args );

// The Loop
while ( $my_posts->have_posts() ) : $my_posts->the_post();
	?><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br
/><?php
endwhile;

// Reset Post Data
wp_reset_postdata();

上述代码将显示2015年夏季(6月1日至8月31日)发布的所有帖子。使用date_query参数,可以根据想要显示的发布日期设置之后和之前的值。inclusive参数在使用after和before参数时使用,并设置是否应该匹配确切的值。在这个例子中,你想要包含6月1日和8月31日发布的帖子,所以把值设置为true。before和after参数也接受strtotime兼容的字符串,所以你可以像这样简化这个查询:

$args = array(
'date_query' => array(
	array(
		'after' => 'June 1st, 2015',
		'before' => 'August 31st, 2015',
		'inclusive' => true
		)
	)
);
$my_posts = new WP_Query( $args );

下面的代码将返回与第一个示例完全相同的结果,但是它更容易阅读和理解。

date_query参数也可以与常规循环参数结合使用。举个例子,让我们返回去年评论最多的帖子:

$args = array(
	'date_query' 	=> array(
		'after' 	=> '1 year ago',
		'before'	 => 'today',
		‘inclusive’ => true,
	),
	'orderby' 		=> 'comment_count',
	'order' 		=> 'DESC',
	'posts_per_page' => '5'
);

$my_posts = new WP_Query( $args );

在本例中,使用date_query参数返回1年前到今天之间发布的所有帖子。还可以将orderby值设置为comment_count,将order设置为DESC。这将首先返回评论数最高的帖子。最后一个参数是posts_per_page,它告诉查询只返回5个posts。很容易看出date_query参数在你的循环中是多么的强大。

全局变量

全局变量是指已定义可以在WordPress执行环境中的任何地方访问的变量。这些变量存储了关于Loop内容、作者和用户的所有类型的信息,以及关于WordPress安装的特定信息,比如如何连接到MySQL数据库。全局变量只能用于检索数据,这意味着永远不应该直接向这些变量写入数据。覆盖全局变量值可能导致异常,因为核心和扩展功能的重要部分依赖于这些值在一个上下文中设置,并在这些设置在查询、页面加载或单post处理期间需要保持一致。给全局变量赋值几乎总是会产生意想不到的副作用,而且它们几乎总是不是用户或博客作者想要的。这里讨论全局变量是为了进一步说明如何操作post数据,你可能会看到一些代码片段利用这些函数在循环之外进行post处理。

Post数据

你已经看到了循环中的第一步是如何调用the_post()的。一旦调用,你将可以访问WordPress中显示的所有数据。此数据存储在全局$post变量中。$post变量存储页面上显示的最后一篇文章的发布数据。因此,如果你的循环显示10篇文章,$post变量将存储显示的第10篇文章的文章数据。下面的例子展示了如何使用print_r() PHP函数引用$post全局变量并显示数组中的所有值。

<?php
global $post;
print_r( $post ); //view all data stored in the $post array
?>

上面的代码将打印$post全局变量的数组值。默认的WordPress博客中值是这样的:

WP_Post Object
(
	[ID] => 1
	[post_author] => 1
	[post_date] => 2015-06-09 19:05:19
	[post_date_gmt] => 2015-06-09 17:23:50
	[post_content] => Welcome to WordPress. This is your first post.
		Edit or delete it, then start blogging!
	[post_title] => Hello world!
	[post_excerpt] =>
	[post_status] => publish
	[comment_status] => open
	[ping_status] => open
	[post_password] =>
	[post_name] => hello-world
	[to_ping] =>
	[pinged] =>
	[post_modified] => 2015-06-09 19:04:12
	[post_modified_gmt] => 2015-06-09 19:04:12
	[post_content_filtered] =>
	[post_parent] => 0
	[guid] => http://localhost/Brad/?p=1
	[menu_order] => 0
	[post_type] => post
	[post_mime_type] =>
	[comment_count] => 1
	[filter] => raw
)

正如你所看到的,$post全局变量包含了post的所有数据。你也可以从数组中显示特定的数据片段,比如帖子的标题和内容,如下所示:

<?php
global $post;
echo $post->post_title; //display the post title
echo $post->post_content; //display the post content
?>

通过全局$post变量访问内容意味着你正在访问未过滤的内容。这意味着任何通常会改变内容输出的插件都不会影响全局内容值。例如,如果你在你的帖子中有内置的gallery(外面带上中括号),短代码来显示所有上传的图片,检索显示的帖子内容将返回gallery而不是实际的图片库。

记住,WordPress提供了可以在任何地方调用的模板标记来检索这些值,并且在大多数情况下,模板标记将是获取这些位的首选机制。
例如,如果你需要获得你的帖子的永久链接,你可以使用以下方法:

<?php
global $post;
echo get_permalink( $post->ID ); //displays the posts permalink
?>

这将在本章后面的“在循环之外的工作”一节中详细介绍。

作者数据

$authordata是一个全局变量,用于存储所显示文章的作者信息。你可以使用这个全局变量来显示作者的名字:

<?php
global $authordata;
echo 'Author: ' .$authordata->display_name;
?>

$authordata变量是在循环中的_post()函数被调用期间调用setup_postdata()时创建的。这意味着$authordata全局变量在循环第一次运行之前不会被创建。这种方法的另一个问题是,全局值没有通过回调过滤器传递,这意味着你安装的任何插件都不会运行这个功能。访问作者元数据(就像获取post数据一样)的首选方法是使用可用的WordPress模板标签。例如,要显示作者的显示名,可以使用以下代码:

<?php
echo 'Author: ' .get_the_author_meta( 'display_name' );
?>

get_the_author_meta()和the_author_meta()函数可用于检索与内容作者相关的所有元数据。如果在循环中使用了这个模板标记,则不需要传递用户ID参数。如果在循环外部使用,则需要用户ID来确定要检索的作者元数据。

用户数据:

全局变量$current _user存储当前登录用户的信息。这是你当前登录WordPress时使用的帐户。以下是如何显示已登录的用户显示名的示例:

<?php
global $current_user;
echo $current_user->display_name;
?>

如果希望向用户显示欢迎消息,那么这是一种有用的技术。请记住,显示名将默认为用户的用户名。要向任何登录的用户显示欢迎消息,可以使用以下代码:

<?php
global $current_user;
if ( $current_user->display_name ) {
echo 'Welcome ' .$current_user->display_name;
}
?>

环境数据

WordPress还为浏览器检测创建了全局变量。下面的例子展示了如何使用全局变量检测用户的浏览器版本:

当需要设计一个包含浏览器特定任务或功能的网站时,这是非常有用的。最好坚持web标准,但为屏幕较小的浏览器优化,在某些情况下,这可能是非常有益的。例如可以使用$is_iphone变量为iPhone web用户加载自定义样式表。

<?php
global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4,
$is_safari, $is_chrome, $is_iphone;
if ( $is_lynx ) {
	echo "You are using Lynx";
}elseif ( $is_gecko ) {
	echo "You are using Firefox";
}elseif ( $is_IE ) {
	echo "You are using Internet Explorer";
}elseif ( $is_opera ) {
	echo "You are using Opera";
}elseif ( $is_NS4 ) {
	echo "You are using Netscape";
}elseif ( $is_safari ) {
	echo "You are using Safari";
}elseif ( $is_chrome ) {
	echo "You are using Chrome";
}elseif ( $is_iphone ) {
	echo "You are using an iPhone";
}
?>

WordPress提供了另一个全局变量来检测用户是否在移动设备上,可能是智能手机或平板电脑。这个全局变量叫做$is_mobile。除了直接调用这个全局变量,还有一个方便的函数wp_is_ mobile()。检测用户是否在移动设备上。如果在使用移动设备浏览,该函数返回true;如果不是,函数返回false,如下所示:

if ( wp_is_mobile() ) {
	echo "You are viewing this website on a mobile device";
}else{
	echo "You are not on a mobile device";
}


WordPress还使用$is_IIS和$is_apache全局变量来存储网站托管的web服务器类型。这里有一个例子:

<?php
global $is_apache, $is_IIS;
if ( $is_apache ) {
	echo "web server is running Apache";
}elseif ( $is_IIS ) {
	echo "web server is running IIS";
}
?>


根据网站使用的服务器不同,代码产生的结果可能会不同于预期。作为开发者,你需要考虑你的插件和主题可能运行在不同的服务器上;为了完成特定的任务,你可能还需要检查用户正在运行什么。

全局变量还是模板标签?

一般来说,只要有可能,就应该使用模板标签。在某些情况下,模板标签是不可用的。在这种情况下,可以替换全局变量来访问所需的信息。此外,全局变量非常适合检索未过滤的数据,这意味着这些值将绕过任何插件,改变通常用于内容的内容,并提供原始值。一旦你的代码访问或处理了原始值,你仍然可以使用以下代码强制过滤器运行:



虽然这被包含在“关于在循环之外工作”的讨论中,你可以在循环内部访问这些全局变量,但是再次记住要将全局变量视为只读的,因为改变它们的值可能会有负面影响。

<?php apply_filters( 'the_content', $post->post_content );?>

在循环之外工作


有时候希望访问一般的文章信息,或者在循环外部操作有关当前显示的文章的一些信息。WordPress提供了一些功能来操作一组文章,以便更细粒度地控制文章显示。

除了对全局变量的访问之外,还有一组WordPress函数可以返回非特定于单个文章或当前显示的文章的通用信息。以下是在循环之外工作时经常使用的函数列表:
➤wp_list_pages() -将页面列表显示为链接
➤wp_list_categories() -将一个类别列表显示为链接
➤wp_tag_cloud() -显示所有标记的标记云
➤get_permalink() -返回帖子的永久链接
➤next_posts_link() -显示以前的帖子链接
➤previous_posts_link() -显示下一篇文章链接

在自定义Loop示例中,你已经看到了如何使用next_posts_link()和previous_posts_link()创建导航链接。现在探索其中的一些函数来真正了解它们是如何工作的。要在WordPress中显示页面列表,可以使用wp_list_pages()函数。这个函数将以列表格式返回页面,所以用 <ul>标记包装函数调用很重要,如下所示:

<ul>
	<?php wp_list_pages( 'title_li=' ); ?>
</ul>

上面的代码将从WordPress中生成一个带有链接的页面列表。注意,将参数title_li设置为nothing,这消除了页面显示的默认标题。这个函数会像这样生成你的菜单列表:

<ul>
<li class="page_item page-item-1">
<a href="http://example.com/about/" title="About">About</a>
</li>
<li class="page_item page-item-2">
<a href="http://example.com/order/" title="Order">Order</a>
</li>
<li class="page_item page-item-3">
<a href="http://example.com/contact/" title="Contact">Contact</a>
</li>
</ul>

你也可以使用wp_page_menu()函数来生成页面菜单。这个页面列表函数有几个优点。第一个参数是一个新的show_home参数,它允许Home链接自动添加到页面列表中。你也不必像前面的代码中那样使用title_li删除标题。这个函数还在菜单周围做了封装,你可以设置它。以下是该函数的示例:

<?php wp_page_menu( 'show_home=1&menu_class=my-menu&sort_column=menu_order'); ?>

生成链接的另一个常用函数是wp_list_categories()。这个函数还在一个列表中列出了类别和子类别。考虑以下例子:

<ul>
	<?php wp_list_categories(
		'title_li=&depth=4&orderby=name&exclude=8,16,34' ); ?>
</ul>

这段代码将生成一个带有链接的类别列表。与之前一样标题设置为空,而不是默认的Categories标题。还可以将深度设置为4。深度参数控制列表中要包含的类别层次结构中的级别。类别将按名称排序。还根据ID排除了三个类别(8、16和34)。

next_posts_link()和previous_posts_link()函数通常在循环完成后直接使用。这两个功能将生成前一个和下一个链接,以查看网站上的更多帖子。注意,next_posts_link()函数实际上返回你以前的文章。这样做的原因是WordPress假定你的帖子是按时间倒序显示的,这意味着帖子的下一页实际上是时间轴上更早的帖子。

现在假设你想在循环之外加载一篇文章。为此可以使用get _ post()函数来加载post数据。以下示例加载ID为1031的post数据:

<?php
$my_id = 1031;
$myPost = get_post( $my_id );
echo 'Post Title: ' .$myPost->post_title .'<br />';
echo 'Post Content: ' .$myPost->post_content .'<br />';
?>

get_post()函数只有一个必需的参数:要加载的post ID。你必须传递一个包含ID整数的变量。传递一个文本整数(例如,5)将导致致命错误。第二个可选参数是希望结果如何返回:作为对象、关联数组或数字数组。默认情况下,返回一个对象。要返回一个关联数组,可以运行以下代码:

<?php
$my_id = 1031;
$myPost = get_post( $my_id, ARRAY_A );
echo 'Post Title: ' .$myPost['post_title'] .'<br />';
echo 'Post Content: ' .$myPost[‘post_content'] .'<br />';
?>

但是,无论如何返回结果,get_post()调用都会返回WordPress数据库中的原始内容。通常在循环中完成的筛选和处理不会应用于返回的内容。解决方案是使用setup_ postdata()函数和get _ post()来设置全局post数据和模板标签,然后应用于你的post:

<?php
$my_id = 1031;
$myPost=get_post( $my_id );
setup_postdata( $myPost );
the_title();
the_content();
?>

函数使用内部的WordPress对象缓存。这意味着如果你正在加载的帖子已经在缓存中,这将避免运行一个不必要的数据库查询。很容易看出这个函数对于快速有效地在循环外加载一篇文章是多么有用。一些可以在循环内部使用的函数也可以在循环外部使用。例如,你可以使用the_author_meta()函数来检索特定的作者元数据:

The email address for user id 1 is <?php the_author_meta( 'user_email', 1); ?>

请记住在循环外部调用the_author_meta()函数时,必须指定要为其加载元数据的作者ID。如果你在循环内部调用这个函数,你不需要指定这个ID,因为它将加载当前文章的作者数据。WordPress还提供了一些特定的函数,用于检索循环之外的文章的个人数据。例如,你可以使用get _the_title()函数根据文章的ID检索文章的标题,如下所示:

<?php
	echo 'Title: ' .get_the_title( 1031 );
?>

还可以使用函数从单个文章中检索文章元数据(自定义字段)。要做到这一点,你可以使用get_post_meta()函数,如下所示:

<?php
	echo 'Color: ' .get_post_meta( 1031, 'color', true );
?>

get_post_meta()函数接受三个参数:post ID、key和single。帖子ID是你想要加载元数据的帖子的ID。key是你想加载的元值的名称。第三个可选值确定结果是作为数组返回,还是函数将返回单个结果。默认情况下,这个值被设置为false,这样就会返回一个数组。如你所见,可以将该值设置为true,以便只返回单一颜色的帖子。

章节小结


本章涵盖了WordPress内容选择和显示的基本机制,并提供了WordPress core的指导,以帮助找到用于实现这些功能的代码。WordPress的真正强大之处在于它插件和主题的可扩展性。在第6章中,将更详细地了解WordPress数据模型,它将向你展示保存的所有内容、用户和元数据之间的各种数据项是如何相互关联的。第7章将介绍自定义文章类型、自定义分类法和元数据,并向展示可以在WordPress中定义和使用的各种类型的内容。然后你将在第8章中使用它作为一个完整的插件结构讨论的基础。除了插件,主题是扩展和定制WordPress的另一种主要方式,在第9章中,你可以通过更深入地了解模板和内容,并重新应用一些Loop构造新表示效果。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈小房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>