How can I alter the WordPress query without "overriding" it? - wordpress

I have a search results page that I want to limit results on i.e. posts_per_page. However if I use query_posts('posts_per_page=6') I lose the original query.
How do I alter my query without damaging the original?

You can use the pre_get_posts filter to access/alter the $query object. In functions.php:
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
if ($query->is_search) {
$query->set('posts_per_page', 6);
}
}
}
add_action('pre_get_posts', 'search_filter');

Never ever use query_posts, it breaks the main query object ($wp_query) and all functionality that relies on the main query object. It also breaks page functionality. Apart from that, it is slow and reruns queries. query_posts should be on top of your most evil list together with functions like create_function(), eval() and extract().
If you need to alter the main query, always use pre_get_posts to do so. Never change the main query with a custom one, it might solve one problem, but it creates many other.
The following will work
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_search()
) {
$q->set( 'posts_per_page', 6 );
}
});

Related

how to remove excerpt on category archive page in genesis framework?

I am trying to remove the excerpt ( content ) from the category archive page so only the title shown on the page, not the content.
I am currently trying the code below with no luck?
does anybody have any suggestions?
add_action ( 'genesis_before_entry' , 'designody_remove_entry_content_archives' );
function designody_remove_entry_content_archives() {
if (in_category('5')) {
remove_action( 'genesis_entry_content', 'genesis_do_post_content' );
}
}
my second solution... also not working
function replace_content( $output) {
if (is_category('5')) {
return '' ;
}
}
add_filter( 'get_the_excerpt', 'replace_content' );
I don't have a fully satisfactory Genesis-specific solution, and I'd be curious to know what StudioPress itself says, but I do have WordPress solutions.
First, to use the Genesis hook and a condition, you need to wrap it in a function:
To quote the Codex: "Warning: You can only use conditional query tags after the posts_selection action hook in WordPress (the wp action hook is the first one through which you can use these conditionals). For themes, this means the conditional tag will never work properly if you are using it in the body of functions.php, i.e. outside of a function."
https://codex.wordpress.org/Conditional_Tags
The following works to remove the excerpt on the specified category archive page:
add_action( 'loop_start', 'remove_content_on_category_pages' ) ;
function remove_content_on_category_pages() {
if ( is_category( '5' ) ) {
remove_action( 'genesis_entry_content', 'genesis_do_post_content' );
}
}
However, the in_category() conditional - which should help with entry content when it appears in other archives (categories, blog, etc.) - doesn't seem to work.
In order to get the desired results as I understand them - no post content, in this implementation "the excerpt", for this category on any type of archive page, but preserving it for individual posts - you can revert to the trusty the_content filter, but note that the the_content can be a tricky and powerful tool subject to unexpected secondary effects. That said, on a vanilla Genesis installation, the following tests out:
add_filter( 'the_content', 'test_gen_content' ) ;
function test_gen_content( $content ) {
/**
apply to all secondary queries don't apply if single page or post, or in
admin, otherwise obliterate - can use is_single() instead of is_singular()
if only posts are at issue
**/
if ( ! is_singular() && ! is_admin() && in_category( '157' ) ) {
return '' ;
}
return $content ;
}
I must say, however, that, given the peculiarities and complications of the Genesis framework, and the peculiarity of the request, out there in the wild I'd be very tempted to use a CSS kludge, shaped to requirements - at least failing direct instruction or intervention from a Genesis maven or StudioPress itself. Whether you needed to refine the CSS further to suit your particular installation, I can't say, but it might be a lot easier, actually, then sorting out the PHP even with the correct hooks etc.
//substitute appropriate category slug for "development-forums"
.home .category-development-forums .entry-content,
.blog .category-development-forums .entry-content,
.archive .category-development-forums .entry-content
{
display: none;
}

Calling a plugin's function from functions.php

I am writing some code in the functions.php of my theme, now what I need to do is execute a function from inside another plugin and im wondering if its possible.
The plugin is wooevents pro and the function I need is as follows:
function order_contains_tickets( $order ) {
// Function code is in here
}
So my code will look something like this
if ( order_contains_tickets( $order ) ) {
// Execute code
}
Technically, the exact code you have would work, but it's also unsafe. In the event that the wooevents pro plugin were ever disabled, the code you added would be referencing a function that no longer exists. Thus, a better option would be to add a check to ensure that the function exists like so...
if( function_exists( 'order_contains_tickets' ) ) {
if( order_contains_tickets( $order ) ){
// Execute code
}
}
It should also be noted that this is dependent on the load order of the two functions. The wooevents pro function must be loaded prior to your function for it to work.

Wordpress: Trying to use update_option_optionname

I am trying to add a tracking mechanism to my wordpress plugin. And I want to use the WP cron mechanism. So I have an options page and when users save all options I want to use a hook to remove or add the tracking to the wp cron depending of the admins choice.
But right now I am stuck.
I have:
register_setting ( 'my-settings-group', 'myplugin_tracking');
add_action ( 'update_option_myplugin_tracking', 'myplugin_schedule_tracking' );
function myplugin_schedule_tracking($old_value, $new_value)
{
echo "Setting is updated!";
echo $old_value;
}
But this does not seem to work. I also used:
add_filter ( 'update_option_myplugin_tracking', 'myplugin_schedule_tracking' );
The option is saved in a form that posts to the options.php if that matters.
What am I doing wrong? Hope somebody can help out as I cannot find much information about doing something upon updating an option!
Thank you.
Okay this seems to work after all.
register_setting ( 'my-settings-group', 'myplugin_tracking');
function myplugin_schedule_tracking($old_value, $new_value)
{
if ($old_value !== $new_value)
{
if ($new_value == '')
{
wp_clear_scheduled_hook( 'myplugin_tracking' );
}
elseif ($new_value == 'on' && $current_schedule == FALSE)
{
wp_schedule_event( time(), 'hourly', 'myplugin_tracking' );
}
}
}
add_filter ( 'update_option_myplugin_tracking', 'myplugin_schedule_tracking', 10, 2);
add_action ( 'myplugin_tracking', 'myplugin_tracking' );
In the function myplugin_tracking you do whatever you have to do to track.
My problem was that I did not see the echo on the screen but it did appear to work after all.
Perhaps not the best code but it may be helpful for others :-)

new Wp_Query() or pre_get_posts() to view ALL posts for custom post type?

I have an archive-template file that shows all posts for custom post type personnel (called archive-personnel.php):
This is the begining of the file...
<?php
get_header();
//Show all posts for this custom posttype (personnel)
$args = array( 'post_type' => 'personnel', 'posts_per_page' => -1 );
$personnel_query = new WP_Query( $args );
if (have_posts()) : while ($personnel_query->have_posts()) : $personnel_query->the_post();
This is working, but I know that I can use pre_get_posts() as well. But with pre_get_posts() - filter you have to check if it affects admin etc.
So my question is: Does it really matter which alternative I use or is just a matter of preference/taste?
Main query versus secondary queries:
Does it really matter which alternative I use or is just a matter of
preference/taste?
Yes , there is a real difference:
1) pre_get_posts is modifying the main query (or all queries) versus adding a secondary query using WP_Query.
2) If you want paging to work on the secondary query, you usually have to make modifications to the main query.
By using the pre_get_posts hook you can modify all queries that are instances of WP_Query(), including the main query, which is an instance of WP_Query() and is present for every page request.
Remember that get_posts() is a wrapper for WP_Query() and the filter is active when the suppress_filters attribute is set as FALSE.
When using pre_get_posts you usually want to target specific queries by using some conditional tags. Here are few examples, you can use:
a) is_main_query() to determine if the current query is the main query.
b) ! is_admin() to prevent modifications to queries in the backend.
c) is_post_type_archive() to target the post type archives.
When you add your custom WP_Query(), then you are adding extra queries in addition to the main query.
I usually go with the pre_get_posts action if I can, instead of adding a secondary query.
Example:
If you want to modify the main query, for the archive of the custom post type personnel, you can try:
add_action( 'pre_get_posts', function( $query ){
if ( ! is_admin() && $query->is_main_query() ) {
if ( is_post_type_archive( 'personnel' ) ) {
$query->set('posts_per_page', -1 );
}
}
});
This is untested but you get the idea ;-)
Further reading:
Hopefully the following links can give you more information regarding the difference:
https://wordpress.stackexchange.com/questions/50761/when-to-use-wp-query-query-posts-and-pre-get-posts/
https://wordpress.stackexchange.com/questions/76553/should-i-use-pre-get-posts-or-wp-query
https://wordpress.stackexchange.com/questions/1753/when-should-you-use-wp-query-vs-query-posts-vs-get-posts
https://wordpress.stackexchange.com/questions/81695/what-is-main-query

Exclude specific post from WP-feed

I know that you can generate a feed using urls like: ?cat=3&feed=rss2
And you can switch it around to exclude the category 3 by putting a subtract sign in front: ?cat=-3&feed=rss2
But, it doesn't look like you can do the same for posts? I'm using the JW video Player and have loaded the related plugin. The related plugin can take an rss-feed (media rss) as the parameter so it can link to other videos/wordpress posts that are related.
My problem is that currently this means that the active video also appears in the related videos feed.
What would be the best solution for solving this problem? I aim to create my own rss feed generator in the future, but for now I just want to keep it simple and use the generated feeds that wordpress creates. Is there a simple way to add support for an url parameter named post for example? It could then take post=-7 to exclude post with id 7 from displaying in the feed.
Or is there better solutions for this?
You can use a function
function exclude_category($query){
if ( $query->is_home || $query->is_feed || $query->is_archive ) {
$query->set('cat', '-1');
}
return $query;
}
add_filter('pre_get_posts', 'exclude_category');
see'a
Instead of explaining the mechanisem - there are many plugins just for that ..
One that I know is :
StelthPubish
Edit I
I do not know about the URL - but you can try use the
function ok9_feed_filter($query) {
if ( !$query->is_admin && $query->is_feed) {
$query->set('post__not_in', array(15, 6) ); // page /post id
}
return $query;
}
add_filter( 'pre_get_posts', 'ok9_exclude_filter' );
or this
function ok9_feed_exlude($where, $wp_query = NULL) {
global $wpdb;
if ( !$wp_query )
global $wp_query;
if ($wp_query->is_feed) {
// exclude post id
$where .= " AND $wpdb->posts.ID NOT IN (15, 6)";
}
return $where;
}
add_filter( 'posts_where','ok9_feed_exlude', 1, 2 );
If you do not want to use a fixed id in the function - you can always add a custom field in the posts you want to exclude , and use that in the query ..

Resources