Convertire un URL in un ID Allegato/Post nel Database WordPress

10 gen 2011, 07:43:54
Visualizzazioni: 16.6K
Voti: 33

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

Ecco la situazione:

Sto ciclando tutti i tag 'img' 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'. In questo processo, se l'immagine da rimuovere è nella galleria, voglio eliminare quel post e poi inserire la mia immagine sostitutiva al suo posto. Ho provato a 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 apparentemente non funziona perché il guid ironicamente non è globalmente univoco. Avevo (precedentemente nello stesso script) caricato un file con lo stesso nome (perché? perché era a risoluzione più alta e sto cercando di sostituire versioni a bassa risoluzione della stessa immagine) e sebbene WordPress salvi l'immagine con un nome diverso nella directory, i guid erano impostati per essere uguali. (possibilmente un bug).

C'è un'altra tecnica che posso usare?

3
Commenti

Probabilmente puoi impostare le variabili della richiesta in base al tuo URL, istanziare WP_Query e ottenere le informazioni da esso.

hakre hakre
10 gen 2011 14:38:51

Sarebbe utile se potessi aggiornare la tua domanda e pubblicare alcuni esempi del tuo HTML che includono gli URL che vuoi sostituire, così possiamo discuterne.

MikeSchinkel MikeSchinkel
10 gen 2011 18:46:21

Mike ha ragione. Le immagini più grandi a cui stai collegando si trovano su siti esterni? Se no, allora ti basta scegliere la dimensione completa quando aggiungi l'immagine al tuo post e hai l'opzione di non collegarla da nessuna parte se non ha più senso.

sanchothefat sanchothefat
10 gen 2011 20:46:36
Tutte le risposte alla domanda 6
7
31

Funzione notevolmente migliorata sviluppata per plugin con molte immagini:

if ( ! function_exists( 'get_attachment_id' ) ) {
    /**
     * Ottiene l'ID dell'allegato per un dato URL dell'immagine.
     *
     * @link   http://wordpress.stackexchange.com/a/7094
     *
     * @param  string $url
     *
     * @return boolean|integer
     */
    function get_attachment_id( $url ) {

        $dir = wp_upload_dir();

        // baseurl non ha mai uno slash finale
        if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
            // L'URL punta a una posizione esterna alla directory di upload
            return false;
        }

        $file  = basename( $url );
        $query = array(
            'post_type'  => 'attachment',
            'fields'     => 'ids',
            'meta_query' => array(
                array(
                    'key'     => '_wp_attached_file',
                    'value'   => $file,
                    'compare' => 'LIKE',
                ),
            )
        );

        // interroga gli allegati
        $ids = get_posts( $query );

        if ( ! empty( $ids ) ) {

            foreach ( $ids as $id ) {

                // il primo elemento dell'array restituito è l'URL
                if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
                    return $id;
            }
        }

        $query['meta_query'][0]['key'] = '_wp_attachment_metadata';

        // interroga nuovamente gli allegati
        $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;
    }
}
17 gen 2011 09:13:18
Commenti

Puoi spiegare perché interroghi sia _wp_attached_file che _wp_attachment_metadata?

Stephen Harris Stephen Harris
2 lug 2014 01:11:12

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

Rarst Rarst
2 lug 2014 01:14:08

Funziona benissimo, ma vale la pena notare che, da WordPress 4, esiste una funzione integrata per farlo come menzionato da Gabriel in un'altra risposta. Funziona esattamente nello stesso modo di questa.

Chris Rae Chris Rae
28 set 2016 02:21:37

@ChrisRae se guardi il sorgente, la funzione principale non funzionerà sulle dimensioni delle immagini, solo sull'immagine principale.

Rarst Rarst
28 set 2016 11:48:12

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

Syed Priom Syed Priom
18 gen 2017 23:17:36

@SyedPriom se l'URL che stai cercando è incoerente con i tuoi dati memorizzati, allora non funzionerà infatti, non era qualcosa che ho considerato quando ho scritto questo, ma probabilmente può essere migliorato per i protocolli. Come sopra, il problema principale con la funzione nativa è che non funzionerà sulle dimensioni delle immagini.

Rarst Rarst
19 gen 2017 10:25:44

È una funzione molto utile, ma a volte genera un avviso "Notice: Only variables should be passed by reference" Per risolverlo basta assegnare il risultato di array_keys a una variabile e passare quella variabile

$image_src = wp_get_attachment_image_src( $id, $size ); if ( $values['file'] === $file && $url === array_shift( $image_src ) ) return $id;

Oleg Apanovich Oleg Apanovich
24 ott 2019 18:41:39
Mostra i restanti 2 commenti
2
15

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

attachment_url_to_postid()

Hai solo bisogno di analizzare l'URL dell'immagine per recuperare l'ID dell'allegato:

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

È tutto ciò di cui hai bisogno.

1 nov 2015 08:58:45
Commenti

Nota che questo non funzionerà sulle dimensioni delle immagini, la versione core cerca solo il file allegato "principale".

Rarst Rarst
28 set 2016 11:48:54

Questa soluzione non ha funzionato con le variazioni di dimensione delle immagini. Funziona solo con l'immagine principale in dimensione "full".

Azamat Azamat
9 nov 2021 09:18:22
0

Ho modificato il codice di Rarst per permetterti di confrontare solo il nome del file invece del percorso completo. Questo è utile se stai per importare lateralmente l'immagine se non esiste. Attualmente funziona solo se i nomi dei file sono unici, ma aggiungerò successivamente un controllo hash per gestire 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;
}
25 apr 2012 19:59:13
0

Ho finalmente trovato la risposta che nessuno ha in rete, ho cercato per giorni. Tieni presente che questo funziona solo se il tuo tema o plugin utilizza WP_Customize_Image_Control(). Se stai usando WP_Customize_Media_Control(), la funzione get_theme_mod() restituirà l'ID e non l'URL.

Per la mia soluzione, stavo utilizzando la versione più recente WP_Customize_Image_Control().

Molti post sui forum menzionano get_attachment_id(), che però non funziona più. Ho usato attachment_url_to_postid().

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

// Questo ottiene l'immagine / URL
$feature1 = get_theme_mod('feature_image_1');

// Questo ottiene l'ID del post
$feature1_id = attachment_url_to_postid($feature1);

// Questo ottiene il testo alternativo dall'immagine impostato nell'area media
$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>
29 apr 2017 05:26:18
1

Dalla versione 4.0 di WordPress esiste una funzione core attachment_url_to_postid che "Prova a convertire un URL di un allegato in un ID post." Ma questa funzione ha un grosso difetto perché non può convertire URL di immagini con dimensioni personalizzate.

Quasi tutte le risposte principali prima cercano di risolvere questo problema, ma tutte hanno una query al database molto pesante che tenta di ottenere tutti gli allegati esistenti e poi li scorre tutti cercando di ottenere i metadati dell'allegato e trovare le dimensioni personalizzate al loro interno. Funziona bene solo se hai una piccola quantità di allegati nel tuo progetto WordPress. Ma avrai sicuramente problemi di prestazioni se hai un progetto grande con più di 10000 allegati.

Ma puoi estendere la funzione core attachment_url_to_postid attraverso il filtro esistente attachment_url_to_postid cercando di forzare la funzione attachment_url_to_postid a cercare anche tra le dimensioni personalizzate delle immagini. Basta aggiungere il codice qui sotto al file functions.php del tuo tema WordPress attivo. e poi usare la funzione attachment_url_to_postid come la usavi prima ma con la funzionalità aggiuntiva delle dimensioni personalizzate.

    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;
    }
4 gen 2020 19:27:52
Commenti

Dovrebbe avere più voti! O meglio ancora, dovrebbe funzionare così nel Core di WP...

Sarah Groß Sarah Groß
21 apr 2022 11:47:26
0

Ecco una soluzione alternativa:

$image_url = get_field('main_image'); // nel caso di utilizzo di un campo personalizzato
$image_id = attachment_url_to_postid($image_url);

// recupera la dimensione thumbnail della nostra immagine
$image_thumb = wp_get_attachment_image_src($image_id, 'thumbnail');

Dalla versione 4.0 di WP è stata introdotta la funzione attachment_url_to_postid() che si comporta in modo simile alla tua find_image_post_id()

Per tua referenza, controlla questo url.

21 mar 2018 12:46:43