If your plugin have to completely control the output of the page, i.e. not taking into account the active theme or other installed plugins, than you can simply prevent WordPress handle that url.
For example:
add_action('init', function() {
if (trim(add_query_arg(array()), "https://wordpress.stackexchange.com/") === 'book-search') {
require_once plugin_dir_path( __FILE__ ) . "pages/book-search.php";
exit();
}
});
add_query_arg()
is used above to obtain the current viewed url relative to home url.
What I do is require a specific php file from plugin folder if the viewed url is the one you’re looking for.
That file, pages/book-search.php
should contain all the code to ouput the content of the page.
If your aim is to integrate some content with active theme, than things ar more complex.
Look at this answer that explain how to create virtual pages with plugins.
In your case, using code in that answer you have to play with setContent()
function to change what is shown.
An alternative is to use shortcodes, but in that case you can’t choose the url.