Ask your WordPress questions! Pay money and get answers fast! (more info)

Checkbox to add Custom Post Type to Main WordPress Loop & Feed WordPress

  • SOLVED

I have a problem with WordPress Custom Post Types that I can't seem to wrap my head around.

I would like to have a category or a custom taxonomy checkbox on my custom post type, and if this one is checked, then display the post in the WordPress main loop and in the WordPress feed.

Note: I don't want to display all posts from my custom post type in the main loop and feed, only the ones that are checked (or unchecked if that's easier).

I want it to be sorted the same way as all other posts, by date, so it shouldn't be a featured post or anything like that, it should behave just like the other, "normal", posts.

This is my code so far:

// register taxonomy

add_action( 'init', 'create_my_taxonomies', 0 );

function create_my_taxonomies() {
register_taxonomy( 'firstpage', array( 'usp_post' ),
array( 'hierarchical' => true, 'label' => 'Show up on first page', 'query_var' => true, 'rewrite' => true ) );
}


// Modify main loop

function limit_posts_per_home_page( $query )
{
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

$first_page_limit = 11;
$limit = get_option('posts_per_page');

if (is_front_page())
{
if ($paged == 1)
{
$limit = $first_page_limit;
}
else
{
$offset = $first_page_limit + (($paged - 2) * $limit);
set_query_var('offset', $offset);
}
}

set_query_var('posts_per_archive_page', $limit);
set_query_var('posts_per_page', $limit);

if ( ( is_front_page() && $query->is_main_query() ) || is_feed() ) {

$args = array(
'post_type' => 'usp_post',
'tax_query' => array(
array(
'taxonomy' => 'firstpage',
'field' => 'slug', //slug, id, name
'terms' => 'featured',
'operator' => 'IN' //IN, NOT IN
),
)
);


$remove_these = get_posts( $args );


$query->set( 'post_type', array( 'post', 'usp_post' ) );

$query->set( 'post__not_in', $remove_these );

}

if ($query->is_author) {
set_query_var( 'post_type', array( 'post', 'usp_post' ) );
}
}
add_filter('pre_get_posts', 'limit_posts_per_home_page');


The function I'm struggling with begins on this line:

if ( ( is_front_page() && $query->is_main_query() ) || is_feed() ) {

The rest of it are for modifying the number of posts that should show up on page 1 of the main loop.

Thanks!

// Jens.

Answers (2)

2015-01-02

Dbranes answers:

Hi, did you try this:

$args = array(
'post_type' => 'usp_post',
'fields' => 'ids',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'firstpage',
'field' => 'slug',
'terms' => array( 'featured' ),
'operator' => 'NOT IN'
),
)
);


where we must use <em>'fields' => 'ids'</em>, to return only an array of posts ids for the <em>post__not_in</em> parameter, as suggested by @Kyle in the previous questions.

Here we use <em>'posts_per_page' => -1</em>, to exclude all of the custom posts that are not in the <em>featured</em> term.

<em>ps:</em> But this might not be practical for huge number of posts ids, because there's a limit for the text size of the SQL command.

<strong>Method 2:</strong>

Here's another idea how to inject, only the custom posts that are in the "featured" term of the "firstpage" taxonomy, into the main loop and the feed.

This could be a replacement for your <em>if</em> sentence in the <em>pre_get_posts</em> callback.


/**
* Inject posts of the custom post type 'usp_post', that are attached to the 'featured' term of the
* 'firstpage' taxonomy, into the main loop and the feed.
*
* @see http://www.wpquestions.com/question/showChronoLoggedIn/id/10370
*/

add_filter( 'pre_get_posts', 'wpq_pre_get_posts', 99 );

function wpq_pre_get_posts( $query )
{
if ( ( is_front_page() && $query->is_main_query() ) || is_feed() )
{
$query->set( 'post_type', array( 'post' ) );
add_filter( 'posts_where', 'wpq_posts_where', PHP_INT_MAX );
}
}

function wpq_posts_where( $where )
{
global $wpdb;
remove_filter( current_filter(), __FUNCTION__, PHP_INT_MAX );

// Modify this to your needs for the injected posts:
$taxonomy = 'firstpage'; // <-- This should be the taxonomy.
$term_slug = 'featured'; // <-- This should be the term slug.
$cpt = 'usp_post'; // <-- This should be the custom post type.

// Get the term info for the term_taxonomy_id:
$term = get_term_by( 'slug', $term_slug, $taxonomy );

// Modify the SQL query:
if( ! is_wp_error( $term ) )
{
$where .= " OR {$wpdb->posts}.ID IN (
SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ( {$term->term_taxonomy_id} ) )
AND {$wpdb->posts}.post_status = 'publish'
AND {$wpdb->posts}.post_type = '{$cpt}' ";
}
return $where;
}


Jens Filipsson comments:

Hey! Thanks!

Method 2 looks like the way to go, it's more efficient right? It's only the custom posts that's associated with the firstpage taxonomy, that's correct.

I'm not sure how I implement it in my existent code though, not totally sure what to replace?

// Jens.


Dbranes comments:

I think it should be better for large number of post ids.

You can for example try the code directly first and remove your previous code, just to test.

I updated the code to support if other custom post type are attached to the same custom taxonomy.

Here's the gist you can try out:

[[LINK href="https://gist.github.com/dbranes/bf5c38fd5e82153446ac"]]https://gist.github.com/dbranes/bf5c38fd5e82153446ac[[/LINK]]


Jens Filipsson comments:

Looks awesome! But, when I try to implement it, I'm not getting any results unfortunately.

BTW, this is how i register the taxonomy. Something I should change there?

add_action( 'init', 'create_my_taxonomies', 0 );

function create_my_taxonomies() {
register_taxonomy( 'firstpage', array('usp_post'),
array( 'hierarchical' => true, 'label' => 'Ocheckad pÄ förstasidan', 'query_var' => true, 'rewrite' => true ) );
}


The id for featured is 1486, so I have updated your code with the following:

$term_id = 1486;

// Jens.


Jens Filipsson comments:

To be clear: The normal posts shows up, but not the custom post type.


Dbranes comments:

I just tested it and it worked on my install. I can see the injected posts from the 'featured' terms

Is the code running on your install, can you for example see this:

echo "I'm now in wpq_posts_where";


when you add this line to the <em>wpq_posts_where()</em> function.

Are you sure <em>is_front_page()</em> is working for you?


Jens Filipsson comments:

Could it be the term id that is wrong?

When I go into admin and edit the "category", the url looks like this:

edit-tags.php?action=edit&taxonomy=firstpage&tag_ID=1486&post_type=usp_post

Is this not the term id? 1486?


Dbranes comments:

yes, that's how I found the correct term_id.

Maybe you can share the SQL query, both before and after the custom code?


Jens Filipsson comments:

I'm using the exact code you posted in github, the query is just the normal wordpress loop, so no changes there.

This line showed up, but over the header of the page:

echo "I'm now in wpq_posts_where";


Dbranes comments:

ok, so the echo message is showing up, that's good ;-)

I'm assuming the featured ups_post posts are published.

Here's the SQL query for the main loop, before and after:

<strong>Before:</strong>

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_date DESC
LIMIT 0, 11;


<strong>After:</strong>

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
OR wp_posts.ID IN (
SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN ( 24 ) )
AND wp_posts.post_status = 'publish'
AND wp_posts.post_type = 'ups_post'
ORDER BY wp_posts.post_date DESC
LIMIT 0, 11;


Jens Filipsson comments:

I'm not sure what to do with this? Should I add it to functions.php as well?


Dbranes comments:

Maybe you could try

SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN ( 24 )

in PHPMyAdmin, just to see what it returns.

ps: maybe I could take a look at your install and try it out?


Dbranes comments:

ps: I meant this one:

SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN ( 1486 )

if your table prefix is wp_


Jens Filipsson comments:

It returned:

object_id
310


When I ran an sql query.

At least that's what I think it returned. I'm still developing locally, so you can't take a look unfortunately..


Jens Filipsson comments:

Btw: I'm using a hierarchical taxonomy (checkbox, like a category), not a tag-like one. If that makes a difference.


Dbranes comments:

ok, at least we got something ;-)

Your taxonomy setup should be ok. I'm using the same setup on my install to check your code, where it works OK.

So the post with post id 310, should show up in your loop.

Next you could try:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID, wp_posts.post_title, wp_posts.post_type
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
OR wp_posts.ID IN (
SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN ( 24 ) )
AND wp_posts.post_status = 'publish'
AND wp_posts.post_type = 'usp_post'
ORDER BY wp_posts.post_date DESC


and try to locate the post with id 310.


Dbranes comments:

ps: replace 24 with 1486 ;-) (that's the value I'm testing on my install, that I forget sometimes to change when I paste code)


Jens Filipsson comments:

The post with id 310 is a normal post unfortunately..


Jens Filipsson comments:

No posts with usp_post shows up when sorting on post type


Dbranes comments:

hmm, that's strange

You should check your wp_terms table, and verify that the "featured" term has term_id=1486


Dbranes comments:

ps:

you could also use the post id of a <em>featured</em> <em>usp_post</em> post,
and then match that number with <em>object_id</em> in the <em>wp_term_relationships</em> table
and check the corresponding <em>term_taxonomy_id</em> value.


Jens Filipsson comments:

I'm not really sure how to do that... Sorry, this is a bit advanced for me :)


Jens Filipsson comments:

Ok, I exported the tables:

From wp_terms:

(1486, 'Featured', 'featured', 0),

From wp_term_taxonomy:

(1550, 1486, 'firstpage', '', 0, 8),


Dbranes comments:

ok so it looks like your term_taxonomy_id is 1550, try that instead.


Dbranes comments:

I updated the code here and for the gist:

[[LINK href="https://gist.github.com/dbranes/bf5c38fd5e82153446ac"]]https://gist.github.com/dbranes/bf5c38fd5e82153446ac[[/LINK]]

Now you only need to modify this part:

// Modify this to your needs for the injected posts:
$taxonomy = 'firstpage'; // <-- This should be the taxonomy.
$term_slug = 'featured'; // <-- This should be the term slug.
$cpt = 'usp_post'; // <-- This should be the custom post type.


and the <em>term_taxonomy_id</em> should be automatically found for you.

I think the problem was that I told you to use the term_id, but we need of course the term_taxonomy_id, but these two were always equal on my install, but obviously not on your install ;-)

So I hope this works now for you ;-)


Jens Filipsson comments:

Works like a charm! Thanks a lot my friend! You're the best!

2015-01-03

Arnav Joy answers:

Hello Jens ,

As you mentioned in your question that you are struggling with this

if ( ( is_front_page() && $query->is_main_query() ) || is_feed() ) {

so every other code of your is working ?


Jens Filipsson comments:

No, the part from there and down :) But I think Dbranes might be on to something, any idea how I could make that code work?


Jens Filipsson comments:

Or maybe you have another solution?