I am trying to add a custom URL structure to a WordPress based website.
for example:
example.com/machines //list all machines in a table
example.com/machines?some=params //list filtered machines in a table
example.com/machines/1 //show single machine
The data will come from an external api i have already developed, via curl.
I cannot import the data into a custom post type as it is normalized over many tables, the business logic is complicated and the api is used by other devices anyway.
I have looked at the docs for add_rewrite_rule, but the second parameter has me stumped:
$redirect
(string) (required) The URL you would like to actually fetch
Well I don't have a url to fetch, I want to run a function, that will act as a simple router - take the url parts, call the external api and return a template with the correct data.
Calling the API will be simple, but how i actually route the url to the function, and how I then load a template (utilizing existing WordPress header.php and footer.php) has me stumped.
After much googling and reading a few good resources, I have found the solution.
Step 1: Use add_rewrite_endpoint
to create a base url that will be mapped to a query variable:
add_action( 'init', function(){
add_rewrite_endpoint( 'machines', EP_ROOT );
} );
Step 2: Visit the permalinks settings page and click "Save Changes" to flush the rewrite rules.
Step 3: Hook into the action 'template_redirect'
to actually do something when the url is hit:
add_action( 'template_redirect', function() {
if ( $machinesUrl = get_query_var( 'machines' ) ) {
// var_dump($machinesUrl, $_GET);
// $machinesURl contains the url part after example.com/machines
// e.g. if url is example.com/machines/some/thing/else
// then $machinesUrl == 'some/thing/else'
// and params can be retrieved via $_GET
// after parsing url and calling api, it's just a matter of loading a template:
locate_template( 'singe-machine.php', TRUE, TRUE );
// then stop processing
die();
}
});
Step 4: The only other thing to do is handle a hit to a url with no further parts to it e.g. example.com/machines
.
It turns out that at some point within WordPress's guts, the empty string gets evaluated to false and thus skipped, so the final step is to hook into the filter 'request'
and set a default value:
add_filter( 'request', function( $vars = [] ) {
if ( isset( $vars['machines'] ) && empty( $vars['machines'] ) ) {
$vars['machines'] = 'default';
}
return $vars;
});
This can easily be improved by wrapping it all in a class(es). The url parsing and template loading logic can be passed to a basic router, even a rudimentary MVC setup, loading routes from a file etc, but the above is the starting point.
A simplier solution is to just create a new template redirect.
So assuming you loading example.com/custom-url
/**
* Process the requests that comes to custom url.
*/
function process_request() {
// Check if we're on the correct url
global $wp;
$current_slug = add_query_arg( array(), $wp->request );
if($current_slug !== 'custom-url') {
return false;
}
// Check if it's a valid request.
$nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
if ( ! wp_verify_nonce( $nonce, 'NONCE_KEY')) {
die( __( 'Security check', 'textdomain' ) );
}
// Do your stuff here
//
die('Process completed' );
}
add_action( 'template_redirect', 'process_request', 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With