Obtener la primera imagen del contenido del post (ej.: imágenes hotlinked)

31 jul 2012, 05:20:13
Vistas: 39.3K
Votos: 13

Estoy usando este código directamente del codex.

function echo_first_image ($postID)
{                   
    $args = array(
    'numberposts' => 1,
    'order'=> 'ASC',
    'post_mime_type' => 'image',
    'post_parent' => $postID,
    'post_status' => null,
    'post_type' => 'attachment'
    );

    $attachments = get_children( $args );

    //print_r($attachments); // Imprimir los adjuntos

    if ($attachments) {
        foreach($attachments as $attachment) {
            $image_attributes = wp_get_attachment_image_src( $attachment->ID, 'thumbnail' )  ? wp_get_attachment_image_src( $attachment->ID, 'thumbnail' ) : wp_get_attachment_image_src( $attachment->ID, 'full' );

            echo '<img src="'.wp_get_attachment_thumb_url( $attachment->ID ).'" class="current">';

        }
    }
}

Lo llamo dentro del loop así echo_first_image ($post->ID);

La función se ejecuta pero no muestra nada... por lo que puedo ver no hay nada en $attachments

Tengo una imagen en el post que estoy usando. No es una imagen destacada ni está en una galería, solo está en el post.

¿Estoy haciendo algo mal, o hay algo mal en el código desde el principio?

0
Todas las respuestas a la pregunta 6
6
30

Si deseas mostrar una imagen que está insertada en tu contenido (una imagen enlazada directamente, por ejemplo), debes usar una función como esta (fuente):

Añade en functions.php:

function catch_that_image() {
  global $post, $posts;
  $first_img = '';
  ob_start();
  ob_end_clean();
  $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
  $first_img = $matches [1] [0];

  if(empty($first_img)){ //Define una imagen por defecto
    $first_img = "/images/default.jpg";
  }
  return $first_img;
}

Luego coloca <?php echo catch_that_image() ?> donde quieras mostrar la imagen.

Nota: una imagen enlazada directamente y colocada en tu contenido no puede establecerse como Imagen destacada, una característica nativa de WordPress.

31 jul 2012 09:26:30
Comentarios

Sí, he visto ese código por ahí... parece un poco un hack, pensarías que habría una forma "WordPress"... Me pregunto por qué necesito usar preg_match cuando el codex dice que puedes hacerlo como publiqué arriba. Eso es realmente mi pregunta para ser honesto. ¿Está mal el código que publiqué? ... más que intentar que funcione realmente. Pero gracias, puede que termine teniendo que usar esto. No entiendo la importancia de "una imagen simplemente colocada en tu contenido no puede establecerse como Imagen Destacada". ¿Eso afecta esto de alguna manera? Solo estoy intentando mostrar la primera imagen del post, no la imagen destacada.

byronyasgur byronyasgur
31 jul 2012 22:06:39

Hay una gran diferencia entre colocar un enlace de imagen dentro del contenido de tu post/página y adjuntar una imagen. Puedes adjuntar una imagen sin mostrarla en absoluto. El ejemplo del Codex trata sobre obtener un archivo adjunto a tu post/página, no hay forma de obtener una imagen colocada dentro mediante enlace, además el hotlinking no es una característica con la que WordPress trabajará sin regex de PHP.

Diana Diana
1 ago 2012 01:52:53

Sobre la referencia del Codex: como puedes ver, el doc se llama igual que la función get_childre, un adjunto es un post hijo, así que este ejemplo solo puede funcionar para contenido adjunto.

Diana Diana
1 ago 2012 02:01:03

Sí, sé que puedo adjuntar una imagen sin insertarla, esa parte está clara... pero no veo cómo puedes insertar una imagen sin adjuntarla... cuando presiono subir/insertar, subo un archivo desde mi computadora y presiono insertar en la entrada y actualizo, luego voy a la biblioteca de medios y me dice que la imagen que subí está "adjunta" a la entrada... ¿o estamos hablando de semántica aquí? Porque entiendo lo que dices sobre que ese fragmento de código solo funciona para imágenes adjuntas.

byronyasgur byronyasgur
1 ago 2012 03:01:19

Puedes enlazar directamente a un archivo de imagen en cualquier lugar. Al hacer clic en Insertar Imagen/Medios, hay una pestaña "Desde URL", donde indicas una URL de imagen, por ejemplo, del servicio imageshack. La expresión regular podrá obtener esta imagen ("tal cual"), pero WP no podrá usar esta imagen como Imagen Destacada, por ejemplo.

Diana Diana
1 ago 2012 05:37:02

Solo un poco más de información aquí, puedes "adjuntar" una imagen a la Entrada #1, pero aún así usarla en la Entrada #2. Aunque se use en la Entrada #2, está adjunta a la Entrada #1, por lo que no aparecería a través de wp_get_attachment_url

Nathan Nathan
15 jun 2016 03:28:44
Mostrar los 1 comentarios restantes
2

Sugiero dos formas:

Usando un Plugin

Consideraría usar el plugin Get The Image, así podrías hacer algo como:

$args = array(
    'post_id' => <id>
    'image_scan' => true
);
get_the_image($args);

Lo anterior intentará hacer las cosas en este orden:

  1. Buscar la imagen destacada del post
  2. Buscar la primera imagen adjunta
  3. Escanear el contenido del post para encontrar una imagen insertada.

Construyendo soporte en tu tema

Sin embargo, estoy usando una función en un plugin que implementa los dos primeros elementos de la lista anterior.

function gpi_find_image_id($post_id) {
    if (!$img_id = get_post_thumbnail_id ($post_id)) {
        $attachments = get_children(array(
            'post_parent' => $post_id,
            'post_type' => 'attachment',
            'numberposts' => 1,
            'post_mime_type' => 'image'
        ));
        if (is_array($attachments)) foreach ($attachments as $a)
            $img_id = $a->ID;
    }
    if ($img_id)
        return $img_id;
    return false;
}

Puedes adaptarla para que también coincida con el tercer elemento del fragmento de Diana:

function find_img_src($post) {
    if (!$img = gpi_find_image_id($post->ID))
        if ($img = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches))
            $img = $matches[1][0];
    if (is_int($img)) {
        $img = wp_get_attachment_image_src($img);
        if ($img) {
            $img = $img[0];
        }
    }
    return $img;
}

Solo incluye estas dos funciones en tu archivo functions.php y úsalas en el loop así:

<?php while (have_posts()) : the_post(); ?>
    <?php if ($img_src = find_img_src($post)) : ?>
        <img src="<?php echo $img_src; ?>" />
    <?php endif; ?>
<?php endwhile; ?>
31 jul 2012 14:37:27
Comentarios

El tema estará a la venta comercialmente, por lo que no quiero decirle al usuario final que debe instalar un plugin, pero gracias.

byronyasgur byronyasgur
31 jul 2012 22:11:39

@byronyasgur Edité la respuesta para aclarar que te di dos soluciones. No necesitas instalar un plugin para seguir la segunda.

vmassuchetto vmassuchetto
1 ago 2012 00:41:59
2

El código parece perfectamente seguro. Como dijiste, no tienes ninguna imagen adjunta al post.

Considera ir al panel de administración de medios y adjuntar una imagen a esa publicación.

Alternativamente, puedes extraer el contenido del post usando una expresión regular para buscar imágenes en él.

31 jul 2012 05:41:36
Comentarios

¿Tengo un malentendido sobre lo que significa exactamente "adjuntado"? ... SÍ tengo una imagen en la publicación ... ¿no se adjunta cuando haces clic en 'añadir a la publicación'?

byronyasgur byronyasgur
31 jul 2012 22:04:47

por tu pregunta, parecía que escribiste el código html que enlaza a una imagen no necesariamente adjuntada por wp.

pcarvalho pcarvalho
1 ago 2012 05:57:41
1

Entiendo que esta es una pregunta muy antigua, pero estoy colocando mi respuesta aquí ya que la respuesta más votada no es apropiada para personas nuevas en PHP.

preg_match no es un buen enfoque para analizar HTML en PHP ya que preg_match es para expresiones regulares y HTML no es una expresión regular.

Podemos usar DOM en su lugar.

function firstImg($html){
  $dom = new DOMDocument;
  $dom->loadHTML($html);
  $images = $dom->getElementsByTagName('img');
  foreach ($images as $image) {
    return $image->getAttribute('src');
  }
  return false;
}

Usar DOM es realmente bueno ya que puedes hacer más cosas además de solo obtener la primera imagen y es la forma correcta de analizar HTML.

Me gustaría poder dar una respuesta usando funciones de WordPress (funciones del CODEX y del núcleo) para obtener la primera imagen, pero ese también es el problema con el que estoy lidiando.

¡Esta no es una respuesta para todos los casos!

Considera el caso de la optimización del tamaño de la imagen. En ese caso, no puedes simplemente usar este código porque la publicación puede contener imágenes de cualquier tamaño.

28 abr 2018 17:40:05
Comentarios

"preg_match no es un buen enfoque para analizar HTML en PHP ya que preg_match es para expresiones regulares y HTML no es una expresión regular." no es cierto -- cualquier cosa con texto puede analizarse como Expresiones Regulares

bresson bresson
3 ene 2021 19:15:54
0

Este código funciona para mí:

function get_first_image( $post_id ) {
    $attach = get_children( array(
        'post_parent'    => $post_id,
        'post_type'      => 'attachment',
        'post_mime_type' => 'image',
        'order'          => 'DESC',
        'numberposts'    => 1
    ) );
    if( is_array( $attach ) && is_object( current( $attach ) ) ) {
        return current( $attach )->guid;
    }
}
24 sept 2018 17:45:41
0

Si estás intentando encontrar el ID de una publicación adjunta con attachment_url_to_postid cuando encuentras una imagen en el contenido, es posible que no encuentres ese ID si la imagen que encontraste es una versión escalada de la original.

Si no te preocupan imágenes con nombres similares, puedes reemplazar "-800x600.jpg" con preg_replace:

$first_img_url_unscaled = preg_replace(
   '/-\d+x\d+\.(jpg|jpeg|gif|png|svg|tiff|webp|heif|heic)$/i',
   '.${1}',
   $first_img_url,
);

También puedes buscar el ID del adjunto de forma más manual en la base de datos si te preocupan nombres de archivo engañosos (por ejemplo, cats-800x600.jpg podría ser un redimensionamiento de una antigua imagen de gato y el actual cats.jpg podría ser realmente una foto de un ganso).

22 may 2022 19:53:01