【问题标题】:Get the_excerpt of a child page from within a parent page从父页面中获取子页面的摘录
【发布时间】:2016-11-17 14:40:48
【问题描述】:

无法从父页面中获取子页面的摘录。我有一个静态父页面,其中列出了属于该父级的所有子页面的摘录。

出于某种原因,我可以返回每个子页面的每个标题和发布日期。但是,当我尝试回显 get_the_excerpt 或 the_excerpt 时,我得到的只是列出的每个子页面的父页面的摘录或内容。我还将标准摘录转换为自定义修剪摘录。这适用于“首页”,但不适用于标准的“父页面”。

不确定我做错了什么或忽略了什么。

这是出现的内容...注意:“父页面内容”重复。

父页面标题

父页面内容

测试子页面标题 A

父页面内容

2016 年 11 月 16 日

测试子页面标题 B

父页面内容

2016 年 10 月 5 日

使用此解决方案:

<?php
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

// Begin listing all child pages
$childpages = get_pages( array( 'child_of' => $post->ID, 'sort_column' => 'post_date', 'sort_order' => 'desc' ) ); 
 foreach( $childpages as $childpage ) { ?>
  <div class="paged-entries">
    <div class="entry">
      <h3 class="page-headline"><?php echo $childpage->post_title; ?></h3>
        <!-- .entry-summary -->
        <div class="post-excerpt">
            <?php
                    $content = get_extended( $childpage->post_content );
                    $page_excerpt = wpse0002_custom_wp_trim_excerpt($content);
                    //echo wpse0002_custom_wp_trim_excerpt($content); // echoes the word "Array" only.
                    //echo $page_excerpt = wpse0002_custom_wp_trim_excerpt($content); // echoes the word "Array" only.
                    //echo $content['main']; // prints the full child post expected.
                    //print_r ($page_excerpt); // prints full post with some php wrapping: Array ( [main] => This is some fresh music. [extended] => [more_text] => )
                    print_r( $childpage->post_content ); // prints the full child post expected.
            ?>
        </div>
        <!-- end .entry-summary -->
        <h6>Published: <?php echo date("M Y", strtotime($pfx_date = get_the_date( $format, $childpage->ID ))); // d m y ?></h6>
    </div>
  </div>
</article>
<?php
}
?>

这就是我所追求的:

父页面标题

父页面内容

测试子页面标题 A

子页面摘录A

2016 年 11 月 16 日

测试子页面标题 B

子页面摘录B

2016 年 10 月 5 日

这是我的自定义修剪器

// 自定义摘录

remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse_custom_wp_trim_excerpt');
$wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags());
function wpse_allowedtags() {
    return '<video>,<audio>,<embed>,<iframe>,<figure>,<figcaption>'; 
}

if ( ! function_exists( 'wpse0002_custom_wp_trim_excerpt' ) ) : 

function wpse0002_custom_wp_trim_excerpt($wpse0002_excerpt) {
    global $post;
    $raw_excerpt = $wpse0002_excerpt;
    if ( '' == $wpse0002_excerpt ) {

        $wpse0002_excerpt = get_the_content('');
        $wpse0002_excerpt = strip_shortcodes( $wpse0002_excerpt );
        $wpse0002_excerpt = apply_filters('the_content', $wpse0002_excerpt);
        $wpse0002_excerpt = substr( $wpse0002_excerpt, 0, strpos( $wpse0002_excerpt, '</p>' ) + 4 );
        $wpse0002_excerpt = str_replace(']]>', ']]&gt;', $wpse0002_excerpt);
        $wpse0002_excerpt = strip_tags($wpse0002_excerpt, wpse_allowedtags()); /*IF you need to allow just certain tags. Delete if all tags are allowed */

        return $wpse0002_excerpt;

    }
    return apply_filters('wpse0002_custom_wp_trim_excerpt', $wpse0002_excerpt, $raw_excerpt);
}

endif;

remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse0002_custom_wp_trim_excerpt');

【问题讨论】:

  • 避免使用$page,因为它是一个引用当前(即父)页面的全局变量:请改用不同的变量名。这可能会解决您的问题。
  • @Dre 这是一个值得注意的更新。我将更新上面的代码。然而,这并没有解决问题,我仍然得到整个帖子内容。使用@Stanimir Stoyanov 建议查看我在上面添加的内容。
  • 您确定echo get_the_excerpt($childpage-&gt;ID) 不起作用吗?另外,您是如何创建自定义修剪摘录的?
  • @Dre 是的。这只是打印我正在显示子页面的实际父页面的摘录。见上文,因为我也添加了自定义修剪并更新了上面的代码。
  • 啊,那个视觉确实澄清了一些事情!我现在明白你试图用你的过滤器做什么了。这在一定程度上改变了我的回答;我会在一段时间内更新它以反映这一点。所以,如果我理解这一点:您希望您的摘录获取第一个 YouTube 嵌入、音频标签和然后第一段?

标签: php wordpress parent-child


【解决方案1】:

冒着听起来傲慢的风险,我将过度解释一切,以便其他人可能会发现这很有用。经历了这一切之后,我对你想要实现的目标有了一个很好的了解:有不止一种方法可以实现它,所以不仅仅是给你一大块代码,我要走通过这一切背后的逻辑,以便您可以选择适用的位。

调试

首先,您到处都有一堆 PHP 错误,这会导致一些不可预知的行为,这表明您没有打开调试。将以下内容添加到wp-config.php

// Enable WP_DEBUG mode
define( 'WP_DEBUG', true );

这将显示警告并帮助您跟踪错误出现的位置。一个值得注意的错误是您在没有传递参数的情况下调用wpse0001_custom_wp_trim_excerpt()

摘录

默认情况下,页面(与帖子不同)没有单独的摘录字段,这就是为什么您一直使用get_extended() 来提取more 标记之前的内容。但是,您可以通过将以下内容添加到 functions.php 来将摘录字段添加到页面。我建议这样做,因为它使所有后续与摘录相关的行为变得更容易。这也意味着 WP 应该自动处理没有摘录的页面的后备;没有意义重新发明轮子。

/**
 * Adds excerpt field to pages
 * @args void
 * @returns void
 */
function my_add_excerpts_to_pages() {
     add_post_type_support( 'page', 'excerpt' );
}
add_action( 'init', 'my_add_excerpts_to_pages' );

在管理区域中,您可能需要检查 屏幕选项 下的 摘录 选项以显示该字段。这使您可以使用 WP 的默认功能和过滤器来显示和操作摘录。它还填充了 $post-&gt;post_excerpt 键,因此如果您需要在不过滤的情况下输出它,您可以使用:echo $post-&gt;post_excerpt

另一个带有摘录的“陷阱”是get_the_excerpt() 必须在循环中使用;您不能将帖子的 ID 传递给它。我很确定你曾经能够做到这一点,但它已经被弃用了:我认为在线文档需要更新,所以我会尝试在那里记录一个更改,以免将来其他人感到困惑.这就是生活。这就引出了我们的下一个主题......

二级循环

您正在使用get_pages() 获取子页面,这很好,但是由于摘录的工作方式,您不得不使用自己的函数来获取和过滤它们。另一种方法是使用WP_Query 而不是get_pages()。因为它是支持get_pages() 的类,它为您提供了一些额外的控制。在这种情况下,我们感兴趣的是它会覆盖全局 $post 变量,这允许 the_excerpt()get_the_excerpt() 正常工作。以下是创建辅助循环以获取正确子页面的方法:

$child_args = array( 
    'post_parent' => $post->ID,     // This assumes you're calling this on the parent music page
    'sort_column' => 'post_date',
    'sort_order' => 'desc',
    'ignore_sticky_posts' => true,  // Don't display any sticky posts
    'post_type' => 'page'           // Only fetch pages, not posts
); 
$child_query = new WP_Query( $child_args );

// Usual Loop logic
if ( $child_query->have_posts() ) : while ( $child_query->have_posts() ) : $child_query->the_post();

    // You can pretty much do whatever you want in here...
    the_title();    // Should output the child page title
    the_excerpt();  // Should output the child page excerpt
    $excerpt = get_the_excerpt(); // Assigns the excerpt to a variable in case you want to do other things to it.


    endwhile; else: 

    // 'No posts' content would go here

endif;

wp_reset_postdata(); // This is important; it sets $post back to the parent page. Always reset it after a loop.

您可能希望将其放入 page-music.php,但我个人的偏好是将其放入模板部分,然后使用 get_template_part() 调用它,这样您就可以轻松地在其他地方重用它页。例如,您应该能够使用它作为特色设计页面,而无需进行任何更改。

另外,请注意wp_reset_postdata() 的使用:您需要在循环结束时执行此操作,因为它将$post 重置回原始页面。您还想在 front-page.php 上执行此操作,就在您循环播放音乐页面之后(第 81 行)。

有关WP_Query的更多信息,您可以查看this SO answer

过滤

现在,如果您使用如上所述的辅助循环,则可以依赖 $post 的存在。这使您可以根据标签、父页面等对摘录应用条件过滤。为了避免必须根据页面父页面创建不同的输出函数——就像你目前正在做的那样——你可以改为应用过滤函数,通过将此添加到functions.php:

/**
 * Custom function for when we need to filter the excerpt differently for particular pages
 * Needs to be used within the loop
 * @args $excerpt(string)       - The incoming excerpt to filter
 * @args $post(obj)             - The post that the excerpt comes from (WP 4.5+)
 * @returns $excerpt(string)    - The filtered excerpt
 */
if ( !function_exists('custom_excerpt_filter')) {
    function custom_excerpt_filter($excerpt='', $post=null) {

        // Fallback for WP 4.4 and below, which don't pass $post
        if (!$post) {
            global $post;
        }

        // Get the unfiltered excerpt if you really want it:
        // if ( !empty($post->post_excerpt) ) {
        //  $excerpt = $post->post_excerpt; // Use an excerpt if there is one.
        // } else {
        //  $excerpt = get_extended($post->post_content)['main']; // Use the content before
        //}


        // Now you can do whatever string manipulations you want with $excerpt here

        // Filtering based on tags...
        if ( has_tag('featured-music',$post) ) {
            // Could apply additional filtering for music page excerpts here
        }

        // Or filtering based on the parent page...
        $parent = get_page_by_path('featured-music'); // Get parent post via the slug
        if ( $post->post_parent == $parent->ID ) {
            // Additional filtering for music child pages here...
        }

        return apply_filters('the_excerpt', $excerpt, $post); // Apply other filters so they can be chained
    }
}
add_filter('get_the_excerpt','custom_excerpt_filter', 10, 2);

我省略了$excerpt 上的实际字符串操作,因为你可以用它做几乎任何你喜欢的事情。

现在,当您在循环中使用 the_excerpt() 时,您的过滤器可以考虑相关摘录的页面标签/父级,并根据需要进行修改。这样一来,您的逻辑将全部保存在一个位置,并在所有模板中一致应用。

在摘录中插入媒体

由于您想在摘录中插入视频和音频,因此在管理员中使用摘录字段时会遇到问题:它不允许您插入任何 HTML 标记。不用担心,您仍然可以将其插入内容中,并通过我们的过滤器进行提取。我们可以使用get_media_embedded_in_content()从页面内容中提取出来,然后插入到摘录中:

/**
 * Custom function for when we need to filter the excerpt differently for particular pages
 * Needs to be used within the loop
 * @args $excerpt(string)       - The incoming excerpt to filter
 * @args $post(obj)             - The post that the excerpt comes from.
 * @returns $excerpt(string)    - The filtered excerpt
 */
if ( !function_exists('custom_excerpt_filter')) {
    function custom_excerpt_filter($excerpt='', $post=null) {


        // Fallback for WP 4.4 and below, which didn't pass $post
        // Assumes you're calling this in the loop
        if (!$post) {
            global $post;
        }

        // Get the unfiltered excerpt if you really want it:
        // if ( !empty($post->post_excerpt) ) {
        //  $excerpt = $post->post_excerpt; // Use an excerpt if there is one.
        // } else {
        //  $excerpt = get_extended($post->post_content)['main']; // Use the content before
        //}


        // Now you can do whatever string manipulations you want with $excerpt here

        // Filtering based on tags...
        if ( has_tag('featured-music',$post) ) {
            // Could apply additional filtering for music page excerpts here
            $excerpt .= ' has featured music tag';
        }

        // Filtering based on parent...
        $parent = get_page_by_path('featured-music'); // Get parent post via the slug

        if ( $post->post_parent == $parent->ID ) {

            $excerpt = ''; // We ignore the current excerpt as we're making our own

            // First we grab all the content
            $content = apply_filters( 'the_content',  $post->post_content); // Apply content filters so shortcodes get applied

            // Get the audio
            $audio = get_media_embedded_in_content($content, array('audio')); // Returns an array
            if (!empty($audio)) { 
                $audio = $audio[0]; // Since we want the first audio embed, grab the first element in the array
                $excerpt .= $audio; // Add the audio to the excerpt
            } 

            // Get the video
            $video = get_media_embedded_in_content($content, array('video', 'iframe'));
            if (!empty($video)) {
                $video = $video[0];
                $excerpt .= $video; // Add the video to the excerpt
            }

            // Now to get the first paragraph
            // There's a bunch of ways you can do this; you just need to bear in mind that there's media in the content that you'll need to work around
            // Here's one possible way:

            // First, strip out all media...
            $content = preg_replace("/<img[^>]+\>/i", "", $content);
            $content = preg_replace("/<iframe[^>]+\>/i", "", $content);
            $content = preg_replace("/<audio[^>]+\>/i", "", $content);

            // ...here we're relying on the fact that Wp doggedly wraps everything in <p> tags 
            // Explode the content into an array
            $content = explode('</p>', $content);

            $excerpt .= $content[0];
        }

        return apply_filters('the_excerpt', $excerpt, $post); // Apply other filters so they can be chained
    }
}
add_filter('get_the_excerpt','custom_excerpt_filter', 10, 2);

获取第一段

你最不想结束的事情就是抓住第一段。有很多不同的方法可以做到这一点;上述功能包括一种方法。您还可以:

  1. 使用get_extended() 抓取more 标签之前的内容,然后使用wp_strip_all_tags() 去除所有媒体。
  2. 使用单独的摘录字段。

结论

通过在过滤函数中使用WP_query 和一些逻辑,您可以简化很多模板,进而帮助您让一切正常工作。希望对您有所帮助!

【讨论】:

  • 这非常有帮助。我会花一些时间来解决这个问题。你能抽出时间来开悟,真是太好了。仅供参考...我发送记住的文件只是部分的,因为我只保留了相关的部分,以免进行筛选。我打开了调试;)...但是,其余的非常有帮助。我一定会告诉你发生了什么。
  • 既然我了解了您试图对摘录做什么,我将对其进行更新以添加有关包含视频和音频嵌入的部分。以上仍然有效:您只需要在最后调整过滤器位。在您等待时,您可能想查看get_media_embedded_in_content() - 它需要一个字符串(即您的帖子内容)并仅返回嵌入内容。使用现有函数通常比尝试提出自己的正则表达式要容易得多。
  • @JonnyBorg 更新了上述答案,为您提供了一种将视频和音频拉入摘录的方法。
  • 非常有帮助。这终于奏效了。非常有见地和有用的信息。我希望这对其他人有帮助。完成后我会分享我的更新。再次感谢!此外,您对需要更新摘录的 Wordpress 文档的评论是非常正确的。这有点令人困惑。
【解决方案2】:

您应该使用get_extended 来获取更多标签之前的文本,insead get_excerpt。如果我没记错,get_the_excerpt 返回摘录字段的内容,而get_extended() 返回更多标签之前的内容。所以你的代码会变成:

$content = get_extended( $page->post_content );
echo $content['main'];

【讨论】:

  • 这只是返回了单词“Array”。另外,如果我这样做$page-&gt;ID,它会字面上显示每个唯一的子页面数字,如 111 或 219 等......所以如果我这样说:echo the_excerpt( $page-&gt;ID);
  • 我的错误。此函数返回一个内容元素数组。我已经更新了我的答案,所以请使用新代码。
  • 好的,可以。竖起大拇指,但是……那是整个帖子,而不是摘录。我有一个自定义修剪的摘录,所以现在我需要将其转换为摘录而不是完整内容。然后我认为我的自定义应该可以正常工作。 echo wpse0001_custom_wp_trim_excerpt();
  • 在这种情况下,$page-&gt;post_content 有效,但 post_excerpt 无效。我原以为这会像它的内容一样提取它的摘录。 $content = get_extended( $page-&gt;post_excerpt ); echo $content['main'];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 2014-10-24
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
相关资源
最近更新 更多