Reason of this behavior is pretty simple. First of all you have to know that get_posts
uses WP_Query
to get posts.
So let’s look at WP_Query implementation. On line 1998 of query.php you can find:
if ( $q['posts_per_page'] == -1 ) {
$q['nopaging'] = true;
Then on line 2544 of query.php you find:
if ( empty($q['nopaging']) && !$this->is_singular ) {
$page = absint($q['paged']);
if ( !$page )
$page = 1;
if ( empty($q['offset']) ) {
$pgstrt = ($page - 1) * $q['posts_per_page'] . ', ';
} else { // we're ignoring $page and using 'offset'
$q['offset'] = absint($q['offset']);
$pgstrt = $q['offset'] . ', ';
}
$limits="LIMIT " . $pgstrt . $q['posts_per_page'];
}
It’s the only part where LIMIT for posts is added. And, as you can see, it is added only if nopaging
is not set. So if posts_per_page
is set to -1, then paging part of SQL query is not added.
So what can you do to work it around? You can set numberofposts
to some big positive number.