Trouble passing arguments to WordPress pre_get_posts - php

I need your help! I am having trouble passing arguments to a function using pre_get_posts.
Purpose of passing arguments:
I have a custom taxonony-$taxonomy.php page which I use to list posts related to a particular category within the specified taxonomy. On this page I also retrieve & setup tags assigned to each post from a custom non hierarchical taxonomy and list them as links on the side. I have another taxonomy-$taxonomy.php (for the custom non hierarchical taxonomy mentioned above) setup so when a user chooses a link he/she clicks on a tag it will direct them to this taxonomy page. This is all working fine.
However, here's where I'm having issues. The posts listed on the non hierarchical taxonomy page are those associate to a particular tag but from multiple categories. What I’m trying to achieve is to list posts associates to the tag chosen and from the category previously being viewed. So for example: Lets say the user clicks on category ‘Accounting’, then chooses the tag ‘Creative Services’. All posts listed should not only be associated with ‘Creative Services’ must also be assigned to only the ‘Accounting’ category. This is where I’ve been trying to pass arguments to the function used by pre_get_posts.
How have I tried passing arguments?:
1- Setup globals: This way no arguments have to be past via the function being invoked. It did not work because the timing is off. The globals are not yet set when the action is called. Below is my code with example post_type and taxonomy. Notice $category is the global variable which hold the category within that taxonomy.
// Alter main query on doc_tag taxonomy templates
function only_query_doc_tag_posts( $query ) {
global $category;
if ( is_tax(array('doc_tag')) && !is_admin() ) {
if($query->is_main_query()) {
$query->set( 'post_type', 'post_type' );
$query->set( 'taxonomy', 'taxonomy_array' );
$query->set( 'taxonomy_name', $category ); //global
}
}
}
add_action( 'pre_get_posts', 'only_query_doc_tag_posts' );
Results:
When I view the main query it shows all the changes except the one using the global. If I manually insert the value into the function, instead of using the a global variable then it works. However, I'd like to be able to change this on the fly. Just so you're aware I do get the posts related to the tag but not those only associated to the category indicated by the global (when using the global).
2- do_action:
// Alter main query on doc_tag taxonomy templates
function only_query_doc_tag_posts( $query,
$post_types, //array
$taxonomies, //array
$category //global var
) {
global $category;
if ( is_tax(array('doc_tag')) && !is_admin() ) {
if($query->is_main_query()) {
$query->set( 'post_type', $post_types );
$query->set( 'taxonomy', $taxonomies );
$query->set( 'taxonomy_name', $category ); //global
}
}
}
add_action( 'pre_get_posts', 'only_query_doc_tag_posts', 10, 4 );
Then on the custom non hierarchical taxonomy page template I add the following:
do_action( 'pre_get_post', $post_types, $taxonomies, $category );
I have a feeling my second approach is not technically but I could be wrong, which is why I'm posting it here in hopes that someone can provide some direction. If I missed information that would help you help me please let me know.
Thank you in advance for helping me with this.
FYI: I've read these posts but did not get find a solution. Maybe it's there and I missed it? Please let me know.
Wordpress pre_get_posts and passing arguments
WordPress pre_get_posts not working
wp_query not filtering tax_query correctly in pre_get_posts
Passing arguments with add_action and do_action throwing error 'First argument is expected to be a valid callback'
Wordpress, filter posts if custom query variables are present. (pre_get_posts, add_vars)
Wordpress pre_get_posts category filter removes custom menu items
passing argument using add_action in wordpress!

I think I understand what you try to do.
Long in short - no, you can not do (do_action) by yourself, it is called by wp query parts.
If you try to pass arguments, you need look into [$query->query_vars].
I think a proper solution, for you need, is write a proper url rewrite rules, it can auto pick the taxonomy, and put it into url list, then values can auto show in [$query->query_vars] .
Which is [add_filter('rewrite_rules_array', 'set_url_rule');]
You may also need install plugin [rewrite-rules-inspector] to help you inspect the rewrite status.
Anyway, it could take you an afternoon to find the logical behind it, but then, it all makes sense.
If you just looking for a quick solution, you can inject some code into query_vars, you just need to :
add_filter('query_vars', 'insert_query_vars');
function insert_query_vars( $vars ){
array_push($vars, 'c_type');
array_push($vars, 'c_tax');
array_push($vars, 'c_term');
return $vars;
}

Related

Why i can't access $post datas in my Wordpress single custom post type template?

I'm facing a really strange issue on my Wordpress plugin development :
I made a custom post type who's working perfectly.
I actually have to define my single.php template on the plugin to propose a ready public page.
I found the "single_template" filter who allow me to define my own template and override the default template for my custom post type.
It's actually working good and i can start the integration.
My problem is that i can't access the POST object/datas in this template, i didn't found a lot of similar cases on the web and would appreciate any help to fix this.
Here are some parts of my code :
Filter to define my own template for the single page
function get_teams_single_template( $single_template ) {
global $post;
if ( $post->post_type == 'mt_teams' ) {
$single_template = cdev_mt_directory . 'templates/teams/single-mt_teams.php';
}
return $single_template;
}
add_filter( 'single_template', 'get_teams_single_template' );
The way i'm trying to get my post => $post return null
<?php
include_once '../../../../../wp-load.php';
get_header();
global $post;
var_dump($post);
die();
If i try the wp function get_post(), it also return null..
Thanks a lot
I solved my problem by replacing my global variable which defined the plugin path.
I was using the plugin_dir_url method and had a url include error, so I replaced this method with plugin_dir_path, which resolved all my conflicts.

Use custom meta data in a WC_Product_Query on Woocommerce 3

I used to use the standard wordpress WP_Query to fetch woocommerce products based on meta data. My products are tracks and have many meta columns (like genre, instrument, mood, etc). Using WP_Query I can create a meta_query based on user input from a form, that searches for products that meet the meta requirements. All of this works great.
Now I want to use wp_get_products instead of WP_Query because it is the new way of fetching products and is supposed to be more future-proof than the old way. However, I can't seem to figure out how to pass the meta_query into that function. It was announced on github that wc_get_products would support meta from version 2.8. The only info I can find on this is at the following link: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query (very last paragraph).
I tried passing the meta_query as an array of arrays, each containing 3 key-value pairs for key, value, and compare, just like in WP_Query. I also tried to add meta as Meta: meta-field-name, which is the name of the actual fields, only the name itself without the 'meta' prefix, and some other varieties. None of these methods work though. Can anyone tell me if this 'custom parameter support' only refers to custom parameters other than meta fields, or am I doing something wrong?
To handle product custom meta data in a WC_Product_Query (located in wp_postmeta table), it's quiet simple and works, as explained in the very last paragraph of the related documentation.
But it doesn't handle multiple values and comparison arguments like in a WP_Query, if you don't set them in the function that extend the meta_query.
For a custom product meta key like _volume to handle the volume taken by a product in m3 (cubic meters), the following code will enable that custom meta_key with a specific compare argument "bigger than":
add_filter( 'woocommerce_product_data_store_cpt_get_products_query', 'handling_custom_meta_query_keys', 10, 3 );
function handling_custom_meta_query_keys( $wp_query_args, $query_vars, $data_store_cpt ) {
$meta_key = '_volume'; // The custom meta_key
if ( ! empty( $query_vars[$meta_key] ) ) {
$wp_query_args['meta_query'][] = array(
'key' => $meta_key,
'value' => esc_attr( $query_vars[$meta_key] ),
'compare' => '>', // <=== Here you can set other comparison arguments
);
}
return $wp_query_args;
}
Code goes in function.php file of the active child theme (or active theme).
Now you will just make your query on this custom _volume meta key based on the specific 'compare' argument, to get all products that have a volume bigger than '0.2':
$queried_products = wc_get_products( array( '_volume' => '0.2' ) );
Tested and works.
As you can see, you can continue using a WP_Query as many Woocommerce developers still do or even SQL queries through WordPress WPDB Class…
The announced revolution around this is not going to come soon and I suppose that they will extend WC_Product_Query and WC_Order_query like WP_Query with many more features and possibilities.
You can add this little function to fix it all :
add_filter( 'woocommerce_product_data_store_cpt_get_products_query', static function($wp_query_args, $query_vars, $data_store_cpt){
if ( ! empty( $query_vars['meta_query'] ) ) {$wp_query_args['meta_query'][] = $query_vars['meta_query'];}
return $wp_query_args;
}, 10, 3 );
Now just pass meta_query to the wc_get_products and it supports it :).
They probably should hire me lol.

custom post types link hierarchy

I have to independet custom post types:
course
lesson
So one course can have many lesson and one lesson can be used in many courses. It is a m:n relation.
Now I've content that should be only visible on the lesson page, if it is viewed from a specific course.
Actually the link structure is like that:
Go to course: example.org/my-first-course
I see all lessons, that related to this course
Click on a lesson. Link structure is: example.org/great-lesson
My problem at this stage is, that I don't know from which course the lesson i called.
One thing I can do is to attach the course id as a get parameter to the link:
example.org/great-lesson/?course_id=123
But I would like to have a link structure more like that:
example.org/my-first-course/great-lesson
How can I do this?
.:: UPDATE: SOLUTION ::.
Here is my solution, maybe it'll help someone.
If you use "add_rewrite_rule", don't forget to change the slug (slug-custom-post-type) for your custom post type and the query var (cpt-query-var) of it.
I've tried to use index.php?name=$matches[1], but it will redirect to the custom post type and all other information in the URL will be lost. So it is important to use the custom post type query var instead.
To access the 'course' you have to use the get_query_var function:
echo get_query_var('course', '');
function my_rewrite_rules() {
add_rewrite_rule( '^slug-custom-post-type/([^/]*)/?', 'index.php?cpt-query-var=$matches[1]&course=$matches[2]', 'top' );
}
add_action('init', 'my_rewrite_rules');
function my_query_vars($qvars) {
$qvars[] = 'course';
return $qvars;
}
add_filter( 'query_vars', 'my_query_vars' );
I think you should use,
example.org/great-lesson/my-first-course
instead of using
example.org/my-first-course/great-lesson
as the great-lesson will be static here and the id or slug is dynamic which shows detailed course/lesson.
And to add custom rewrite rule you can use,
function custom_rewrite_basic() {
add_rewrite_rule('^great_lesson/(.*)', 'index.php?page_id=$matches[1]', 'top');
}
add_action('init', 'custom_rewrite_basic');
Then get the slug from url and write code according to it. Read more about add_custom_rule

Get every category in custom post type [Wordpress] [Events Manager]

I am having trouble to get all categories of specifically the plugin Events Manager. What I am trying to achieve is an select field with every category available in Events Manager in a template file. I tried using wordpress functions like get_terms() but couldn't figure out what to use as args.
I am getting my results like this:
$events = EM_Events::get(array('limit'=>0));
foreach( $events as $EM_Event ){
...
}
I appreciate any help
Events manager registers event-categories taxonomy (for categories), and event-tags taxonomy (for tags).
So to get all the terms for a certain category, you can use, as you noted,
$event_terms = get_terms( 'event-categories', array(
'hide_empty' => false,
) );
This should return an array of all the terms for that taxonomy.
Read more here: https://developer.wordpress.org/reference/functions/get_terms/

WordPress get_query_var()

I am busy developing a WordPress application and I need to be able to pass url parameters using WordPress functions. I use add_query_arg() function to add a url parameter. However, when I try to get the passed value in the other page using get_query_var() nothing gets returned. When I used $_GET['var_name'] the values gets returned.
What is the possible cause of this situation? I can successfully add arguments to the url but I am not able to access them.
I managed to get the get_query_var() function to work.
To use the two functions successfully, you need to add the query vars to wordpress's query vars array. Here is a code sample.
function add_query_vars_filter( $vars ){
$vars[] = "query_var_name";
return $vars;
}
//Add custom query vars
add_filter( 'query_vars', 'add_query_vars_filter' );
Now you can use get_query_var() and add_query_arg() as follows:
Add the query var and value
add_query_arg( array('query_var_name' => 'value'), old_url );
Get the query var value
$value = get_query_var('query_var_name');
More information and code samples can be found at the Codex: get_query_var and add_query_arg
To troubleshoot, what variables are being used in the request use following code
global $wp_query;
var_dump($wp_query->query_vars);
If you check out the Codex, you'll see you actually need to do some fiddling to get WP to start reading your query string.
Codex (under Custom Query Vars)
Excerpt:
In order to be able to add and work with your own custom query vars that you append to URLs (eg: "mysite com/some_page/?my_var=foo" - for example using add_query_arg()) you need to add them to the public query variables available to WP_Query. These are built up when WP_Query instantiates, but fortunately are passed through a filter 'query_vars' before they are actually used to populate the $query_vars property of WP_Query.

Categories