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
pis a valid name for a query variable, butbananais 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=417665and I wanted a pretty URL e.g./tomsanswers/417665where417665is 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 thestackanswerquery variable has a value, but I’d need to addstackanswerto 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=searchtermto 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_poststhat 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_postsornew WP_Queryat the top of every template, switching it to instead usepre_get_postscan 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.