将URL转换为附件/帖子ID


32

有什么办法可以获取图像的URL,并在数据库中找到该图像的附件或帖子ID?

情况如下:

我正在循环遍历我的帖子内容中所有被“ a”标签包围的“ img”标签。如果'img'标签的src属性与外部'a'标签的href属性不匹配,那么我想替换'img'标签。在此过程中,如果要删除的“ img”在图库中,则我要删除该帖子,然后将替换的“ img”放在其位置。我尝试使用这样的功能:

function find_image_post_id($url) {
  global $wpdb;
  $postid = $wpdb->get_var($wpdb->prepare("SELECT DISTINCT ID FROM $wpdb->posts WHERE guid='$url'"));
  if ($postid) {
    return $postid;
  }
  return false;
}

这显然是不对的,因为具有讽刺意味的是,guid在全球范围内并不唯一。我曾经(在同一脚本中使用较早版本)上传了一个具有相同名称的文件(为什么?因为它具有更高的分辨率,并且我正试图替换同一图像的低分辨率版本),尽管wordpress会以不同的名称保存该图像在目录中,GUID设置为相同。(可能是一个错误)。

我可以使用另一种技术吗?


您可以根据您的URL设置请求变量,实例化WP_Query并从中获取信息。
hakre 2011年

如果您可以更新问题并发布包含要替换的URL的HTML示例,这将有所帮助,以便我们进行讨论。
MikeSchinkel 2011年

迈克就在那里。您要链接到外部站点的较大图像吗?如果不是,那么在将图像添加到帖子中时,您只需要选择完整大小即可,并且可以选择不再将其链接到任何地方(如果不再有意义)。
2011年

Answers:


30

为大量图像插件开发的功能大大改进:

if ( ! function_exists( 'get_attachment_id' ) ) {
    /**
     * Get the Attachment ID for a given image URL.
     *
     * @link   http://wordpress.stackexchange.com/a/7094
     *
     * @param  string $url
     *
     * @return boolean|integer
     */
    function get_attachment_id( $url ) {

        $dir = wp_upload_dir();

        // baseurl never has a trailing slash
        if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
            // URL points to a place outside of upload directory
            return false;
        }

        $file  = basename( $url );
        $query = array(
            'post_type'  => 'attachment',
            'fields'     => 'ids',
            'meta_query' => array(
                array(
                    'key'     => '_wp_attached_file',
                    'value'   => $file,
                    'compare' => 'LIKE',
                ),
            )
        );

        // query attachments
        $ids = get_posts( $query );

        if ( ! empty( $ids ) ) {

            foreach ( $ids as $id ) {

                // first entry of returned array is the URL
                if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
                    return $id;
            }
        }

        $query['meta_query'][0]['key'] = '_wp_attachment_metadata';

        // query attachments again
        $ids = get_posts( $query );

        if ( empty( $ids) )
            return false;

        foreach ( $ids as $id ) {

            $meta = wp_get_attachment_metadata( $id );

            foreach ( $meta['sizes'] as $size => $values ) {

                if ( $values['file'] === $file && $url === array_shift( wp_get_attachment_image_src( $id, $size ) ) )
                    return $id;
            }
        }

        return false;
    }
}

1
您能否解释为什么同时查询_wp_attached_file_wp_attachment_metadata
Stephen Harris

3
@StephenHarris,因为URL可以指向任何具有不同文件名的图像大小
Rarst 2014年

1
这很好用,但是在这里值得注意的是,自WordPress 4起,就如Gabriel在另一个答案中提到的那样,有一个内置函数可以做到这一点。它的工作方式与此完全相同。
克里斯·雷

2
@ChrisRae如果您查看源代码,则核心功能将不适用于图像尺寸,仅适用于主图像。
拉斯特

我认为内置的WordPress功能效果更好。这在我的产品中不起作用,但在暂存(没有SSL证书)上有效。内置函数(如下面的Ego Ipse所指出的)在两种环境中均可使用。
Syed Priom

15

所有这些复杂功能都可以简化为一个简单功能:

attachment_url_to_postid()

您只需要解析图像URL即可检索附件ID:

$attachment_id = attachment_url_to_postid( $image_url );
echo $attachment_id;

这就是您所需要的。


6
值得注意的是,这不适用于图像大小,核心版本仅搜索“主”附件。
拉斯特

3

我修改了Rarst的代码,以允许您仅匹配文件名而不是完整路径。如果您要旁载图像(如果图像不存在),这将很有帮助。当前,这仅在文件名唯一的情况下有效,但是稍后我将添加哈希检查以帮助处理具有相同文件名的图像。

function get_attachment_id( $url, $ignore_path = false ) {

if ( ! $ignore_path ) {

    $dir = wp_upload_dir();
    $dir = trailingslashit($dir['baseurl']);

    if( false === strpos( $url, $dir ) )
        return false;
}

$file = basename($url);

$query = array(
    'post_type' => 'attachment',
    'fields' => 'ids',
    'meta_query' => array(
        array(
            'key'     => '_wp_attached_file',
            'value'   => $file,
            'compare' => 'LIKE',
        )
    )
);

$ids = get_posts( $query );

foreach( $ids as $id ) {
    $match = array_shift( wp_get_attachment_image_src($id, 'full') );
    if( $url == $match || ( $ignore_path && strstr( $match, $file ) ) )
        return $id;
}

$query['meta_query'][0]['key'] = '_wp_attachment_metadata';
$ids = get_posts( $query );

foreach( $ids as $id ) {

    $meta = wp_get_attachment_metadata($id);

    foreach( $meta['sizes'] as $size => $values ) {
        if( $values['file'] == $file && ( $ignore_path || $url == array_shift( wp_get_attachment_image_src($id, $size) ) ) )
            return $id;
    }
}

return false;
}

3

好的,我找到了答案,这是我现在几天都在网上找不到的答案。请我的,如果你的主题或插件使用这仅适用WP_Customize_Image_Control(),如果你正在使用WP_Customize_Media_Control()get_theme_mod()将返回ID,而不是网址。

对于我的解决方案,我使用的是较新版本 WP_Customize_Image_Control()

论坛上的许多帖子get_attachment_id()都不再起作用了。我用了attachment_url_to_postid()

这就是我能够做到的方式。希望这可以帮助某人

// This is getting the image / url
$feature1 = get_theme_mod('feature_image_1');

// This is getting the post id
$feature1_id = attachment_url_to_postid($feature1);

// This is getting the alt text from the image that is set in the media area
$image1_alt = get_post_meta( $feature1_id, '_wp_attachment_image_alt', true );

标记

<a href="<?php echo $feature1_url; ?>"><img class="img-responsive center-block" src="<?php echo $feature1; ?>" alt="<?php echo $image1_alt; ?>"></a>

0

这是一个替代解决方案:

$image_url = get_field('main_image'); // in case of custom field usage
$image_id = attachment_url_to_postid($image_url);

// retrieve the thumbnail size of our image
$image_thumb = wp_get_attachment_image_src($image_id, 'thumbnail');

自WP 4.0起,他们引入了attachment_url_to_postid()与您的功能类似的功能find_image_post_id()

请检查此网址以供参考。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.