Как вставить ссылки из wp_links в цикл?
Я хочу создать цикл, в котором 2 или 3 элемента из моего блогролла будут вставлены следующим образом:
<loop>
<post1>
<post2>
<blogroll1>
<post3>
<blogroll3>
</loop>
Я буду использовать изображения и отрывки для цикла, и цель - чтобы ссылки wp_links
отображались ТОЧНО как wp_posts
, поэтому если бы я мог как-то вставить ссылки в переменную $post
и перебирать их КАК БУДТО они являются записями, это было бы отлично.
Получить ссылки через get_bookmarks
легко, но как заставить WP думать, что это $posts
и как вставить их в объект $post
?

Я пробовал что-то похожее (ну, немного другое, я пытался создать временную шкалу, где посты и комментарии отображались бы вместе)...
Объединение этих двух массивов — непростая задача, потому что объект поста имеет совершенно другие свойства по сравнению с объектом ссылки. Если вы хотите это сделать, вам придется использовать array_map
для массива, возвращаемого функцией get_bookmarks
, чтобы привести каждый из этих объектов к структуре объекта $post; затем объединить оба массива и, наконец, отсортировать их с помощью своей собственной функции сравнения. Много головной боли за очень небольшую выгоду.
Если вы только начинаете работать с этим, почему бы не сделать ваши ссылки пользовательским типом записи (custom post type), чтобы можно было объединять ссылки и посты в одном запросе?
Или еще лучше — если вы можете работать с разработкой версии 3.1, сделайте ваши ссылки форматом поста! В этом случае вообще не придется возиться с запросом, и все заработает сразу.
Примечание: изначально я разместил этот код в отдельном ответе. По рекомендации Яна объединяю ответы в один, чтобы было понятнее.
Ладно, это действительно криво, и я повторяю, что не рекомендую так делать, но если уж очень нужно, вот пример:
$links = get_bookmarks('show_updated=true');
/* Сопоставляем свойства ссылки со структурой объекта поста */
$linkposts = array_map( 'link2postobj', $links );
function link2postobj( $obj ) {
$post_object = array(
'post_name' => $obj->link_name,
'post_content' => '<a href="'.$obj->link_href.'" >'.
$obj->link_name.'</a><p>'.
$obj->link_description.'</p>', // "контент"
'post_author' => $obj->link_owner,
'post_date' => $obj->link_updated,
'post_status' => 'link', // просто метка, что это ссылка
'guid' => $obj->link_href );
return (object)$post_object;
}
/* Объединяем ссылки с постами из запроса */
global $wp_query;
$posts = array_merge( $wp_query->posts, $linkposts );
/* Сортируем вместе по вашей функции (здесь используется link_updated для объединения в шкале времени.
Учтите, что link_updated — ненадежное свойство. */
usort( $posts, 'sortbydate' );
function sortbydate( $a, $b ) {
return ( strtotime($a->post_date) > strtotime($b->post_date) );
}
/* Теперь просто проходим по временной шкале */
foreach ( $posts as $post ) :
if ( 'link' == $post->post_status ) {
// шаблон для ссылок здесь
} else {
setup_postdata( $post );
// шаблон для обычных постов здесь
}
endforeach;
Помимо других проблем, я заметил, что поле link_updated
не очень надежно (многие ссылки в моей базе возвращали 0 в качестве значения). Так что, скорее всего, вам нужно будет изучить свои данные и придумать другую функцию для сортировки ссылок и постов.
Но серьезно, подумайте о переходе на передовые технологии и переносе всех ссылок в посты с форматом "link". Думаю, для вашей задачи это гораздо логичнее, и время, затраченное на создание скрипта для преобразования ссылок в посты, окупится с лихвой по сравнению с поддержкой такого костыльного решения.

То, что вы сказали выше, в основном совпадает с тем, что я пытаюсь сделать, за исключением того, что я использовал array_splice для добавления новых ссылок "posts" в существующую переменную $post

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

Пожалуйста, да. Я работаю с существующей БД, и они уже используют свою текущую структуру ссылок, так что я не могу выйти за её рамки.

Вы можете использовать обычный цикл WordPress (без усложнений) и функцию get_bookmarks($args) для получения нужных ссылок.
Примерно так:
$i = 1;
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
//ваши записи здесь
if ($i&1) echo 'список ссылок '.$i;//список ссылок 2, 4 и т.д.
$i++;
<?php endwhile; endif; ?>

Спасибо всем. Вот решение, к которому я в итоге пришел. Вместо того чтобы возиться с самим циклом, я решил подключиться к хуку the_post
с функцией, которая воссоздает разметку цикла, используя данные из $links
.
<?php
global $links;
global $links_count;
$links = get_bookmarks("limit=5");
function dg_archive_insert_links(){
global $post;
if (!is_singular()){
add_action('the_post', 'dg_insert_links');
}
}
add_action('wp', 'dg_archive_insert_links');
function dg_insert_links(){
global $wp_query;
global $links_count;
global $links;
if ( ($wp_query->current_post % 3) == 0 && ($wp_query->current_post > 0) && $links[$links_count]->link_url):
?>
<div class="post type-post hentry">
<h2><a href="<?php echo $links[$links_count]->link_url; ?>" rel="bookmark" title='Нажмите, чтобы прочитать: "<?php echo $links[$links_count]->link_name; ?>"'><?php echo $links[$links_count]->link_name; ?></a></h2>
<?php if ($links[$links_count]->link_description): ?><div class="entry-summary"><?php echo $links[$links_count]->link_description; ?></div><?php endif; ?>
<?php if ($links[$links_count]->link_image && $links[$links_count]->link_description): ?>
<a href="<?php echo $links[$links_count]->link_url; ?>" rel="bookmark" title="<?php echo $links[$links_count]->link_description; ?>" class="post_thumbnail" ><img src="<?php echo $links[$links_count]->link_image; ?>" width="150px" alt="<?php echo $links[$links_count]->link_description; ?>" /> </a>
<?php endif; ?>
</div>
<?php
$links_count++;
endif;
}
Нет необходимости создавать новую переменную для подсчета, так как она уже существует в $wp_query->current_post
.
