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.
Related
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;
}
I was trying to find out how wordpress process each request and returns the result. I found wp() function calls $wp->main() which in turn calls $this->query_posts(); and which calls $wp_the_query->query($this->query_vars) function in query.php file. The query() function calls return $this->get_posts(); and return the result.
My question is didn't see any any variables receiving this returned value so why this function has return, even though the wordpress works if I remove the return from the code. so what is the purpose of this return, (I guess this code saves the contents (posts) to $this->posts variable). btw I am using wp 3.6
I believe this answer may provide what you're looking for:
https://wordpress.stackexchange.com/a/1755
Specifically this image (which I did not create myself):
The use of return is related to php (also used in other languages) not only WordPress. When execution reaches a return statement, the function stops and returns that value without processing any more of the function. A return with no value returns null and If there is no return keyword at the end of a function then, in this case too, a null value get returned.
Using a return statement at the end of a method/function is a good coding practice, it just returns the execution control back to the point, from where it started and it also Prevents Code Injection in PHP include files. Also, check this.
Short Answer:
There are other functions that make use of the returned value, mostly in themes and plugins, but also in WP core. examples are given below.
Long Answer:
In wordpress the WP_Query::query() method is used for getting posts from the DB.
This is done by providing certain criteria for selection, ie: the query_vars.
Based on which the posts are retrieved and made available.
now, in the case mentioned by you what is of important is the call stack, ie the path used to call the function.
ie:
wp() --->
[WP->main()]-->
WP->query_posts() {here the query is
called on the global
wp_query Object}
-->WP_Query->query()
In WP->main(), the parse_request methond is called, which creates the query_vars from the REQUEST_URI.
so whatever post is fectched depends on the requested pages URL. i.e the criteria for selection is provided by the requested page's url.
And since the query method is called on the global wp_query object, there is no need to return it.
This forms the main path, ie: global wp query, and request uri query vars.
But in cases, like in themes, plugin, when you need to fetch additional posts. you will create a new wp query object, and use the query method.
eg: to fetch all posts by 'john'. in these situation the value returned by the query method is used.
$wpquery = new Wp_query();
posts = $wpquery->query("author_name=john");
Some functions that uses it:
wp_nav_menu_item_post_type_meta_box /wp-admin/includes/nav-menu.php
wp_link_query /wp-includes/class-wp-editor.php
I am trying to override a plugin that creates SEO titles in wordpress. The filter does the job but I need to dynamically create the titles. So I create the title then pass it to an anonymous function. I could have another function that creates the titles put this will definitely be cleaner...
This works
function seo_function(){
add_filter('wpseo_title', function(){
return 'test seo title';
});
}
This doesn't
function seo_function(){
//create title above
$title="test seo title";
add_filter('wpseo_title', function($title){
return $title;
});
}
Thanks for any help
Joe
Without using an anonymous function example - this works, but I still can't pass a variable, I'd have to duplicate code to create the title.
function seo_function(){
//create title above
$title="test seo title";
add_filter('wpseo_title', 'seo_title');
}
function seo_title(){
$title="test";
return $title;
}
You pass variables into the closure scope with the use keyword:
$new_title = "test seo title";
add_filter( 'wpseo_title', function( $arg ) use ( $new_title ) {
return $new_title;
});
The argument in function($arg) will be sent by the apply_filters() call, eg the other plugin, not by your code.
See also: Passing a parameter to filter and action functions
The params you can provide to custom filters are defined by the filter and the way filters work in Wordpress. See http://codex.wordpress.org/Plugin_API/Filter_Reference for documentation about filters in Wordpress.
Also you're not the first attempting this so maybe this will help you (as I don't have a Wordpress install to test it with):
http://wordpress.org/support/topic/change-the-title-dynamically
If you can't get it working I would suggest using the forum of the plugin you're using or contacting the developer directly.
I am writing plugin that uses init() action and the_content() filter.
In init I would like to do some cookie checks and set some variables based on result (lets say $mycookieset = 1). In the_content filter I would like to modify article based on $mycookieset variable.
How to pass $mycookieset variable in safe way between these two hooks? I would prefer not to use sessions. It also should be multiple users safe (hundreds of people browsing the web same time).
Any ideas? Thanks
You can add the filter inside a function that is hooked into init, and use the cookie value as a variable in the $function_to_add parameter:
add_action( 'init', 'my_init_function' );
function my_init_function(){
// do the cookie stuff
add_filter( 'the_content', 'my_variable_cookie_func_' . $mycookieset );
}
Of course, you should have an appropriate callback function for each possible cookie value.
I'm making a tutorialsystem with Codeigniter, but I'm a bit stuck with using subcategories for my tutorials.
The URL-structure is like this: /tutorials/test/123/this-is-a-tutorial
tutorials is the controller
test is a shortcode for the category
123 is the tutorial ID (used in the SQL query)
this-is-a-tutorial is just a slug to prettify the URL
What I do is passing the category as a first parameter and the ID as a second parameter to my controller function:
public function tutorial($category = NULL, $tutorial_id = NULL);
Now, if I want subcategories (unlimited depth), like: /tutorials/test/test2/123/another-tutorial. How would I implement this?
Thanks!
For reading infinite arguments, you have at least two useful tools:
func_get_args()
The URI class
So in your controller:
Pop the last segment/argument (this is your slug, not needed)
Assume the last argument is the tutorial ID
Assume the rest are categories
Something like this:
public function tutorial()
{
$args = func_get_args();
// ...or use $this->uri->segment_array()
$slug = array_pop($args);
$tutorial_id = array_pop($args); // Might want to make sure this is a digit
// $args are your categories in order
// Your code here
}
The rest of the code and the validation depends on what specifically you want to do with the arguments.
If you need variable categories you could use the URI class: $this->uri->uri_to_assoc(n)
Another option you may want to consider is CodeIgniter's controller function remapping functionality which you can use to override the default behaviour. You would be able to define a single function inside a controller that would handle all the calls to that controller and have the remaining URI parameters passed in as an array. You could then do whatever you want with them.
See here for the docs reference on the matter.