Zmień adres URL w identyfikator załącznika / posta

32

Czy mogę w jakiś sposób pobrać adres URL obrazu i znaleźć załącznik lub identyfikator tego obrazu w bazie danych?

Oto sytuacja:

Jestem w pętli przeglądając wszystkie tagi „img”, które są otoczone przez tagi „a” w treści mojego postu. jeśli atrybut src znacznika „img” nie pasuje do atrybutu href zewnętrznego znacznika „a”, to chcę zastąpić znacznik „img”. Robiąc to, jeśli „img”, który ma zostać usunięty, znajduje się w galerii, chcę usunąć ten post, a następnie umieścić moje zastępcze „img” na jego miejscu. Próbowałem użyć funkcji takiej jak ta:

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

To najwyraźniej nie jest słuszne, ponieważ przewodnik nie jest ironicznie wyjątkowy na całym świecie. Przesłałem (wcześniej w tym samym skrypcie) plik o tej samej nazwie (dlaczego? Bo to była wyższa rozdzielczość i próbuję zastąpić wersje tego samego obrazu w niskiej rozdzielczości) i chociaż wordpress zapisze obraz pod inną nazwą w katalog, przewodniki były ustawione tak samo. (prawdopodobnie błąd).

Czy mogę zastosować inną technikę?

Ankur
źródło
Możesz pewnie ustawić zmienne żądania zgodnie ze swoim adresem URL, utworzyć instancję WP_Query i uzyskać z niej informacje.
hakre 10.01.11
Pomoże Ci to zaktualizować pytanie i opublikować przykłady kodu HTML zawierającego adresy URL, które chcesz zastąpić, abyśmy mogli je omówić.
MikeSchinkel,
Mike tam jest. Czy większe obrazy, do których prowadzisz linki w witrynach zewnętrznych? Jeśli nie, musisz po prostu wybrać pełny rozmiar podczas dodawania obrazu do postu i masz opcję, aby nie linkować go nigdzie, jeśli nie ma to już sensu.
sanchothefat 10.01.11

Odpowiedzi:

30

Znacząco ulepszona funkcja opracowana dla wtyczek obciążających obrazy:

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
źródło
1
Czy możesz wyjaśnić, dlaczego pytasz zarówno, jak _wp_attached_filei _wp_attachment_metadata?
Stephen Harris
3
@StephenHarris, ponieważ adres URL może wskazywać na dowolny rozmiar obrazu, z których wszystkie mają różne nazwy plików
Rarst
1
Działa to świetnie, ale warto tutaj zauważyć, że od WordPress 4 jest wbudowana funkcja, aby to zrobić, jak wspomniał Gabriel w innej odpowiedzi. Działa dokładnie tak samo jak ten.
Chris Rae
2
@ChrisRae, jeśli spojrzysz na źródło, podstawowa funkcja nie będzie działać na rozmiarach obrazów, tylko na głównym obrazie.
Rarst
Myślę, że wbudowana funkcja WordPress działa lepiej. Nie działało to w mojej produkcji, ale działało na etapie testowania (który nie ma certyfikatu SSL). Wbudowana funkcja (jak wskazał Ego Ipse poniżej) działa w obu środowiskach.
Syed Priom
15

Wszystkie te złożone funkcje można sprowadzić do jednej prostej funkcji:

załącznik_url_to_postid ()

Musisz tylko przeanalizować adres URL obrazu, aby pobrać identyfikator załącznika:

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

To wszystko czego potrzebujesz.

Ego Ipse
źródło
6
W szczególności nie będzie to działać na rozmiarach obrazów, wersja podstawowa przeszukuje tylko „główny” załączony plik.
Rarst
3

Zmodyfikowałem kod Rarsta, aby umożliwić dopasowanie tylko nazwy pliku zamiast pełnej ścieżki. Jest to przydatne, jeśli masz zamiar załadować obraz na bok, jeśli nie istnieje. Obecnie działa to tylko wtedy, gdy nazwy plików są unikalne, ale później dodam kontrolę skrótu, aby pomóc w przypadku obrazów o tej samej nazwie pliku.

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
źródło
3

Ok znalazłem odpowiedź, której nikt nie ma w sieci, której szukałem od kilku dni. Przechowywać w kopalni to działa tylko wtedy, gdy motyw lub wtyczka jest za pomocą WP_Customize_Image_Control()jeśli używasz zwróci identyfikator, a nie URL.WP_Customize_Media_Control()get_theme_mod()

Do mojego rozwiązania korzystałem z nowszej wersji WP_Customize_Image_Control()

Wiele postów na forach zawiera te, get_attachment_id()które już nie działają. użyłemattachment_url_to_postid()

Oto jak mogłem to zrobić. Mam nadzieję, że to pomoże komuś tam

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

Narzut

<a href="<?php echo $feature1_url; ?>"><img class="img-responsive center-block" src="<?php echo $feature1; ?>" alt="<?php echo $image1_alt; ?>"></a>
DevTurtle
źródło
0

Oto alternatywne rozwiązanie:

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

Od WP 4.0 wprowadzono funkcję, attachment_url_to_postid()która zachowuje się podobnie do twojejfind_image_post_id()

Sprawdź ten adres URL w celach informacyjnych.

Lefan
źródło