Превратите 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;
    }
}

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>

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 для вашей справки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.