Strange side effect of a PHP post query code in Wordpress - php

Why this code in functions.php has this strange side effect of switching the menu to the mobile version in not-home pages in wordpress?
function my_blog_category( $query ) {
if ( $query->is_home() && !is_front_page() || is_archive()) {
$query->set( 'cat', '6');
}
}
add_action( 'pre_get_posts', 'my_blog_category' );
This code should affect only posts in blog and archive page so why's that?

The reason it's not working is because you were asking:
If $query->is_home() && !is_front_page()
Or, is_archive()
Group your conditional expression using brackets.
function my_blog_category( $query ) {
if ( $query->is_home() && ( !is_front_page() || is_archive() ) ) {
$query->set( 'cat', '6');
}
}
add_action( 'pre_get_posts', 'my_blog_category' );
Now you're asking:
If $query->is_home()
And, if !is_front_page() or is_archive()

Related

Wordpress pre_get_posts breaks all pages

I know this should be obvious but my function is making all pages use index.php except the page using archive-project.php and the category pages for that post-type.
function change_project_loop( $query ) {
// Make sure this only fires when we want it too
if( !is_admin() || is_home() || is_page_template( 'archive-projects.php' ) && $query->is_main_query() && $query->is_tax('projectcat') ) {
// If so, modify the order variables
$query->set('meta_key', 'status' );
$meta_query[] = array(
array(
'key' => 'status',
'value' => 'assigned',
'compare' => 'NOT LIKE',
),
);
$query->set('meta_query',array( $meta_query ) );
}
}
add_action('pre_get_posts', 'change_project_loop', 9999);
I only want this to run on the home page, the page that uses archive-projects.php and the taxonomy pages for "projectcat".
You have incorrect if conditions.
if ( !is_admin() || is_home() || is_page_template( 'archive-projects.php' ) && $query->is_main_query() && $query->is_tax('projectcat') ) {
// ...
}
This means it is not admin page OR is home OR in template archive-projects.php
AND $query->is_main_query() AND $query->is_tax('projectcat') is true.
The !is_admin() is always be true if you use in theme/template for front pages even is_home() and is_page_template() is false but one of your condition is met.
And if all $query conditions are true then it means this if condition will always work on your front pages.
To fix this, remove !is_admin() because it is unnecessary, is_home() and is_page_template() will work for front pages already.
Also wrap your OR condition with bracket to group them.
if( (is_home() || is_page_template( 'archive-projects.php' )) && $query->is_main_query() && $query->is_tax('projectcat') ) {
// ...
}
Now, this means (it must be in home OR using specific template) - one of these conditions must be true.
AND all $query conditions must be true.

How do I delete the old Custom Post Type permalink after rewriting the URL to exclude the slug?

I have a Custom Post Type called Book, and the link is: mywebsite.com/book/mybookname
I want to change this so that the link is mywebsite.com/mybookname.
I have added the following code to change the link and it works as expected:
function books_theme_remove_slug( $post_link, $post, $leavename ) {
if ( 'book' != $post->post_type || 'publish' != $post->post_status ) {
return $post_link;
}
$post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );
return $post_link;
}
add_filter( 'post_type_link', 'books_theme_remove_slug', 10, 3 );
function books_theme_parse_request( $query ) {
if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array( 'post', 'book', 'page' ) );
}
}
add_action( 'pre_get_posts', 'books_theme_parse_request' );
The problem is that the old link(mywebsite.com/book/mybookname) is still working. I'd like to make that link go to a 404 page without breaking the current links.
I tried the following but it breaks everything:
function books_theme_parse_request( $query ) {
if(isset($query->query['post_type']) && $query->query['post_type'] == 'book'){
global $wp_query;
$wp_query->set_404();
status_header( 404 );
get_template_part( 404 ); exit();
}
if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array( 'post', 'book', 'page' ) );
}
}
add_action( 'pre_get_posts', 'books_theme_parse_request' );
How do I delete old url?
This shouldn't be happening in the first place, so you shouldn't try to fix it programmatically - instead you should fix it at source. Try to identify the cause and fix it. Otherwise you could introduce other issues down the line.
Some possible solutions, depending on the cause:
Flush your Rewrite Cache
Wordpress doesn't write redirections into the .htaccess, it uses rewrite rules to parse the url and find a match for the redirection.
It means that if you don't refresh your rewrite rules, the old links still work.
Ref: SarahCoding's answer to 'Remove Old Permalinks?'
How to do it: Re-saving your permalinks will flush the rewrite rules, but there if that doesn't work there are Three Ways to Flush the Rewrite Cache in WordPress
Clear your Cache
If you have an Caching plugins installed, they will need to be cleared. Some security plugins also use caching e.g. Securi. It could also just be cached in your browser.
How to do it: See How to Clear Your Cache in WordPress
Delete old WP permalinks
When you update a slug, the old permalinks are still stored in the database. This could cause issues if you want to use a slug that you had previously used for example.
How to do it: The old permalinks are stored in the table postmeta with the meta_key of _wp_old_slug. To clear all of the old slugs, run this query in your WP database:
DELETE FROM wp_postmeta WHERE meta_key = '_wp_old_slug';
Ref Mark Dave Tumanda's answer to 'Remove Old Permalinks?'
Check Redirection Plugins
If you are using any redirection plugins, check the redirection rules in case there is anything there that is clashing with your new urls.
Based on your comment all you need then is to know if the url contains /book ... see below for the added snip-it:
function books_theme_parse_request( $query ) {
global $wp;
$current_url = home_url( $wp->request );
if (strpos($current_url, "/book" == false)) { return; }
if(isset($query->query['post_type']) && $query->query['post_type'] == 'book'){
global $wp_query;
$wp_query->set_404();
status_header( 404 );
get_template_part( 404 ); exit();
}
if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array( 'post', 'book', 'page' ) );
}
}
add_action( 'pre_get_posts', 'books_theme_parse_request' );
As people have mentioned reference
A Warning About Admin Usage
This filter can also be used to affect admin screen queries. Be sure to check if your modification is affecting your post edit screens. For example, just checking is_main_query() and is_post_type_archive('movie') will also change the query for the edit.php?post_type=movie admin screen, unless you also check for !is_admin()

wp redirect to same page in php

on my website I restricted 3 pages (IDs 861, 869, 931) to all non-registered users but I'm having a problem, those pages will always redirect the user to the login page (even if I'm logged in), what I'm doing wrong?
Here's the code, a little help would be greatly apprecieated
add_action( 'template_redirect', 'redirect_to_specific_page' );
function redirect_to_specific_page() {
if ( is_single('861') or is_single('869') or is_single(931) &&
!is_user_logged_in() ) {
wp_redirect( 'http://mywebsite.com/login', 301 );
exit;
}
}
It looks like you need to scope your order of operations a little better. You first need to check if you're on any of those pages, and THEN if the user is logged in. So:
add_action( 'template_redirect', 'redirect_to_specific_page' );
function redirect_to_specific_page() {
if ( (is_single('861') || is_single('869') || is_single(931)) &&
!is_user_logged_in() ) {
if ( !is_user_logged_in() ) {
wp_redirect( 'http://mywebsite.com/login', 301 );
exit;
}
}
Better yet, you could pass those IDs into the same is_single() call:
if ( is_single(array(861, 869, 931)) && !is_user_logged_in() ) {
if ( !is_user_logged_in() ) {
wp_redirect( 'http://mywebsite.com/login', 301 );
exit;
}
}
By the way, why are you using is_single() if you're checking pages? Are these custom post types? You might be better off with is_page().
if ( is_single('861') or is_single('869') or is_single(931) &&
!is_user_logged_in() )
Shouldn't it be more like?
if ( (is_single('861') || is_single('869') || is_single(931)) &&
!is_user_logged_in() )
C# conditional AND (&&) OR (||) precedence
In C# && apparently has higher precedence than ||. Better put it into () just in case.
http://php.net/manual/en/language.operators.precedence.php
I mean, maybe PHP too.
You if conditional is incorrect. Try this code
add_action( 'template_redirect', 'redirect_to_specific_page' );
function redirect_to_specific_page() {
if ( is_single('861') || is_single('869') || is_single(931) ) {
if ( !is_user_logged_in() ) {
wp_redirect( 'http://mywebsite.com/login', 301 );
exit;
}
}

Add categories to default WordPress search

I have a search form containing select fields. The first two are populated with custom taxonomies and the third with the default wordpress categories. When using the first two only for a query it works fine. When I use the third( the categories), the search query just ignores the field and comes up with the same results. How can I fix this?
I've used these functions to make them work:
function ftiaxnospiti_filter_search($query) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_search ) {
$query->set( 'post_type', array('post', 'seller') );
}
return $query;
};
add_action('pre_get_posts', 'ftiaxnospiti_filter_search');
function ftiaxnospiti_add_custom_types_to_tax( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
// Get all your post types
$post_types = array( 'post', 'seller' );
$query->set( 'post_type', $post_types );
}
return $query;
}
add_action( 'pre_get_posts', 'ftiaxnospiti_add_custom_types_to_tax' );

Change default order of pages in WordPress Admin / Backend

I am trying to change the default sorting order of the pages in my WordPress backend. I know this can easily be done by clicking on the tab "Title", "Date" or "ID" but those are merely one-time settings and I need a global = default solution.
I went ahead and tried using this function which to me makes perfect sense but it just doesn't work with WordPress 4.2.3 :-(
function set_post_order_in_admin( $wp_query ) {
global $pagenow;
if ( is_admin() && 'edit.php' == $pagenow && !isset($_GET['orderby'])) {
$wp_query->set( 'orderby', 'title' );
$wp_query->set( 'order', 'asc' );
}
}
add_filter('pre_get_posts', 'set_post_order_in_admin', 5 );
Any idea why this is not working any more? How can I achieve that?
Thanks + regards,
Henning
Just change order "ASC" to "DESC" in your own code, it will work perfectly. Or copy and paste below mentioned code into your functions.php :
function set_post_order_in_admin( $wp_query ) {
global $pagenow;
if ( is_admin() && 'edit.php' == $pagenow && !isset($_GET['orderby'])) {
$wp_query->set( 'orderby', 'title' );
$wp_query->set( 'order', 'DESC' );
}
}
add_filter('pre_get_posts', 'set_post_order_in_admin', 5 );
Use this snippet of code :
function set_post_order_in_admin( $wp_query ) {
global $pagenow;
if ( is_admin() && 'edit.php' == $pagenow && !isset($_GET['orderby'])) {
$wp_query->set( 'orderby', 'title' );
$wp_query->set( 'order', 'DSC' );
}
}
add_filter('pre_get_posts', 'set_post_order_in_admin' );

Categories