Convierta una URL en un adjunto / ID de publicación

32

¿Hay alguna forma de tomar una URL de una imagen y encontrar el archivo adjunto o la identificación de publicación de esa imagen en la base de datos?

Aquí está la situación:

Estoy en un ciclo revisando todas las etiquetas 'img' que están rodeadas por etiquetas 'a' en el contenido de mi publicación. si el atributo src de la etiqueta 'img' no coincide con el atributo href de la etiqueta 'a' externa, entonces quiero reemplazar la etiqueta 'img'. Al hacer esto, si el 'img' que se va a eliminar está en la galería, quiero eliminar esa publicación y luego colocar mi 'img' de reemplazo en su lugar. Intenté usar una función como esta:

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

Aparentemente, esto no es correcto porque, irónicamente, no es irónicamente único a nivel mundial. Había subido (anteriormente en el mismo script) un archivo con el mismo nombre (¿por qué? Porque era de mayor resolución y estoy tratando de reemplazar las versiones de baja resolución de la misma imagen) y aunque Wordpress guardará la imagen con un nombre diferente en el directorio, los guid se configuraron para ser iguales. (posiblemente un error).

¿Hay otra técnica que pueda usar?

Ankur
fuente
Puede establecer variables de solicitud de acuerdo con su URL, crear una instancia de WP_Query y obtener la información de la misma.
Hakre
Sería útil si puede actualizar su pregunta y publicar algunos ejemplos de su HTML que incluye las URL que desea reemplazar para que podamos analizarlas.
MikeSchinkel
Mike está justo ahí. ¿Las imágenes más grandes con las que se vincula en sitios externos? Si no es así, solo necesita elegir el tamaño completo cuando agregue la imagen a su publicación y tiene la opción de no vincularla en ningún lugar si ya no tiene sentido.
sanchothefat

Respuestas:

30

Funcionalidad enormemente mejorada desarrollada para complementos pesados ​​en imágenes:

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
fuente
1
¿Puede explicar por qué consulta ambos _wp_attached_filey _wp_attachment_metadata?
Stephen Harris
3
@StephenHarris porque la URL puede apuntar a cualquiera de los tamaños de imagen, que tienen nombres de archivo diferentes
Rarst
1
Esto funciona muy bien, pero vale la pena señalar aquí que, desde WordPress 4, hay una función integrada para hacerlo como lo menciona Gabriel en otra respuesta. Funciona exactamente de la misma manera que este.
Chris Rae
2
@ChrisRae si observa la fuente, la función principal no funcionará en los tamaños de imagen, solo en la imagen principal.
Rarst
Creo que la función incorporada de WordPress funciona mejor. Esto no funcionó en mi producción, pero funcionó en la puesta en escena (que no tiene un certificado SSL). La función integrada (como señala Ego Ipse a continuación) funciona en ambos entornos.
Syed Priom
15

Todas esas funciones complejas se pueden reducir a una función simple:

attach_url_to_postid ()

Solo necesita analizar la URL de la imagen para recuperar la ID del archivo adjunto:

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

Eso es todo lo que necesitas.

Ego Ipse
fuente
66
En particular, esto no funcionará en tamaños de imagen, la versión principal solo busca el archivo adjunto "principal".
Rarst
3

Modifiqué el código de Rarst para permitirle que coincida solo con el nombre del archivo en lugar de la ruta completa. Esto es útil si está a punto de cargar la imagen si no existe. Actualmente, esto solo funciona si los nombres de los archivos son únicos, pero más adelante agregaré una comprobación de hash para ayudar con las imágenes que tienen el mismo nombre de archivo.

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;
}
Luke Gedeon
fuente
3

Ok, encontré la respuesta que nadie tiene en la red que he estado buscando durante días. Tenga en mina de esto sólo funciona si su tema o plugin está utilizando el WP_Customize_Image_Control()si está utilizando WP_Customize_Media_Control()el get_theme_mod()devolverá el ID y no la URL.

Para mi solución, estaba usando la versión más nueva WP_Customize_Image_Control()

Muchas publicaciones en los foros tienen el get_attachment_id()que ya no funciona. solíaattachment_url_to_postid()

Así es como pude hacerlo. Espero que esto ayude a alguien por ahí

// 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 );

Margen

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

Aquí hay una solución alternativa:

$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');

Desde WP 4.0 introdujeron una función attachment_url_to_postid()que se comporta de manera similar a la de tufind_image_post_id()

Por favor, consulte esta url para su referencia.

Lefan
fuente