Virtual page with Rewirte Api without Custom Post Type

Hi @helgi,

Because Blade templates aren’t PHP, you can’t include them directly. They need to be compiled by the templating engine first, which converts them to PHP. That PHP is the equivalent of what you would have written if you wrote the template without using Blade.

If you look up a little in filters.php you can see how this is done:

The template() function is used to compile the Blade template file specified in $template to PHP, passing the $data to it. The output of that PHP is then echod, giving the output that’s sent to the browser for that template.

Here’s an example of how you could create a virtual page using the template() function. You should be able to adapt this to your specifics.

You may find that WordPress treats your virtual page as a 404 since there is no matching entity in the database. To prevent that, you can return a fake post object as shown below. This also allows you to customize the title used in your site’s meta tags.

In filters.php or wherever you like:

/**
 * Add /virtual/ endpoint permalink
 * Must be appended to an existing URL structure
 * You would replace this with your rewrite rule code.
 */
add_action('init', function () {
    add_rewrite_endpoint('virtual', EP_PERMALINK);
});

/**
 * Load the virtual page's template
 * Any additional logic, data prep, etc., can be run or called from here before rendering the template
 */
add_action('template_redirect', function () {
    global $wp_query;

    // bail if the virtual endpoint was not called
    // modify this to check for whatever will identify your virtual page request (i.e., your query var)
    if (!isset($wp_query->query_vars['virtual'])) {
        return;
    }

    $template = locate_template(["views/partials/virtual.blade.php"]);

    if ($template) {
        // customize the passed array if you need to send data to your template; omit if not
        echo template($template, [
            'title' => 'Virtual Page',
            'description' => 'This is how you might render a virtual page.',
        ]);
        die();
    }
});

/**
 * Prevent 404 and customize page title, etc.
 */
add_filter('the_posts', function (array $posts, \WP_Query $query) {
    // modify this to check for whatever will identify your virtual page request (i.e., your query var)
    if (!isset($query->query_vars['virtual'])) {
        return $posts;
    }

    // Returning a fake post bypasses WP's 404 logic
    $title = 'Virtual Page';
    $post = [
        'ID'             => -100,
        'post_title'     => $title,
        'post_name'      => sanitize_title($title),
        'post_content'   => '',
        'post_excerpt'   => '',
        'post_parent'    => 0,
        'menu_order'     => 0,
        'post_type'      => 'page',
        'post_status'    => 'publish',
        'comment_status' => 'closed',
        'ping_status'    => 'closed',
        'comment_count'  => 0,
        'post_password'  => '',
        'to_ping'        => '',
        'pinged'         => '',
        'guid'           => home_url($query->getUrl()),
        'post_date'      => current_time('mysql'),
        'post_date_gmt'  => current_time('mysql', 1),
        'post_author'    => 0,
        'is_virtual'     => true,
        'filter'         => 'raw'
    ];

    return [
        new \WP_Post((object) $post)
    ];
}, 10, 2);

Then your template (views/partials/virtual.blade.php in this case) can be whatever you need, e.g.:

@extends('layouts.app')

@section('content')
  <h1>{{ $title }}</h1>

  <p>
    {{ $description }}
  </p>
@endsection

Resources:

https://metabox.io/how-to-create-a-virtual-page-in-wordpress/

https://coderwall.com/p/fwea7g/create-wordpress-virtual-page-on-the-fly

https://gist.github.com/gmazzap/1efe17a8cb573e19c086

https://wordpress.stackexchange.com/questions/139071/plugin-generated-virtual-pages

https://barn2.co.uk/create-fake-wordpress-post-fly/

6 Likes