Получить первое изображение из содержимого записи (например: hotlinked изображения)
Я использую этот код непосредственно из документации.
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); // Вывести массив вложений
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">';
}
}
}
Я вызываю его внутри цикла вот так: echo_first_image ($post->ID);
Функция вызывается, но ничего не выводится... насколько я могу видеть, в $attachments
ничего нет.
У меня есть изображение в записи, которую я использую. Это не избранное изображение и не находится в галерее, просто в записи.
Я делаю что-то не так, или изначально с кодом что-то не так?

Если вы хотите отобразить изображение, вставленное в ваш контент (например, горячую ссылку на изображение), вам необходимо использовать функцию, подобную этой (источник):
Добавьте в 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)){ // Определяет изображение по умолчанию
$first_img = "/images/default.jpg";
}
return $first_img;
}
Затем разместите <?php echo catch_that_image() ?>
там, где вы хотите отобразить изображение.
Примечание: изображение с горячей ссылкой, просто вставленное в ваш контент, не может быть установлено как Избранное изображение (Featured Image), встроенная функция WordPress.

Да, я видел этот код в разных местах... кажется это немного костыль, можно было бы ожидать более "WordPress"-способа... Мне интересно, почему мне нужно использовать preg_match, когда в кодексе говорится, что можно сделать как я написал выше. Вот в чем мой вопрос, если честно. Разве код, который я привел, ошибочный? ... больше чем попытки заставить его работать. Но спасибо, возможно мне придется использовать это. Я не понимаю значимости "изображение, просто размещенное в вашем контенте, не может быть установлено как Избранное изображение". Это как-то влияет на данную ситуацию? Я просто пытаюсь отобразить первое изображение из поста, а не избранное изображение.

Есть большая разница между размещением ссылки на изображение внутри контента вашего поста/страницы и прикреплением изображения. Вы можете прикрепить изображение, вообще не отображая его. Пример из Кодекса касается получения файла, прикрепленного к вашему посту/странице — нет способа получить изображение, просто размещенное внутри через ссылку, также хотлинкинг — это не та функция, с которой WP будет работать без PHP regex.

По поводу ссылки на Кодекс: как вы можете видеть, документ называется по имени функции get_childre
, вложение (attachment) является дочерним постом, поэтому этот пример работает только для прикрепленного контента.

Да, я знаю, что можно прикрепить изображение без вставки, эта часть понятна... но я не понимаю, как можно вставить изображение без прикрепления... когда я нажимаю "загрузить/вставить", загружаю файл с компьютера, нажимаю "вставить в запись" и обновляю, затем перехожу в медиатеку, там указано, что загруженное изображение "прикреплено" к записи?.. Или мы говорим о семантике, потому что я понимаю, о чем вы говорите в отношении того, что этот код работает только для прикрепленных изображений.

Вы можете использовать прямую ссылку на изображение где угодно. При нажатии "Вставить изображение/медиа" есть вкладка "Из URL", где вы указываете URL изображения, например, с сервиса imageshack. Регулярное выражение сможет получить это изображение ("как есть"), но WordPress не сможет использовать его как Избранное изображение, к примеру.

Предлагаю два способа:
Использование плагина
Я бы рекомендовал использовать плагин Get The Image, тогда вы сможете сделать так:
$args = array(
'post_id' => <id>
'image_scan' => true
);
get_the_image($args);
Вышеуказанный код будет пытаться выполнить поиск в таком порядке:
- Поиск миниатюры записи
- Поиск первого прикрепленного изображения
- Сканирование содержимого записи на наличие вставленного изображения
Реализация в теме
Однако я использую функцию в плагине, которая реализует первые два пункта из списка выше.
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;
}
Вы можете адаптировать её для работы с третьим пунктом, используя сниппет от 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;
}
Просто добавьте эти две функции в ваш файл functions.php
и используйте их в цикле следующим образом:
<?php while (have_posts()) : the_post(); ?>
<?php if ($img_src = find_img_src($post)) : ?>
<img src="<?php echo $img_src; ?>" />
<?php endif; ?>
<?php endwhile; ?>

Тема предназначена для коммерческой продажи, поэтому я не хочу говорить конечному пользователю, что ему нужно устанавливать плагин, но спасибо.

код выглядит абсолютно безопасным. как вы сказали, у вас нет изображений прикрепленных к записи.
Попробуйте перейти в панель управления медиафайлами и прикрепить изображение к этой записи.
Либо можно просканировать содержимое записи с помощью регулярного выражения для поиска изображений в ней.

У меня неправильное понимание того, что именно означает "прикреплённый"? ... В посте ЕСТЬ изображение ... разве оно не прикрепляется, когда вы нажимаете 'добавить в пост'?

Я понимаю, что это очень старый вопрос, но оставляю свой ответ здесь, поскольку самый популярный ответ не подходит для новичков в PHP.
preg_match — не лучший подход для парсинга HTML в PHP, так как preg_match предназначен для регулярных выражений, а HTML не является регулярным выражением.
Вместо этого мы можем использовать DOM.
function firstImg($html){
$dom = new DOMDocument;
$dom->loadHTML($html);
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
return $image->getAttribute('src');
}
return false;
}
Использование DOM действительно удобно, так как позволяет делать больше вещей, чем просто получение первой картинки, и это правильный способ парсинга HTML.
Хотел бы я дать ответ с использованием функций WordPress (функций из CODEX и ядра) для получения первой картинки, но это как раз проблема, с которой я сейчас разбираюсь.
Это не универсальное решение!
Учитывайте случай оптимизации размера изображений. В таком случае вы не можете просто использовать этот код, так как запись может содержать изображения любого размера.

Этот код работает у меня:
function get_first_image( $post_id ) {
$attach = get_children( array(
'post_parent' => $post_id, // ID родительской записи
'post_type' => 'attachment', // Тип записи - вложение
'post_mime_type' => 'image', // Только изображения
'order' => 'DESC', // Сортировка по убыванию
'numberposts' => 1 // Количество возвращаемых записей
) );
if( is_array( $attach ) && is_object( current( $attach ) ) ) {
return current( $attach )->guid; // Возвращаем URL первого изображения
}
}

Если вы пытаетесь найти ID вложения (attachment post ID) с помощью функции attachment_url_to_postid, когда находите изображение в контенте, вы можете не найти этот ID, если найденное изображение является масштабированной версией исходного.
- attachment_url_to_postid может найти cats.jpg
- attachment_url_to_postid может не найти cats-800x600.jpg
Если вас не беспокоят схожие названия изображений, вы можете заменить "-800x600.jpg" с помощью 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,
);
Также вы можете вручную выполнить поиск ID вложения в базе данных, если вас беспокоят вводящие в заблуждение названия файлов (например, cats-800x600.jpg может быть уменьшенной версией старого изображения кота, а текущий файл cats.jpg на самом деле содержит изображение гуся).
