有什么办法可以获取图像的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并从中获取信息。

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

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

#1 楼

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

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;
    }
}


评论


您能否解释为什么同时查询_wp_attached_file和_wp_attachment_metadata?

–斯蒂芬·哈里斯(Stephen Harris)
2014年7月1日在22:11

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

–稀有
2014年7月1日在22:14

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

–克里斯·雷(Chris Rae)
16-09-27在23:21

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

–稀有
16-09-28在8:48

@SyedPriom如果您正在搜索的URL与您存储的数据不一致,则它实际上将无法工作,这不是我在编写此文件时所考虑的事情,但可能会针对协议进行改进。如上所述,本机功能的主要问题是它不适用于图像尺寸。

–稀有
17年1月19日在8:25

#2 楼

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

attachment_url_to_postid()

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

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


这就是您所需要的。

评论


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

–稀有
16-09-28在8:48

#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;
}


#4 楼

好的,我找到了答案,这是我现在几天都在网上找不到的答案。请记住,这仅在主题或插件使用WP_Customize_Image_Control()时有效,如果使用WP_Customize_Media_Control(),则get_theme_mod()将返回ID而不是URL。

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

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

这就是我的方法。希望这对外面的人有帮助

#5 楼

这是一个替代解决方案:

$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()类似。

请检查此网址供您参考。

#6 楼

从wordpress 4.0版开始,有一个wordpress核心功能attachment_url_to_postid,“尝试将附件URL转换为帖子ID”。但是这些函数有很大的缺陷,因为它无法转换自定义图像的url大小。

尝试解决这些问题之前,几乎所有的最佳答案,但是所有这些函数都有非常繁重的数据库查询,试图获取所有现有的附件,然后遍历所有附件,以获取附件元数据并在其中找到自定义尺寸。仅当您的wordpress项目中的附件数量很少时,它才能很好地工作。但是,如果您的大型项目具有10000个以上的附件,则肯定会遇到性能问题。

但是您可以通过现有的filter_attach_url_to_postid扩展Attachment_url_to_postid核心函数,然后尝试强制自定义图像大小中的attachment_url_to_postid函数搜索。
只需将以下代码添加到活动的wordpress主题的functions.php文件中。
,然后像以前一样使用attachment_url_to_postid函数,但具有其他自定义大小功能。

    add_filter( 'attachment_url_to_postid', 'change_attachment_url_to_postid', 10, 2 );
    function change_attachment_url_to_postid( $post_id, $url ) {
        if ( ! $post_id ) {
            $file  = basename( $url );
            $query = array(
                'post_type'  => 'attachment',
                'fields'     => 'ids',
                'meta_query' => array(
                    array(
                        'key'     => '_wp_attachment_metadata',
                        'value'   => $file,
                        'compare' => 'LIKE',
                    ),
                )
            );

            $ids = get_posts( $query );

            if ( ! empty( $ids ) ) {

                foreach ( $ids as $id ) {
                    $meta = wp_get_attachment_metadata( $id );

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

        return $post_id;
    }