从 Wordpress post 获取嵌入内容和链接的函数(从 1 到所有)

Function to get the embedded content and links from a Wordpress post (from 1 to all of them)

我正在制作将与 Wordpress 一起使用的自定义设计(不是主题)。 我创建了一个函数来获取 post 中的一个、多个或所有嵌入项。 它适用于 <img><audio><video><iframe><a> 标签,但可以轻松编辑它以获取任何 html 标签。 我循环使用它:

if (have_posts()) : while (have_posts()) : the_post();

我针对所有标签和不同数量的项目对其进行了简单的测试,它可以在除 iframe 之外的所有项目上正常工作。您可以获得所有其他标签。 该函数获取 src 属性,然后根据需要重新创建整个元素,并在需要时使用其他属性。 我将 post 整个功能放在下面,它有点长。

所以我想获取 iframe 源。 我尝试了很多不同的 preg_match 方法来获取它,但没有成功。 奇怪的是,它与 'video' 一起工作,无论是先写还是在 if 部分...但没有 iframe。

由于 我既不是 wordpress 也不是 php 开发人员,任何其他评论 - 无论是安全问题还是我做错了什么 - 我会非常感谢被告知。 我也想知道我是否正确使用 ob_start();如果同时有很多访问者,它是否有助于使服务器更轻松地使用此功能... 另外,如果有更好的方法来为函数创建参数...

我稍后会为每个单独的项目添加一个包装器,这非常有用(例如从 posts 链接创建一个菜单),我希望有人会发现它有用,尤其是当那些 iframe得到修复。

这是函数:

// $universal_modifier for img size ('thumbnail') or link target '_blank'
// example: get_the_customized_post_content('link', 'all', 'link-class', '_blank');
// example: get_the_customized_post_content('image', 1, 'image-class', 'custom-thumbnail');

function get_the_customized_post_content($item_type = null, $items_num = null, $item_classes = null, $universal_modifier = null)
{
    // PHP automatically flushes open output buffers when it reaches the end of a script
    ob_start();
    global $post;
    $single_img = false;

    if ($items_num) {
        if ($item_type === 'image') {
            if ($items_num === 1 && $universal_modifier) {
                $single_img = true;
                // this will get the featured image, which allows for getting
                // the 'full' img with its sourceset
                the_post_thumbnail($universal_modifier, array(
                    'class' => esc_attr($item_classes),
                    'alt' => esc_html(get_the_title())
                ));
            } else {
                preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $item_src);
                $additional_attr = '';
                $the_html_tag = '<img';
                $close_tag = '';
            }
        } elseif ($item_type === 'audio') {
            preg_match_all('/<audio.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->content, $item_src);
            $additional_attr = 'preload=none loading=lazy controls';
            $the_html_tag = '<audio';
            $close_tag = '</audio>';
        } elseif ($item_type === 'video') {
            preg_match_all('/<iframe.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $item_src);
            $additional_attr = 'loading=lazy frameborder=0 allowfullscreen';
            $the_html_tag = '<iframe';
            $close_tag = '</iframe>';
            if (count($item_src[1]) === 0) {
                echo 'Getting videos';
                preg_match_all('/<video.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $item_src);
                $additional_attr = 'preload=metadata loading=lazy controls';
                $the_html_tag = '<video';
                $close_tag = '</video>';
            }
        } elseif ($item_type === 'link') {
            preg_match_all('/<a.+href=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $item_src);
            preg_match_all('/<a.+>([^\'"]+)<\/a>/i', $post->post_content, $anchor_text);
            if ($universal_modifier) {
                $additional_attr = 'target=' . $universal_modifier;
            } else {
                $additional_attr = '';
            }
            $the_html_tag = '<a';
            $close_tag = '</a>';
        } else {
            echo '<p class="' . esc_attr('not-found-info') . '">' . esc_html('Media not found...') . '</p>';
        }
    }


    if ($single_img) {
        $display_item = ob_get_clean();
        echo $display_item;
    } else {
        if (count($item_src[1]) === 0) {
            echo '<p class="' . esc_attr('not-found-info') . '">' . esc_html('Media not found...') . '</p>';
        } else {
            $num_of_items = count($item_src[0]);
            if ($items_num === 'all') {
                $items_total = $num_of_items;
            } else {
                $items_total = min($num_of_items, $items_num);
                // get the smaller number of the two
            }

            if ($items_total > 0) {
                for ($i = 0; $i < $items_total; $i++) {

                    if ($item_type === 'link') {
                        $source_type = 'href';
                        $item_content = $anchor_text;
                    } else {
                        $source_type = 'src';
                        $item_content = '';
                    }

                    $the_item = $the_html_tag . ' class="' . esc_attr($item_classes) . '" ' . $source_type . '="' . esc_url($item_src[1][$i]) . '" ' . esc_attr($additional_attr) . '>' . $item_content[1][$i] . $close_tag;
                    echo $the_item;
                };
            };
        };
    }
}

我不得不更改功能,我认为现在好多了。它可以完全工作并且易于使用。函数有点长…

我用了var_dump($post->post_content),发现post内容里没有iframe。它们仅在页面的输出中得到回显。

因此我使用 get_media_embedded_in_content() 和适当的媒体类型来获取所需的内容,然后 preg_match() 来获取所需的内容。

当每个 post 只需要一张图像时,该函数获取 post 的缩略图 'full'(post 必须有特色图像 – 有一个用于自动创建的插件),它 return 将图像与源集联系起来,使其具有响应能力。对于每个 post 的更多图像,它 return 是完整图像大小。

如果需要,我为每个单独的项目添加了一个包装器。可以向其中添加 类。 它对于将图像包装在 <a> 标签中很有用——它会自动生成 href。 它对于用 <li> 标签包装 links 也很有用,以便从 posts links 制作菜单(个人而言,在这种情况下,这对我来说是最重要的事情之一). 如果设置 link 目标,它将用于所有 links – links 作为项目或 links 作为包装。

只有图片可以正确包裹在<a>标签中,其他的会被包裹但没有href。 如果 $item_type 设置为 'video',它将同时找到 <video><iframe> 标签。它将首先搜索 <iframe>,因为与自托管视频相比,每个人最有可能 post 来自外部来源的视频。

<video><audio> 将有控件。 <video> 将有 preload="metadata"<audio> preload="none"<iframe> 将有 frameborder="0" allowfullscreen。 除了 link 之外的所有内容都将具有 loading="lazy"。 我不确定它是否适用于所有使用 wordpress 的人,但它没有害处......如果没用,可以稍后删除......

据我所知,我转义了所有 html/attribute/url 输出。

该函数在循环内部调用,在类别页面中:

if (have_posts()) : while (have_posts()) : the_post();

    get_the_customized_post_content(
        $item_type = 'image',
        $items_num = 'all',
        $item_classes = 'item-image-class class-two',
        $item_wrap = 'a',
        $item_wrap_classes = 'item-wrap-class one-more-class',
        $the_link_target = '_blank'
    );

    endwhile;
wp_reset_postdata();
endif;

或:

query_posts(array(
    'category_name' => 'your-cat-name',
    'posts_per_page' => 1
));

if (have_posts()) : while (have_posts()) : the_post();

        get_the_customized_post_content(
            $item_type = 'audio',
            $items_num = 1,
            $item_classes = 'item-audio-class',
            $item_wrap = 'div',
            $item_wrap_classes = 'item-wrap-class classs-two',
            $link_target = false
        );

    endwhile;
    wp_reset_postdata();
    wp_reset_query();
endif;

$items_num 可以是 'all' 或从 1 到所需的数量 - 如果指定的项目多于 post 的项目,它将 return 所有项目post 有。

任何不需要的东西,把它设为 false (… $item_wrap = false, …)。 当然有更好的方法来写这个,只写那些需要的论据,而忽略所有错误的,但我不知道该怎么做。

我还是想听听 wordpress/php 开发者的意见,尤其是关于函数的性能,还有关于编码——我相信它可以写得更好……

编辑:

  • 为 link 的创建改进了 preg_match_all。
  • 添加了多个图片 alt 标签。

您还必须删除:

  • 特色图片width/height 内联属性
  • 特色图片 Wordpress 默认 类
// remove Featured Image width/height inline attributes
function remove_img_size_attr($html)
{
    $html = preg_replace('/(width|height)="\d+"\s/', "", $html);
    return $html;
}
add_filter('post_thumbnail_html', 'remove_img_size_attr', 10);
add_filter('image_send_to_editor', 'remove_img_size_attr', 10);

// remove Featured Image classes
remove_action('begin_fetch_post_thumbnail_html', '_wp_post_thumbnail_class_filter_add');

都在functions.php

OK,函数(放在functions.php中):

function get_the_customized_post_content(
    $item_type = null,
    $items_num = null,
    $item_classes = null,
    $item_wrap = null,
    $item_wrap_classes = null,
    $link_target = null
) {
    // PHP automatically flushes open output buffers when it reaches the end of a script
    ob_start();
    global $post;
    $not_found_class = 'media-not-found'; // class for the p tag container for "Nothing found" info

    if ($item_type && $items_num) {
        if ($item_type === 'video') {
            $the_item_media = get_media_embedded_in_content(apply_filters('the_content', get_the_content(), -1), array('video', 'iframe'));
            $num_of_items = count($the_item_media);
        } elseif ($item_type === 'audio') {
            $the_item_media = get_media_embedded_in_content(apply_filters('the_content', get_the_content(), -1), array('audio'));
            $num_of_items = count($the_item_media);
        } elseif ($item_type === 'image') {
            if ($items_num === 1) {
                // this will get the featured image, which allows for getting
                // the 'full' img with its sourceset
                // it's buffered, otherwise it echos automatically
                the_post_thumbnail('full', array(
                    'class' => esc_attr($item_classes),
                    'alt' => esc_attr(get_the_title())
                ));
                $featured_img = ob_get_clean();
                $the_item_url = get_the_post_thumbnail_url(get_the_ID(), 'full');
                $num_of_items = 1;
            } else {
                preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $item_src);
                $the_item_media = $item_src[1];
                $the_item_url = $item_src[1];
                $the_title_attr = $item_src[1];
                $num_of_items = count($the_item_media);
            };
        } elseif ($item_type === 'link') {
            preg_match_all('/<a.+href=[\'"]([^\'"]+)[\'"].*>([^\'"]+)<\/a>/i', $post->post_content, $link_parts);
            $num_of_items = count($link_parts[0]);
        } else {
            echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Please enter the item type.') . '</p>';
        };
    } else {
        echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Please enter the item type and the number of items to return...') . '</p>';
    };

    if ($num_of_items > 0) {

        if ($link_target) {
            $link_target_window = 'target=' . esc_attr($link_target);
        } else {
            $link_target_window = '';
        };

        if ($items_num === 'all') {
            $items_total = $num_of_items;
        } else {
            $items_total = min($num_of_items, $items_num);
            // get the smaller number of the two
        };

        if ($item_type === 'image') {

            if ($items_num === 1) {
                if ($item_wrap) {
                    if ($item_wrap === 'a') {
                        echo '<a class="' . esc_attr($item_wrap_classes) . '" href="' . esc_url($the_item_url) . '" ' . $link_target_window . '>';
                    } else {
                        echo '<' . $item_wrap . ' class="' . esc_attr($item_wrap_classes) . '">';
                    }
                };

                echo $featured_img;

                if ($item_wrap) {
                    echo '</' . $item_wrap . '>';
                }
            } else {
                for ($i = 0; $i < $items_total; $i++) {
                    if ($item_wrap) {
                        if ($item_wrap === 'a') {
                            echo '<a class="' . esc_attr($item_wrap_classes) . '" href="' . esc_url($the_item_url[$i]) . '" ' . $link_target_window . '>';
                        } else {
                            echo '<' . $item_wrap . ' class="' . esc_attr($item_wrap_classes) . '">';
                        }
                    };

                    $img_src = pathinfo($item_src[1][$i]);
                    $img_alt_tag = $img_src['filename'];

                    $fix_filename = array();
                    $fix_filename[0] = '/-/';
                    $fix_filename[1] = '/_/';
                    $fix_filename[2] = '/\s\s+/';

                    $img_alt_tag = ucwords(preg_replace($fix_filename, ' ', $img_alt_tag));

                    echo '<img class="' . esc_attr($item_classes) . '" alt="' . esc_attr($img_alt_tag) . '" src="' . esc_url($item_src[1][$i]) . '" loading=' . esc_attr('lazy') . '>';

                    if ($item_wrap) {
                        echo '</' . $item_wrap . '>';
                    }
                };
            }
        } elseif ($item_type === 'link') {
            for ($i = 0; $i < $items_total; $i++) {

                if ($item_wrap) {
                    echo '<' . $item_wrap . ' class="' . esc_attr($item_wrap_classes) . '">';
                };

                echo '<a class="' . esc_attr($item_classes) . '" href="' . esc_url($link_parts[1][$i]) . '" ' . esc_attr($link_target_window) . '>' . esc_html($link_parts[2][$i]) . '</a>';

                if ($item_wrap) {
                    echo '</' . $item_wrap . '>';
                };
            };
        } elseif ($item_type === 'video') {
            for ($i = 0; $i < $items_total; $i++) {

                preg_match('/<iframe.+src=[\'"]([^\'"]+)[\'"].*>/i', $the_item_media[$i], $item_src);

                if ($item_wrap) {
                    echo '<' . $item_wrap . ' class="' . esc_attr($item_wrap_classes) . '">';
                };

                if ($item_src[1]) {
                    echo '<iframe class="' . esc_attr($item_classes) . '" loading="lazy" src="' .
                        esc_url($item_src[1]) . '" frameborder="0" allowfullscreen></iframe>';
                } else {
                    preg_match('/<video.+src=[\'"]([^\'"]+)[\'"].*>/i', $the_item_media[$i], $item_src);

                    if ($item_src[1]) {
                        echo '<video class="' . esc_attr($item_classes) . '" loading="lazy" src="' .
                            esc_url($item_src[1]) . '" preload="metadata" controls></video>';
                    } else {
                        echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Media not found.') . '</p>';
                    };
                };

                if ($item_wrap) {
                    echo '</' . $item_wrap . '>';
                };
            };
        } elseif ($item_type === 'audio') {
            for ($i = 0; $i < $items_total; $i++) {

                preg_match('/<audio.+src=[\'"]([^\'"]+)[\'"].*>/i', $the_item_media[$i], $item_src);

                if ($item_wrap) {
                    echo '<' . $item_wrap . ' class="' . esc_attr($item_wrap_classes) . '">';
                };

                if ($item_src[1]) {
                    echo '<audio class="' . esc_attr($item_classes) . '" loading="lazy" src="' .
                        esc_url($item_src[1]) . '" preload="none" controls></audio>';
                } else {
                    echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Media not found.') . '</p>';
                };

                if ($item_wrap) {
                    echo '</' . $item_wrap . '>';
                };
            };
        } else {
            echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Nothing found.') . '</p>';
        };
    } else {
        echo '<p class="' . esc_attr($not_found_class) . '">' . esc_html('Media not found.') . '</p>';
    };
};