Virtual page with Rewirte Api without Custom Post Type

Greetings.

I created a virtual page with Rewrite Api. It is a url linked to a template. I see that it does not work with blade.

The virtual page does not refer to a Custom Post Type, only to a URL and a template file. Blade does not interpret it.

Thanks for the help.

Hey @helgi,

What have you tried? Can you share your code and what’s happening?

2 Likes

In the file app / filter.php I write the following code to create a page or virtual path not associated with any template

/**
 * Create path /propiedades
 */
add_filter('generate_rewrite_rules', function ($wp_rewrite) {

    $wp_rewrite->rules = array_merge(
        ['propiedades/?$' => 'index.php?propiedad=1'],
        $wp_rewrite->rules
    );

    return $wp_rewrite;
});

add_filter('query_vars', function ($query_vars) {
    $query_vars[] = 'propiedad';
    return $query_vars;
});

In the app / setup.php file I write the hook to leave a file propiedades.blade.php

add_action('template_redirect', function () {
    $custom = intval(get_query_var('propiedad'));
    if ($custom) {
        include get_template_directory() . '/views/propiedades.blade.php';
        die;
    }
});

But properties.blade.php does not work with blade. How to make it work?

Thank you

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

Regards @mmirus.

Thanks for the time and the help provided.

In add_rewrite_endpoint (‘virtual’, EP_PERMALINK) EP_PERMALINK did not work and I changed it to EP_ALL. Yes it worked.

After analyzing I did not need an endpoint, so I combined this code in filter.php:

add_filter('generate_rewrite_rules', function ($wp_rewrite) {
$wp_rewrite->rules = array_merge(
    ['virtual/?$' => 'index.php?virtual=1'],
    $wp_rewrite->rules
);

});
add_filter(‘query_vars’, function ($query_vars) {
$query_vars[] = ‘virtual’;
return $query_vars;
});

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);

And in setup.php:

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/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();
}

});

Aunge Controllers in sage work with the hierarchy of WordPress templates, is there any way a controller works with a virtual page just like they do in sage?

Thank you

@helgi there may be a way to get the controllers to automatically work with this, but not sure off the top of my head. Check the controller docs for ideas. https://github.com/soberwp/controller/

You may also be able to learn something from how the data is collected in filters.php: https://github.com/roots/sage/blob/master/app/filters.php#L59-L61.

But at the very least you could also just call methods form your controllers from within your action hook as you’re preparing the data to pass to template().

1 Like

Thanks @mmirus
for the orientation. I think I’m ready with your suggestions to consume a very basic WebService, read only in json format. I was thinking about reading the service and having wordpress create the contents based on the personalized Post Type. But now I’m going to create some virtual pages and show the service.

My challenge now are the images of the service. It is a software made in C # to which I do not have access. They only give me the reading of the data and the images do not send them optimized.

I go step by step and thank you for your help.

2 Likes

This topic was automatically closed after 42 days. New replies are no longer allowed.