MB Views - Creating WordPress templates without touching theme files

Edit this page on Github

MB Views helps you to get Meta Box fields and build your templates in the front end fast and easily.

With MB Views, you can just select fields you want to show, fill in some parameters and done! The extension supports all custom fields built with Meta Box, and also post fields (such as post title and post content), site settings, user fields, and even query fields.

You can also customize all templates in WordPress, even for post types that don’t have Meta Box fields.

Video tutorial

In this video, we show you step-by-step how to use MB Views to create singular and archive templates for a custom post type. We also show you the basis of Twig and how to set location rules.

Creating a view

To create a view, go to Meta Box > Views and click the Add New button.

creat a new view

In the view screen, you’ll see 2 areas:

  • Template editors: where you can enter template code for the view. It contains 3 editors for the template, CSS and JavaScript.
  • Settings: where you can set location rules for the view.

In the main editor, you can enter any HTML or shortcodes for the template. All shortcodes will be parsed automatically in the front end.

Insert fields

To insert a field, click the Insert Field button. It will open a panel on the right, where you can see all available fields.

Fields are categorized into 4 tabs:

  • Post: contains all post fields and custom fields for posts.
  • Site: contains all site fields and settings fields (created by MB Settings Page plugin).
  • User: contains all user fields and custom fields for users (created by MB User Meta plugin).
  • Query: contains loop and pagination for archive pages.

To insert a field, click on the field title to insert it. The field might have additional parameters (such as choose image size for image field). And in that case, the plugin will open a popup for you to enter or select options.

enter field options

When you’re done entering the field options, click Insert button to insert the field in the editor. The plugin will generate a snippet and insert it into the editor.

If a field doesn’t have options, then the plugin will insert a snippet into the editor immediately without opening a popup.

Main query

The items on the Insert Field tab only works with the main query. We can understand when setting Type and Location for the View. For example: You can only use the item “Term ID” when Type is Archive and Location is Taxonomy Archive, if you use the item “Post ID”, it will not work.

main query

Cloneable fields

Cloneable fields are marked with a repeat icon, like this:

cloneable group fields

To insert a cloneable field, click on the field title, like inserting a normal field.

The plugin will generate a snippet for the field, like this:


{% for clone in post.tickets %}
    Content here might be different depends on the field type
{% endfor %}

This is a for loop, created by using Twig template engine. You’ll find more details about it below. The content inside the for loop might be different depending on the field type.

Group fields

Group fields are marked with an arrow on the left, just like the image above. Clicking on the arrow will toggle the group sub-fields.

To insert a sub-field, click on the sub-field title, like inserting a normal field. Depending on the field type, it will open a popup for additional options or not.

Important: if you have a cloneable group, before inserting sub-fields, you MUST insert the for loop for the group first. To insert the group, click on the group title. See the Cloneable Fields section above for details.

Relationship fields

Relationships created with MB Relationships extension can be inserted in the tab Query.

Once you registered a relationship, it will show 2 fields here: one for “from” side, and one for “to” side. Clicking a field will insert a loop of connected items, and inside the loop, you can insert post/term/user fields as usual.

See tutorial: How To Display Relationships?

Include other views

The plugin allows you to include other views, which helps you to break down a large templates into smaller ones and re-use them in other views.

To insert a view, go to tab tab Query, and click on the view you want to insert. Note that when you include view into another view, they have access to the same context as the current view. This means that any variable defined in the main view will be available in the included view.

See tutorial: Creating and Including Template Parts in MB Views

Running PHP functions

To run PHP functions, use the mb proxy. It acts as a transformer between views and PHP.

Assume you want to get another post in WordPress with post ID 123, you can write a simple PHP code:

$post = get_post( 123 );
echo $post->post_title;

With the mb proxy, you can call the get_post() function like this:


{% set post = mb.get_post( 123 ) %}
{{ post.post_title }}

Here you see, the normal PHP function is prefixed by mb., e.g. get_post becomes mb.get_post. So if you want to call a function my_custom_function, you need to write mb.my_custom_function. The parameters passed to the function remain the same.

Custom query

Relate to the Main query above, if you use the function get_posts() or get_post(), it will return post object.

WP_Post Object
(
    [ID] =>
    [post_author] =>
    [post_date] => 
    [post_date_gmt] => 
    [post_content] => 
    [post_title] => 
    [post_excerpt] => 
    [post_status] =>
    [comment_status] =>
    [ping_status] => 
    [post_password] => 
    [post_name] =>
    [to_ping] => 
    [pinged] => 
    [post_modified] => 
    [post_modified_gmt] =>
    [post_content_filtered] => 
    [post_parent] => 
    [guid] => 
    [menu_order] =>
    [post_type] =>
    [post_mime_type] => 
    [comment_count] =>
    [filter] =>
)

These properties are different from the Post items in the Insert Field tab and you can only use these properties to get the post information. For the post meta, you can use the helper function rwmb_meta() or WordPress functions to retrieve it.


{% set args = { post_type: 'post', posts_per_page: -1 } %}
{% set posts = mb.get_posts( args ) %}
{% for post in posts %}
    Post title: {{ post.post_title }} 
    
    Single image:
    {% set image = mb.rwmb_meta( 'single_image', '', post.ID ) %}
    <img src="{{ image['full_url'] }} "> 

    Post thumbnail: {{ mb.get_the_post_thumbnail( post.ID, 'thumbnail' ) }}
{% endfor %}   

In case you want to set arguments for functions, use the set syntax. Twig allows you to set complex variables, like lists with keys and values and then you can pass it to the function:


{% set my_var = ["first", "second"] %}
{% set my_var = {first: "first value", second: "second value"}

{% set my_var = {first: "first value", second: "second value"}

{% set value = mb.custom_function( my_var ) %}

Custom data

The plugin allows you to pass custom data to the shortcode via custom attributes. This allows you to build flexible views and show them in multiple places with custom data.

For example, you want to display user info in a view. While fetching custom user data is fine, you might want to set user details (like “name” and “age”) in some specific cases. You can pass “name” and “age” to a view shortcode like this:

[mbv id="your-view-id" name="Brian" age="50"]

And in your view template, you can use this data directly like this:


<p><strong>Name:</strong> {{ name }}</p>
<p><strong>Age:</strong> {{ age }}</p>

Locations

Each view can serve multiple pages on your website. To set where the view appears, go to Settings meta box below the editor:

view locations

There are several options:

Type

What type of page do you want to set the view for? Supports:

  • Singular pages
  • Archive pages
  • Action: the view will display when an action fires
  • Code: you can use PHP or WordPress conditional tags to set the rules where to show the view.
  • Shortcode: you need to use a shortcode to insert the view to the location you want. The shortcode is available after you save the view.

Location Rules

Where you set the rules for the singular and archive pages. Location rules are divided into groups, and in each group, you can set multiple rules.

Rules inside a group are combined with OR logical operator, which means the views will serve this page if either condition is satisfied.

Groups are combined with AND logical operator, which means the views will serve this page if all conditions are satisfied.

With the combination of OR and AND, you can build complex rules for views.

Render type

After choosing location rules, you can decide where to render the view for those chosen pages. You have 2 options:

  • Render for the whole page layout, including header and footer. This option is useful when you want to build a complete new page on your site.
  • Render for the whole layout between header and footer. Using this option, you have full control to build the layout.
  • Render only for the post content area. Using this option, you leave the layout to the theme and control only the post content area.

Position

If you choose to render the view for the post content area, then you can set it to appear before, after or replace the content area.

Order

The order settings is used to set the loading order for views. If you have multiple views for the same page, then views with a lower order will render first.

Hooks

mbv_location_validate:

This filter is used to allow developers to create custom rules for location validation. It accepts 3 parameters:

  • $result: the validation result
  • $view: the view object (which is a post object)
  • $type: the view type

For example, if you have a view that display for all archive pages, but you don’t want it to appear on pages that have query string ?custom_var=1, you can do like this:

add_filter( 'mbv_location_validate', function( $result, $view, $type ) {
    // Run for 'my-view-name' only.
    if ( $view->post_name !== 'my-view-name' ) {
        return $result;
    }

    if ( isset( $_GET['custom_var'] ) && $_GET['custom_var'] == 1 ) {
        return false;
    }
    return $result;
}, 10, 3 );

mbv_location_action_active

This filter is used to allow developers to create custom rules for location validation for the views that has displayed on a specific action (type = action). It accepts 3 parameters:

  • $active: is the view active
  • $view: the view object (which is a post object)
  • $action: the action name

For example, if you have a view that display on wp_footer, but you don’t want it to appear on pages that have query string ?custom_var=1, you can do like this:

add_filter( 'mbv_location_action_active', function( $active, $view, $action ) {
    // Run for 'my-view-name' only.
    if ( $view->post_name !== 'my-view-name' || $action !== 'wp_footer' ) {
        return $active;
    }

    if ( isset( $_GET['custom_var'] ) && $_GET['custom_var'] == 1 ) {
        return false;
    }
    return $active;
}, 10, 3 );

mbv_twig_env

This filter allows you to change the Twig instance to render the view.

add_filter( 'mbv_twig_env', function( $twig ) {
    // return your own $twig instance.
    return $twig;
} );

mbv_data

This filter allows you to add/change/remove data sent to Twig to render the view.

add_filter( 'mbv_data', function( $data, $twig ) {
    $data['custom_var1'] = 'Value 1';
    $data['custom_var2'] = 'Value 2';
    
    return $data;
}, 10, 2 );

Twig

When editing a template for views, you can use any HTML/CSS/JavaScript.

In some cases, when you need to set a condition for an HTML section or loop through all values of an array, then you can use Twig.

Twig is a powerful template engine for PHP, which allows you to write conditions (if..else), control structure (for) and use filters to transform the output.

For example, if you want to output an image if the post doesn’t have a featured image, then you can use the following snippet:


{% if post.thumbnail.full %}
    <img src="{{ post.thumbnail.full.url }}">
{% else %}
    <img src="https://via.placeholder.com/800x100">
{% endif %}

If a field has multiple values, then you can use for-loop to render all the values, like this:


{% for country in post.countries %}
    {{ country }}
{% endfor %}

You can also use filter to transform the value, like this:

{{ post.date | date( 'm/d/Y' ) }}

For details about using Twig, please see the documentation.

External template files

Since version 1.10, MB Views allows you to write template in the extenal files in your themes/plugins and include or use it inside views or with [mbv] shortcode.

Using external template files has some benefits:

  • You can write templates in Twig instead of PHP, which is a beautiful syntax. Twig templates also support getting WordPress and Meta Box’s values easier
  • You can put template files under a version control like Git to track changes and never loose anything
  • You can deploy (upload) templates to other websites with ease via (S)FTP, Git or any CI/CD

Let’s see how to do that:

Adding template paths

First, you need to register the paths, where the plugin looks for template files. Simply use the mbv_fs_paths as follows:

// Load template files from the 'views' folder in your theme.
add_filter( 'mbv_fs_paths', function( $paths ) {
    $paths[] = get_template_directory() . '/views';
    return $paths;
} );

// Or shorter
add_filter( 'mbv_fs_paths' , function( $paths ) { 
    return array_merge( $paths, [ get_template_directory() . '/views' ] );
} );

// Shortest with arrow functions in PHP 7.4+
add_filter( 'mbv_fs_paths' , fn( $paths ) => array_merge( $paths, [ get_template_directory() . '/views' ] ) );

You can also register multiple paths, the plugin will try to load templates from these paths, in the registered order:

add_filter( 'mbv_fs_paths' , function( $paths ) { 
    return array_merge( $paths, [
        get_template_directory() . '/views',
        get_template_directory() . '/default',
    ] );
} );

Or you can use the filesystem loader to add paths:

add_action( 'mbv_fs_loader_init', function( $fs_loader ) {
    // Add a path.
	$fs_loader->addPath( get_template_directory() . '/views' );
    
    // Prepent a path, which change the order of registered paths and thus the order to load template files.
    $fs_loader->prepend( get_template_directory() . '/default' );
} );

Using extenal views

You can include external views in your views using this snippet:


{% include 'header.twig' %}

This snippet will load the header.twig template from the registered paths (in the examples above - the views directory in your theme). If you register multiple paths, then the plugin will search for the template in these paths and return the first found template file. So, pay attention to the order of registered paths.

You can also render the template with the [mbv] shortcode as follows:

[mbv name="header.twig"]

Note that the file extension doesn’t matter. You can name the file header.twig, header.html or anything. It’s only used to search for the template files.

Namespace

When loading template files, the order of registered paths define the order of paths where the plugin search for a template. However, there are some cases when you have templates with a same name, but used for different purpose, such as a header.twig for the homepage and another header.twig for the rest of the website. You might use different names for files, but there’s a better option is using namespace.

To add a template with a namespace, use the code below:

add_action( 'mbv_fs_loader_init', function( $fs_loader ) {
    // Add 'views/home' folder under the namespace 'home'
	$fs_loader->addPath( get_template_directory() . '/views/home', 'home' );
    
    // Add another namespace
    $fs_loader->addPath( get_template_directory() . '/views/default', 'default' );
} );

Usage:


{% include '@home/header.twig' %}
{% include '@default/header.twig' %}

// or with shortcode

[mbv name="@home/header.twig"]
[mbv name="@default/header.twig"]

Edit this page on Github