Transformă un URL într-un ID de Atașament/Postare

10 ian. 2011, 07:43:54
Vizualizări: 16.6K
Voturi: 33

Există vreo metodă prin care pot lua URL-ul unei imagini și să găsesc ID-ul atașamentului sau postării acelei imagini în baza de date?

Iată situația:

Sunt într-o buclă care parcurge toate tag-urile 'img' înconjurate de tag-uri 'a' din conținutul postării mele. Dacă atributul src al tag-ului 'img' nu se potrivește cu atributul href al tag-ului 'a' exterior, atunci vreau să înlocuiesc tag-ul 'img'. În acest proces, dacă 'img'-ul care urmează să fie eliminat face parte din galerie, vreau să șterg acea postare și apoi să pun imaginea mea de înlocuire în locul ei. Am încercat să folosesc o funcție ca aceasta:

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

Această abordare pare să nu funcționeze corect, deoarece guid-ul, ironic, nu este global unic. Am încărcat mai devreme (în același script) un fișier cu același nume (de ce? pentru că avea o rezoluție mai mare și încerc să înlocuiesc versiunile cu rezoluție mai mică ale aceleiași imagini) și, deși WordPress salvează imaginea cu un nume diferit în director, guid-urile au fost setate la aceeași valoare. (posibil un bug).

Există vreo altă tehnică pe care o pot folosi?

3
Comentarii

Probabil poți seta variabilele de request conform URL-ului tău, instantia WP_Query și obține informațiile din el.

hakre hakre
10 ian. 2011 14:38:51

Ar fi de ajutor dacă ai putea actualiza întrebarea ta și să postezi câteva exemple din HTML-ul tău care include URL-urile pe care vrei să le înlocuiești, astfel încât să le putem discuta.

MikeSchinkel MikeSchinkel
10 ian. 2011 18:46:21

Mike are dreptate aici. Imaginile mai mari la care te legi sunt pe site-uri externe? Dacă nu, atunci trebuie doar să alegi dimensiunea maximă când adaugi imaginea în postare și ai opțiunea să nu o legezi nicăieri dacă nu mai are sens.

sanchothefat sanchothefat
10 ian. 2011 20:46:36
Toate răspunsurile la întrebare 6
7
31

Funcție îmbunătățită masiv dezvoltată pentru plugin-uri cu multe imagini:

if ( ! function_exists( 'get_attachment_id' ) ) {
    /**
     * Obține ID-ul atașamentului pentru o anumită URL a imaginii.
     *
     * @link   http://wordpress.stackexchange.com/a/7094
     *
     * @param  string $url
     *
     * @return boolean|integer
     */
    function get_attachment_id( $url ) {

        $dir = wp_upload_dir();

        // baseurl nu are niciodată o bară oblică la final
        if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
            // URL-ul indică o locație în afara directorului de încărcare
            return false;
        }

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

        // interoghează atașamentele
        $ids = get_posts( $query );

        if ( ! empty( $ids ) ) {

            foreach ( $ids as $id ) {

                // primul element din array-ul returnat este URL-ul
                if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
                    return $id;
            }
        }

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

        // interoghează din nou atașamentele
        $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 ian. 2011 09:13:18
Comentarii

Poți explica de ce interoghezi atât _wp_attached_file cât și _wp_attachment_metadata?

Stephen Harris Stephen Harris
2 iul. 2014 01:11:12

@StephenHarris deoarece URL-ul poate indica oricare dintre dimensiunile imaginii, care au toate nume de fișiere diferite

Rarst Rarst
2 iul. 2014 01:14:08

Această soluție funcționează excelent, dar merită menționat aici că, începând cu WordPress 4, există o funcție integrată pentru a face acest lucru, așa cum a menționat Gabriel într-un alt răspuns. Funcționează exact la fel ca aceasta.

Chris Rae Chris Rae
28 sept. 2016 02:21:37

@ChrisRae dacă te uiți la sursă, funcția de bază nu va funcționa pe dimensiunile imaginilor, doar pe imaginea principală.

Rarst Rarst
28 sept. 2016 11:48:12

Cred că funcția încorporată din WordPress funcționează mai bine. Aceasta nu a funcționat în mediul meu de producție, dar a funcționat pe Staging (care nu are un certificat SSL). Funcția încorporată (așa cum a menționat Ego Ipse mai jos) funcționează în ambele medii.

Syed Priom Syed Priom
18 ian. 2017 23:17:36

@SyedPriom dacă URL-ul pe care îl cauți este inconsistent cu datele tale stocate, atunci într-adevăr nu va funcționa, nu era ceva la care m-am gândit când am scris asta, dar probabil poate fi îmbunătățit pentru protocoale. După cum am menționat mai sus, principala problemă cu funcția nativă este că nu va funcționa pe dimensiunile imaginilor.

Rarst Rarst
19 ian. 2017 10:25:44

Este o funcție excelentă, dar uneori aruncă o notificare "Notice: Only variables should be passed by reference" Pentru a o rezolva, atribuiți rezultatul array_keys unei variabile și transmiteți acea variabilă

$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 oct. 2019 18:41:39
Arată celelalte 2 comentarii
2
15

Toate acele funcții complexe pot fi reduse la o singură funcție simplă:

attachment_url_to_postid()

Trebuie doar să analizezi URL-ul imaginii pentru a obține ID-ul atașamentului:

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

Este tot ce ai nevoie.

1 nov. 2015 08:58:45
Comentarii

Este important de menționat că acest lucru nu va funcționa pentru dimensiunile imaginilor, versiunea de bază caută doar fișierul atașat "principal".

Rarst Rarst
28 sept. 2016 11:48:54

Această soluție nu a funcționat cu variațiile de dimensiuni ale imaginilor. Funcționează doar cu imaginea principală în dimensiunea "full".

Azamat Azamat
9 nov. 2021 09:18:22
0

Am modificat codul lui Rarst pentru a permite potrivirea doar a numelui fișierului în loc de calea completă. Acest lucru este util dacă intenționați să încărcați manual imaginea în cazul în care aceasta nu există. În prezent, acest lucru funcționează doar dacă numele fișierelor sunt unice, dar voi adăuga ulterior o verificare prin hash pentru a ajuta cu imaginile care au același nume de fișier.

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

Bun, am găsit răspunsul pe care nimeni nu îl are pe internet. Am căutat zile întregi. Rețineți că acest lucru funcționează doar dacă tema sau pluginul tău utilizează WP_Customize_Image_Control(). Dacă folosești WP_Customize_Media_Control(), funcția get_theme_mod() va returna ID-ul și nu URL-ul.

Pentru soluția mea, am folosit versiunea mai nouă WP_Customize_Image_Control().

Multe postări pe forumuri menționează get_attachment_id(), care nu mai funcționează. Eu am folosit attachment_url_to_postid().

Iată cum am reușit să o fac. Sper că acest lucru va ajuta pe cineva.

// Aceasta obține imaginea / URL-ul
$feature1 = get_theme_mod('feature_image_1');

// Aceasta obține ID-ul postului
$feature1_id = attachment_url_to_postid($feature1);

// Aceasta obține textul alternativ al imaginii setat în zona 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

Începând cu versiunea 4.0 a WordPress, există o funcție de bază attachment_url_to_postid care "Încearcă să convertească un URL de atașament într-un ID de post." Dar această funcție are un mare dezavantaj pentru că nu poate converti URL-uri de imagini cu dimensiuni personalizate.

Majoritatea răspunsurilor populare înainte încercau să rezolve această problemă, dar toate implicau o interogare grea la baza de date, încercând să obțină toate atașamentele existente și apoi să parcurgă fiecare dintre ele pentru a obține metadatele atașamentului și a găsi dimensiunile personalizate. Acest lucru funcționează bine doar dacă ai un număr mic de atașamente în proiectul tău WordPress. Dar cu siguranță vei avea probleme de performanță dacă ai un proiect mare cu peste 10.000 de atașamente.

Totuși, poți extinde funcția attachment_url_to_postid prin filtrul existent attachment_url_to_postid, forțând funcția să caute și între dimensiunile personalizate ale imaginilor. Doar adaugă codul de mai jos în fișierul functions.php al temei active WordPress. și apoi folosește funcția attachment_url_to_postid ca înainte, dar cu funcționalitatea suplimentară pentru dimensiuni personalizate.

    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 ian. 2020 19:27:52
Comentarii

Ar trebui să aibă mai multe voturi pozitive! Sau, mai bine, ar trebui să funcționeze așa în WP Core...

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

Iată o soluție alternativă:

$image_url = get_field('main_image'); // în cazul utilizării unui câmp personalizat
$image_id = attachment_url_to_postid($image_url);

// preluăm dimensiunea thumbnail a imaginii noastre
$image_thumb = wp_get_attachment_image_src($image_id, 'thumbnail');

Începând cu WP 4.0 au introdus o funcție attachment_url_to_postid() care se comportă similar cu funcția ta find_image_post_id()

Te rugăm să verifici acest link pentru referință.

21 mar. 2018 12:46:43