Because they do different things and source their data from different places.
$_GET
is for URL parameters, values passed via HTTP GET. get_query_var
is for fetching the query variables of the main post query aka the WP_Query
object. Query variables and GET values are not the same thing.
Query variables usually get their values either from query objects, e.g. the parameters and arguments passed to new WP_Query
or get_posts
. Another place they can come from are rewrite rules. This may be where confusion is coming from as query variables can be set using URL parameters, but this does not mean that all URL parameters are query values. Query values can only have certain values.
Should you use get_query_var
to fetch URL parameters/GET values?
No, you should not, that’s not what that function is for.
Instead use standard PHP methods such as filter_input
or $_GET
Notes on Query Variables
- Query variables have a whitelist, so
p
is a valid name for a query variable, butbanana
is not. There is a filter to add these but it’s rarely used.- It’s main use is when writing custom rewrite rules in order to pass information along, For example lets say I had a plugin to redirect to stack exchange answers that had
/?stackanswer=417665
and I wanted a pretty URL e.g./tomsanswers/417665
where417665
is a stack exchange ID, I’d add a rewrite rule with a regex to map that toindex.php?stackanswer=match[1]
, and I’ll then look to see if thestackanswer
query variable has a value, but I’d need to addstackanswer
to the list of allowed query variables or it’ll be stripped out. In this sitaution$_GET['stackanswer']
would not exist - you can set query variables on any page via URL/GET variables because ugly permalinks take the form
index.php?queryvar=value
, and pretty permalinks are just regexes that turn pretty URLs into ugly ones. Note that with pretty permalinks those ugly URLs are purely hypothetical and internal, no redirects are happening, and no server mapping happens. It’s not the same as doing it in an Apache/Nginx config, the URL hasn’t actually changed. This is why you can add?s=searchterm
to any archive in WP to search just that archive rather than the entire site.
- It’s main use is when writing custom rewrite rules in order to pass information along, For example lets say I had a plugin to redirect to stack exchange answers that had
- Query variables, or query arguments can be changed but you must do this before the query runs. An action is provided for this named
pre_get_posts
that will provide the query in question as a function argument.- Similar actions exist for terms/comments/users e.g.
pre_get_users
- these run for all queries, not just the main query, and not just the frontend
- You can’t use this action from a theme template if you want to modify the main query because it’s too late and would require a small amount of time travel
- If you have
query_posts
ornew WP_Query
at the top of every template, switching it to instead usepre_get_posts
can provide huge performance boosts, and avoid lots of common errors, e.g. pagination problems- this also fixes RSS feeds not showing the right posts, 404’s when your custom template has 10 pages but the original query only has 6 pages of content and the user requests page 7, etc etc
- Similar actions exist for terms/comments/users e.g.