Превратите URL в идентификатор вложения / сообщения

32

Можно ли каким-либо образом взять URL-адрес изображения и найти вложение или идентификатор публикации этого изображения в базе данных?

Вот ситуация:

Я нахожусь в цикле, просматривая все теги 'img', которые окружены тегами 'a' в моем посте если атрибут src тега 'img' не совпадает с атрибутом href внешнего тега 'a', то я хочу заменить тег '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;
}

Это, очевидно, не правильно, потому что по иронии судьбы не является глобально уникальным. Я (ранее в том же сценарии) загрузил файл с тем же именем (почему? Потому что это было более высокое разрешение, и я пытаюсь заменить версии одного и того же изображения с низким разрешением), и хотя WordPress сохранит изображение с другим именем в каталог, направляющие были установлены одинаковыми. (возможно ошибка).

Есть ли другая техника, которую я могу использовать?

Анкур
источник
Вы можете установить переменные запроса в соответствии с вашим URL, создать экземпляр WP_Query и получить информацию из него.
Хакре
Было бы полезно, если бы вы могли обновить свой вопрос и опубликовать несколько примеров вашего HTML-кода, включающего URL-адреса, которые вы хотите заменить, чтобы мы могли их обсудить.
MikeSchinkel
Майк прямо здесь. Большие изображения, на которые вы ссылаетесь, находятся на внешних сайтах? Если нет, тогда вам просто нужно выбрать полный размер, когда вы добавляете изображение в свое сообщение, и у вас есть возможность не связывать его где-либо, если это больше не имеет смысла.
sanchothefat

Ответы:

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;
    }
}
Rarst
источник
1
Можете ли вы объяснить, почему вы запрашиваете оба _wp_attached_fileи _wp_attachment_metadata?
Стивен Харрис
3
@StephenHarris, потому что URL может указывать на любой размер изображения, у каждого из которых есть разные имена файлов
Rarst
1
Это прекрасно работает, но здесь стоит отметить, что, начиная с WordPress 4, есть встроенная функция для этого, как упомянуто Габриэлем в другом ответе. Он работает точно так же, как и этот.
Крис Рей
2
@ChrisRae, если вы посмотрите на источник, основная функция не будет работать на размерах изображения, только на основном изображении.
Первый
Я думаю, что встроенная функция WordPress работает лучше. Это не работало в моем производстве, но работало на Staging (у которого нет сертификата SSL). Встроенная функция (как указывает Ego Ipse ниже) работает в обеих средах.
Syed Priom
15

Все эти сложные функции могут быть сведены к одной простой функции:

attachment_url_to_postid ()

Вам нужно только проанализировать URL-адрес изображения, чтобы получить идентификатор вложения:

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

Это все, что вам нужно.

Эго Ипс
источник
6
Примечательно, что это не будет работать с размерами изображений, основная версия ищет только «основной» вложенный файл.
Первый
3

Я изменил код Рарста, чтобы вы могли сопоставлять только имя файла вместо полного пути. Это полезно, если вы собираетесь загружать изображение, если оно не существует. В настоящее время это работает, только если имена файлов уникальны, но позже я добавлю проверку хеша, чтобы помочь с изображениями с таким же именем файла.

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()если вы используете возвращает идентификатор , а не URL - адрес.WP_Customize_Media_Control()get_theme_mod()

Для моего решения я использовал более новую версию 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>
DevTurtle
источник
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()

Пожалуйста, проверьте этот URL для вашей справки.

Lefan
источник