80

I am having trouble trying to pass an extra variable in the url to my WordPress installation.

For example /news?c=123

For some reason, it works only on the website root www.example.com?c=123 but it does not work if the url contains any more information www.example.com/news?c=123. I have the following code in my functions.php file in the theme directory.

if (isset($_GET['c'])) 
{
  setcookie("cCookie", $_GET['c']); 
}

if (isset($_SERVER['HTTP_REFERER']))
{
  setcookie("rCookie", $_SERVER['HTTP_REFERER']);
}

Any Ideas?

Maxime
  • 8,645
  • 5
  • 50
  • 53
Chuck D
  • 1,718
  • 4
  • 19
  • 26
  • [This question on wordpress.stackexchange explains the process](https://wordpress.stackexchange.com/questions/48487/how-to-retrieve-get-variables-from-rewritten-urls) – admcfajn Nov 08 '18 at 19:05

9 Answers9

126

To make the round trip "The WordPress Way" on the "front-end" (doesn't work in the context of wp-admin), you need to use 3 WordPress functions:

  • add_query_arg() - to create the URL with your new query variable ('c' in your example)
  • the query_vars filter - to modify the list of public query variables that WordPress knows about (this only works on the front-end, because the WP Query is not used on the back end - wp-admin - so this will also not be available in admin-ajax)
  • get_query_var() - to retrieve the value of your custom query variable passed in your URL.

Note: there's no need to even touch the superglobals ($_GET) if you do it this way.

Example

On the page where you need to create the link / set the query variable:

if it's a link back to this page, just adding the query variable

<a href="<?php echo esc_url( add_query_arg( 'c', $my_value_for_c ) )?>">

if it's a link to some other page

<a href="<?php echo esc_url( 
    add_query_arg( 'c', $my_value_for_c, site_url( '/some_other_page/' ) ) 
    )?>">

In your functions.php, or some plugin file or custom class (front-end only):

function add_custom_query_var( $vars ){
  $vars[] = "c";
  return $vars;
}
add_filter( 'query_vars', 'add_custom_query_var' );

On the page / function where you wish to retrieve and work with the query var set in your URL:

$my_c = get_query_var( 'c' );

On the Back End (wp-admin)

On the back end we don't ever run wp(), so the main WP Query does not get run. As a result, there are no query vars and the query_vars hook is not run.

In this case, you'll need to revert to the more standard approach of examining your $_GET superglobal. The best way to do this is probably:

$my_c = filter_input( INPUT_GET, "c", FILTER_SANITIZE_STRING );

though in a pinch you could do the tried and true

$my_c = isset( $_GET['c'] ) ? $_GET['c'] : "";

or some variant thereof.

wittich
  • 2,079
  • 2
  • 27
  • 50
Tom Auger
  • 19,421
  • 22
  • 81
  • 104
  • 1
    Also you need to use `esc_url` with `add_query_arg` https://developer.wordpress.org/reference/functions/add_query_arg/ – electroid Sep 26 '15 at 17:14
  • This is a great answer, been looking ages for a simple example like this, thanks – Sam Skirrow Nov 30 '15 at 09:56
  • Great description! Does wordpress strip out unregistered query arguments (it seems to be for me, but I'm not totally sure what's going on)? it would be good to state this if so, to alleviate confusion :) – Damon Apr 06 '16 at 00:47
  • It doesn't take them out of $_GET, but they're not available to your rewrite rules or within your `$query_vars` – Tom Auger Apr 06 '16 at 13:07
  • @electroid if you're not sure what your variable may contain, then absolutely, especially if it's coming from user input (ie: $_REQUEST) – Tom Auger Apr 06 '16 at 13:08
  • 1
    @electroid modified my answer to reflect your best practice. – Tom Auger May 19 '16 at 19:00
  • Works perfectly, thank you! How would I alter the function to work with multiple values? – Alex Green Mar 03 '17 at 12:27
38

There are quite few solutions to tackle this issue. First you can go for a plugin if you want:

Or code manually, check out this post:

Also check out:

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
17

Since this is a frequently visited post i thought to post my solution in case it helps anyone. In WordPress along with using query vars you can change permalinks too like this

www.example.com?c=123 to www.example.com/c/123

For this you have to add these lines of code in functions.php or your plugin base file.

From shankhan's anwer

add_filter( 'query_vars', 'addnew_query_vars', 10, 1 );
function addnew_query_vars($vars)
{   
    $vars[] = 'c'; // c is the name of variable you want to add       
    return $vars;
}

And additionally this snipped to add custom rewriting rules.

function custom_rewrite_basic() 
{
    add_rewrite_rule('^c/([0-9]+)/?', '?c=$1', 'top');
}
add_action('init', 'custom_rewrite_basic');

For the case where you need to add rewrite rules for a specifc page you can use that page slug to write a rewrite rule for that specific page. Like in the question OP has asked about

www.example.com/news?c=123 to www.example.com/news/123

We can change it to the desired behaviour by adding a little modification to our previous function.

function custom_rewrite_basic() 
{
    add_rewrite_rule('^news/([0-9]+)/?', 'news?c=$1', 'top');
}
add_action('init', 'custom_rewrite_basic');

Hoping that it becomes useful for someone.

Shahbaz A.
  • 4,047
  • 4
  • 34
  • 55
15

add following code in function.php

add_filter( 'query_vars', 'addnew_query_vars', 10, 1 );
function addnew_query_vars($vars)
{   
    $vars[] = 'var1'; // var1 is the name of variable you want to add       
    return $vars;
}

then you will b able to use $_GET['var1']

shankhan
  • 6,343
  • 2
  • 19
  • 22
4
<?php
$edit_post = add_query_arg('c', '123', 'news' );

?>

<a href="<?php echo $edit_post; ?>">Go to New page</a>

You can add any page inplace of "news".

user3777827
  • 344
  • 1
  • 5
  • 16
4

One issue you might run into is is_home() returns true when a registered query_var is present in the home URL. For example, if http://example.com displays a static page instead of the blog, http://example.com/?c=123 will return the blog.

See https://core.trac.wordpress.org/ticket/25143 and https://wordpress.org/support/topic/adding-query-var-makes-front-page-missing/ for more info on this.

What you can do (if you're not attempting to affect the query) is use add_rewrite_endpoint(). It should be run during the init action as it affects the rewrite rules. Eg.

add_action( 'init', 'add_custom_setcookie_rewrite_endpoints' );

function add_custom_setcookie_rewrite_endpoints() {
    //add ?c=123 endpoint with
    //EP_ALL so endpoint is present across all places
    //no effect on the query vars
    add_rewrite_endpoint( 'c', EP_ALL, $query_vars = false );
}

This should give you access to $_GET['c'] when the url contains more information like www.example.com/news?c=123.

Remember to flush your rewrite rules after adding/modifying this.

niall.campbell
  • 409
  • 4
  • 5
3

to add parameter to post urls (to perma-links), i use this:

add_filter( 'post_type_link', 'append_query_string', 10, 2 );
function append_query_string( $url, $post ) 
{
    return add_query_arg('my_pid',$post->ID, $url);
}

output:

http://yoursite.com/pagename?my_pid=12345678

T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 2
    @mwebber the answer was not aimed to give answer "how to detect ? or # in url", but to show a hook to modify the url. However, as you wished, I've updated the answer to comply with your comment. – T.Todua Feb 02 '19 at 18:27
1

This was the only way I could get this to work

add_action('init','add_query_args');
function add_query_args()
{ 
    add_query_arg( 'var1', 'val1' );
}

http://codex.wordpress.org/Function_Reference/add_query_arg

brenjt
  • 15,997
  • 13
  • 77
  • 118
-1

In your case, Just add / after url and then put query arguments. like

www.example.com/news/?c=123 or news/?c=123

instead of

www.example.com/news?c=123 or news?c=123

Vicky P
  • 553
  • 6
  • 12