Further upgrade: just built a class to place in functions.php or maybe in a plugin.
I did that mainly because I want almost always have sticky posts, probably in more loops per page. So got a lot of duplication. Therefore here is a basic class, that certainly can be exapanded/perfectioned some way, but for my needs just works:
class Posts_With_Sticky{
public $max_items_amount;
public $normal_items_amount;
public $category;
public $sticky_ids;
public $sticky_query;
public $normal_query;
function __construct($category = null, $max_items_amount = 5){
$this->max_items_amount = $max_items_amount;
$this->sticky_ids = get_option('sticky_posts');
$this->category = $category;
$this->get_query();
}
public function get_query(){
//sticky query
if(count($this->sticky_ids) != 0){
$this->sticky_query = new WP_Query();
$this->sticky_query->query(array(
'category_name' => $this->category,
'posts_per_page' => $this->max_items_amount,
'post__in' => $this->sticky_ids
));
}
//check amount of stikies and room for normals
if(isset($this->sticky_query)){
$stikies = count($this->sticky_query->posts);
if($stikies == $this->max_items_amount) return;
else $this->normal_items_amount = $this->max_items_amount - $stikies;
}
//normal posts query
$this->normal_query = new WP_Query();
$this->normal_query->query(array(
'category_name' => $this->category,
'posts_per_page' => $this->normal_items_amount,
'post__not_in' => $this->sticky_ids
));
}//end get_query
public function render_posts($sticky_loop_function,
$normal_loop_function = "",
$before_markup = "",
$after_markup = ""){
if(!$sticky_loop_function) return;
//shortcut
$sticky_setted = isset($this->sticky_query);
$normal_setted = isset($this->normal_query);
if(!$sticky_setted && !$normal_setted) return;
$sticky_loop = $sticky_loop_function;
$normal_loop = ($normal_loop_function !== "") ? $normal_loop_function : $sticky_loop_function;
echo $before_markup;
if($sticky_setted) $sticky_loop($this->sticky_query);
if($normal_setted) $normal_loop($this->normal_query);
echo $after_markup;
}//end render_posts
}//end Posts_With_Sticky
Then, in the html page, I’ll write a different loop function for every section, and then pass it to render_posts().
Something like this:
<?php
//html output function
function write_soon_items($query){
while($query->have_posts()){
$query->the_post();
$date = get_the_date('d.m.Y');
$title = get_the_title();
$excerpt = get_the_excerpt();
$link = get_permalink();
echo <<< ITEM_BLOCK
<article>
<h4>
$date - $title
</h4>
<p>
<a href="https://wordpress.stackexchange.com/questions/36280/$link" title="$title">$excerpt</a>
</p>
<div class="float-reset"></div>
</article>
ITEM_BLOCK;
}
}//end write_sub_items
$soon_posts = new Posts_With_Sticky('coming-soon');
$soon_posts->render_posts('write_soon_items')
?>
So, every time I need a loop that honours sticky posts of a certain category, I just make another Posts_With_Sticky instance and then call its render_posts() method passing a custom output loop function.
Note that you can pass render_posts() a function for stickies, a function for normals (if you don’t, the first one will be used), a ‘before_markup’ and a ‘after_markup’.
Hope it helps someone.
Bye