Trasforma un URL in un ID allegato / post


32

Esiste un modo per prendere un URL di un'immagine e trovare l'allegato o l'ID post di quell'immagine nel database?

Ecco la situazione:

Sono in un ciclo che esamina tutti i tag "img" che sono circondati da tag "a" nel contenuto del mio post. se l'attributo src del tag 'img' non corrisponde all'attributo href del tag 'a' esterno, allora voglio sostituire il tag 'img'. Nel fare questo, se il 'img' che deve essere rimosso si trova nella galleria, voglio eliminare quel post e quindi mettere il mio 'img' sostitutivo al suo posto. Ho provato ad usare una funzione come questa:

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

Questo a quanto pare non è giusto perché il guid non è ironicamente non globalmente unico. Avevo caricato (precedentemente nello stesso script) un file con lo stesso nome (perché? Perché era una risoluzione più alta e sto cercando di sostituire le versioni a bassa risoluzione della stessa immagine) e sebbene wordpress salverà l'immagine con un nome diverso in la directory, i guid erano impostati per essere gli stessi. (possibilmente un bug).

C'è un'altra tecnica che posso usare?


È possibile impostare in modo comprensibile le variabili di richiesta in base al proprio URL, creare un'istanza di WP_Query e ottenere le informazioni da esso.
Hacre,

Sarebbe utile se puoi aggiornare la tua domanda e pubblicare alcuni esempi del tuo HTML che include URL che desideri sostituire in modo che possiamo discuterne.
MikeSchinkel,

Mike è proprio lì. Le immagini più grandi a cui stai collegando su siti esterni? In caso contrario, devi solo scegliere la dimensione intera quando aggiungi l'immagine al tuo post e hai la possibilità di non collegarla da nessuna parte se non ha più senso.
sanchothefat,

Risposte:


30

Funzione notevolmente migliorata sviluppata per plugin ricchi di immagini:

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
Puoi spiegare perché esegui una query su entrambi _wp_attached_filee _wp_attachment_metadata?
Stephen Harris,

3
@StephenHarris perché l'URL può puntare a qualsiasi dimensione dell'immagine, che hanno tutti nomi di file diversi
Rarst

1
Funziona benissimo, ma vale la pena notare che, da WordPress 4, esiste una funzione integrata per farlo, come indicato da Gabriel in un'altra risposta. Funziona esattamente allo stesso modo di questo.
Chris Rae,

2
@ChrisRae se guardi alla fonte la funzione principale non funzionerà sulle dimensioni dell'immagine, ma solo sull'immagine principale.
Rarst,

Penso che la funzione WordPress integrata funzioni meglio. Questo non ha funzionato nella mia produzione, ma ha funzionato su Staging (che non ha un certificato SSL). La funzione integrata (come sottolineato da Ego Ipse di seguito) funziona in entrambi gli ambienti.
Syed Priom,

15

Tutte queste funzioni complesse possono essere ridotte a una semplice funzione:

attachment_url_to_postid ()

Devi solo analizzare l'URL dell'immagine per recuperare l'ID allegato:

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

Questo è tutto ciò di cui hai bisogno.


6
In particolare, ciò non funzionerà sulle dimensioni delle immagini, la versione principale cerca solo il file allegato "principale".
Rarst,

3

Ho modificato il codice di Rarst per permetterti di abbinare solo il nome del file invece del percorso completo. Questo è utile se stai per caricare di sideload l'immagine se non esiste. Attualmente funziona solo se i nomi dei file sono univoci, ma in seguito aggiungerò un controllo hash per aiutare le immagini con lo stesso nome file.

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

Ok ho trovato la risposta che nessuno ha in rete che cercavo da giorni ormai. Tenete a mia questo funziona solo se il tema o il plug-in sta usando il WP_Customize_Image_Control()se si utilizza WP_Customize_Media_Control()la get_theme_mod()restituirà l'ID e non l'url.

Per la mia soluzione stavo usando la versione più recente WP_Customize_Image_Control()

Molti post sui forum hanno il get_attachment_id()quale non funziona più. ero solitoattachment_url_to_postid()

Ecco come sono riuscito a farlo. Spero che questo aiuti qualcuno là fuori

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

markup

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

0

Ecco una soluzione 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');

Da WP 4.0 hanno introdotto una funzione attachment_url_to_postid()che si comporta in modo simile alla tuafind_image_post_id()

Controlla questo url come riferimento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.