How to add categories for pages only? - php

I have added this function in my functions.php file to show category option for wordpress pages. It works fine.
function support_category_for_pages() {
// Add category support to pages
register_taxonomy_for_object_type('category', 'page');
}
add_action( 'init', 'support_category_for_pages' );
But is it possible to show/limit some categories for pages only(they must not appear under posts) ?
I hope I am writing this correctly. Basically the requirement is to keep different categories for post & pages and they should not appear in each other's category option.

There are two approaches i can think off. I am not sure how you want it to work regarding the archive page and search page so second approach may not work for you.
First solution creating templates:
For example category-news.php
Inside you can modify the query specificly for this category
$args = array(
'post_type' => 'posts'
//add more arguments if needed
);
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
// Do Stuff
} // end while
} // endif
// Reset Post Data
wp_reset_postdata();
Second solution using pre_get_posts:
function wp50_exclude_post_type_pages() {
//in the array you can add ids, slugs or names
if ( is_category( array( 9, 'cat2', 'Category 3' )) && $query->is_main_query() ) {
//here we tell the query to show posts type only
$query->set( 'post_type', 'posts' );
return $query;
}
}
add_action( 'pre_get_posts', 'wp50_exclude_post_type_pages');

Related

How to sort/order get_next_post_link in Wordpress?

I'm using get_next_post_link for next and previous posts but I don't understand the order.
I would like to sort posts by acf value (a number) and order by ascending.
My code:
<?php
if ( get_next_post_link() ) {
next_post_link();
}
?>
My acf field: 'position' and its unique value so I can sort it.
Try somethink like this
https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters
https://themeisle.com/blog/re-order-wordpress-blog-posts/
$wp_query = WP_Query('orderby' => 'title', 'order' => 'DESC');
while ($wp_query->have_posts()) {
$wp_query->the_post();
get_next_post_link(); //this should work
//if not here is alternative
$next_post = get_next_post(); // or $wp_query->next_post();
echo get_permalink( $next_post->ID );
}
If you have any other logic to get the next post you will need to use wp_query to fetch it and then you can use get_permalink($id)
Or you can overwrite the default action which fetches posts in WordPress.
// # template-functions.php
function order_posts_by_title( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query-set( 'orderby', 'title' );
$query-set( 'order', 'ASC' );
}
}
add_action( 'pre_get_posts', 'order_posts_by_title' );
// now the get_posts(); and get_next_post(), get_next_post_link() will be ordered by custom query

How to fix Wordpress pagination (page not found after 8th page)

I am having trouble with Wordpress pagination. I have a custom archive page displaying custom post types from the specific category. I want to use pagination and display 12 posts per page. My problem is that pagination works correctly but only up to the 8th page. After that I am being presented with "Page not found".
I am using theme built-in function to display page navigation (1, 2... 10, 11). It correctly shows 11 pages in total, but they seem not to work after the 8th page.
$taxonomy = 'product_cat';
$term_id = get_queried_object()->term_id;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'product',
'paged' => $paged,
'posts_per_page' => '12',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $term_id
)
)
);
<?php $wp_query = new WP_query( $args ); ?>
<?php if( $wp_query->have_posts() ): ?>
<?php while( $wp_query->have_posts() ): ?>
<?php $wp_query->the_post(); ?>
//post content
<?php endwhile; ?>
<?php endif; ?>
<?php s7upf_paging_nav();?>
<?php wp_reset_postdata(); ?>
#edit
When I go to a different category page which should have 12 pages they work correctly up to the 9th page.
If I go to the one that has 2 pages, only the first one works.
I tried updaing permalinks. Setting posts per page to 12 in wordpress settings.
When i change posts per page in my query args to -1 it correctly shows all the posts on one page.
When manually setting the number of a page to display ('paged' => '11') it also displays correct page with correct posts.
You are using the wrong query. On page you are creating your own query instead of the actual query the page already did.
This will also be better for performance.
Step 1. Check what is in the normal query.
At the top of taxonomy-product_cat.php
global $wp_query;
var_dump( $wp_query->query_vars );
That probably fits mostly.
Step 2. Do the normal loop
Remove all your query stuff (maybe keep a backup of the $args for the next step)
example: Replace
<?php if( $wp_query->have_posts() ): ?>
with
<?php if( have_posts() ): ?>
And so on.
Step 3. Edit the main query
We are going to use the hook pre_get_posts
add_action('pre_get_posts', 'so_53315648');
function so_53315648( WP_Query $wp_query ){
// only check this on the main query
if (! $wp_query->is_main_query() ){
return;
}
// only check this on the product_cat taxonomy
if ( ! $wp_query->is_tax('product_cat')) {
return;
}
// maybe do some more checks?
$wp_query->query_vars['posts_per_page'] = 12;
// Is this really needed??
//$wp_query->query_vars['posts_type'] = 'product';
// tweak the query the way you like.
}
As you can see $wp_query->query_vars should pretty much be the same $args. But do not overwrite it. This might break other stuff.
Of course I could not test your specific site. But the answer should be inside the pre_get_posts hook. And tweaking the main query instead of doing a extra separate one.
Test, also check the var_dump of step 1 that your changes are coming through.
The checks at the top are to stop other pages from being affected, maybe you need more?
Let me know.

Does get_query_var('cat') fetches child Category Posts as well?

In category.php I am using custom query to get posts:
<?php
$cat_id = get_query_var('cat');
$args = array(
'posts_per_page' => 2,
'orderby' => 'date',
'cat' => $cat_id
);
query_posts($args);
// the Loop
get_template_part('aa_HomeLoopMain');
?>
I am using get_query_var('cat') to get category post of current category and I think this would only give Category Posts of category id with $cat_id but not it's child category posts?
You are doing it wrong. Never ever use query_posts, it breaks the main query object, reruns queries and is slow which all negatively impacts on performance and SEO and other functions that relies on the main query. Also, if this is your main query, you should not be using a custom query at all, you should be using pre_get_posts to alter the main query before it executes.
get_query_var(cat) only returns the queried category, not its children.
You should remove the query_posts part and add the following to your functions.php
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_category()
) {
$q->set( 'posts_per_page', 6 );
}
});
EDIT
You should query a total of 6 posts, I have updated my as such. You can try the following with your loop
if ( have_posts() ) {
while( have_posts() ) {
the_post();
if ( 1 <= $wp_query->current_post ) {
// Add your markup for column one, this will display 2 posts
} else {
// Add your markup for column two, this will display 4 posts
}
}
}
EDIT 2
For some reason I cannot post comments from my mobile, but I think you are using the code wrongly. I have updated my code to show the loop. It does work. If it does not, something else is breaking your page like query_posts

Wordpress: have template output all posts with category x where x is assigned dynamically

I am trying to create a series of pages that display the posts within a single category. To do this I use the following PHP code:
<?php
$args = array( 'category' => '$CATEGORY', 'numberposts' => 10000000000);
$myposts = get_posts( $args );
foreach($myposts as $post) :
setup_postdata($post);
?>
My problem is that the $CATEGORY does not seem to contain the category as a string. I have tried using both %s and $id but as I have not declared that it is the category id I am wanting it fails to work. The resulting output has been either an error or all the posts regardless of category.
What argument will convey the category string?
Below is a page illustrating the problem. This is a category page, meaning it should hold all the necessary info. If it was working it would only show the topmost post as it is the only post en site that has the "Press Release" category. Worth mentioning that I have another page just like it called "Dokument" and it displays the press release.
Page: http://www.skinwellness.se/category/pressrelease/
EDIT
I did not notice this before, but it seems that you are using the bundled theme twentythirteen. Simply delete the category.php from your child theme. If you have made changes to the parent theme directly, you should get a fresh copy of the theme, and create a child theme with all your modifications. Never make changes to a theme that you did not write. When such themes update, all you changes will be gone forever
You should then just need the pre_get_posts section in your child theme's functions.php to make everyone work
ORIGINAL ANSWER
You problem is purely your custom loop. As explained in the linked post, you should not be using custom queries in place of the main query on any type of archive page or on your home page
To solve this, revert back to the default loop. This is all you should have. No get_posts or foreach loops
if( have_posts() ) {
while( have_posts() ) {
the_post();
// Add your loop elements here like the_title() and the_content()
}
}
This should fix the problem that when you visit a category page, only the category been viewed will be viewed, no posts from other categories will be shown
Now, if you need to change anything on your category page, use pre_get_posts to do that. Make use of the is_category() conditional tag to target your category pages only. You can also target a specific category with this tag
Say for instance, you need to change the posts per page on you category page, as your case, display all posts with no pagination, you can do this in your functions.php
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
If you need to for example change the order to ASC and need to order posts by author, you can do this
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
$query->set( 'order', 'ASC' );
$query->set( 'orderby', 'author' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
You should see WP_Query for all available parameters to use

Display pages and posts in archive

I have many categories, but for clearity I will do an example with only two:
News that contains many posts
Products that contains many pages (I've added this feature in functions.php)
I want that archive.php displays:
the posts when the user choose the category News
the pages when the user choose the category Products
At the moment Wordpress by deafult shows only posts and not pages.
I know that this is possible by adding a simple function in functions.php but I can't find it.
EDIT: For another project with custom post type "Books" I used this code
function query_post_type($query) {
$post_types = get_post_types();
if ( is_category() || is_tag()) {
$post_type = get_query_var('books');
if ( $post_type ) {
$post_type = $post_type;
} else {
$post_type = $post_types;
}
$query->set( 'post_type', $post_type );
return $query;
}
}
add_filter('pre_get_posts', 'query_post_type');
Is there something like that for my case?
You can query for solely pages in the WP Query.
PHP:
$args = array(
'post_type' => 'page'
);
$query = new WP_Query( $args );
This will return all pages in your database, and zero posts. Vice versa, you could have 'post_type' => 'post' to query all posts, but that's the default behaviour of the WP Query.
For more documentation on this, check out the WP Query reference in the Wordpress Codex.

Categories