Wallogit.com
2017 © Pedro Peláez
A better way to organize Wordpress templates.
A better way to develop Wordpress templates., (*1)
All the template files reside in the templates folder.
Any template files at the theme's root folder will not work, (*3)
Template Wrapper transforms wordpress's default template file naming to provide better organization of the files.
'Slugged' template files, i.e. single-{post_type|post_name|post_id} etc., are grouped in a subdirectory named to that type., (*4)
Example:
- templates/single/post.php will be used in place of single-post.php.
- templates/page/about-us.php will be used in place of page-about-us.php.
- templates/archive/4.php will be used in place of archive-4.php.
- Template-type files will still be used as is; e.g., templates/single.php, templates/page.php, etc., (*5)
In general, files are organized by {type}/{slug|id|custom-name}.php format., (*6)
Custom page templates should be placed in the templates folder., (*7)
Template Wrapper uses custom page template files only for registration in the admin.
That is, custom page template files will not be used as "views".
You have to create a file of the same name in the templates/page folder., (*8)
Example:, (*9)
To use a custom "Donate Page Template" using
custom-donate-page.php,
Create one in thepage-templatesfolder as a registry, containing only the template name.
Create another one in thetemplates/pagefolder as a "view". This will be the one rendering your view., (*10)
Template Wrapper allows route registration through template_routes hook.
Routes are placed in src/routes.php in the following manner:, (*12)
// src/routes.php
add_filter( 'template_routes', function () {
return array(
$template_slug => $callable,
);
});
$template_slug (String), (*13)
The "route" to the template slug. This is similar to the Wordpress's template hierarchy, though transformed to become directory-based., (*14)
$callable (Function or Object/Class Method), (*15)
The "controller". This will handle the data passed to the template. This can be either a function or an object/class method, similar to MVC approach., (*16)
Example:, (*17)
// Matches is_single(), using a function name
'single' => 'post_data',
// Matches 'project' post type single, Using a static class method
'single/project' => [ 'MyControllerClass', 'project_single' ],
// Matches single for a post_id of 12
'single/12' => [ 'MyControllerClass', 'project_single' ],
// Will match about page, using a namespaced class method
'page/about' => [ '\\MyNamespace\\AnotherController', 'about' ],
// Will match a custom page template registered in `page-templates/custom-page.php`
'page/custom-page' => [ 'MyControllerClass', 'custom_page_data' ],
// Will match any page or single which is not registered in route
'page' => 'any_page_data',
'single' => 'any_single_data',
```
***Note:***
A "slugged" route doesnt require a template counterpart. Just like wordpress's template hierarchy, it will use the available template for that slug.
That is, a `page/about` route will use `templates/page.php` if `templates/page/about.php` is not available.
<a name="wrapper"></a>
## Template Wrapper
This is inspired by **scribu**'s [theme wrapper](http://scribu.net/wordpress/theme-wrappers.html) which also implemented in Sage starter themes.
It allows you to have your main layout in `wrapper.php`, and the main template will be automatically wrapped with it.
It prevents code repition caused by using `get_header()` or `get_footer()` at each main template.
<a name="template-includes"></a>
## Template Includes
The Template Wrapper provides a way to include templates and passing data through `include_template` method of the `Wrapper` class.
```php
// single.php
use QtGye\TemplateWrapper\Wrapper;
This is an awesome post!
To avoid having to declare Wrapper's namespace in every template, it is recommended to wrap it in a global function instead, like so:, (*18)
// functions.php
function include_template ( $template_slug ='', $data = [] ) {
QtGye\TemplateWrapper\Wrapper::include_template( $template_slug, $data );
}
$template_slug (String), (*19)
The slug of the template file relative to the templates folder. In the example, it will load
templates/modules/content.php., (*20)
$data (Assoc. Array), (*21)
The data to be passed into the included template. Note that user-defined globals are also available in the included templates, so if there are common variable names, the template data will override it., (*22)
The route callable handles the data being passed to the template. Through reflection, the callable may receive user-defined globals as arguments., (*24)
Example: ```php class MyControllerClass {, (*25)
// Using the $post global
static function about_page ( $post ) {
$data = [];
$data['id'] = $post->ID;
$data['slug'] = $post->name;
// The variables $id and $slug are now available in the template
return $data;
}
} ```, (*26)
The user-defined global data is defined in the src/global.php through the template_global_data hook. These globals are available within templates., (*27)
Example: ```php // src/global.php, (*28)
add_filter('template_global_data', function ( $predefined_globals ) { // For some reason, use $wp_roles global global $wp_roles;, (*29)
// $wp_roles variable is now ready to be used in the templates
return compact('wp_roles');
}); ```, (*30)
Template Wrapper provides pre-defined globals to which user-defined globals are merged:
$wp, $wpdb, $wp_query, $post, $authordata, $page;, (*31)
Template Wrapper provides a way to handle ajax routing using action., (*33)
Register ajax routes through the ajax_routes hook.
```php
// src/routes.php, (*34)
add_action( 'ajax_routes', function () {
return array(
// Matches ?action=items
'items' => [ "MyController", "ajax" ],
);
});
```, (*35)
Within the ajax callback, GET parameters and user-defined globals are passed through reflection., (*36)
```php class MyController {, (*37)
// Handling ?action=items&filter=all&page=3
// The argument names should match the GET parameter names. Hence, order is irrelevant.
static function ajax ( $page, $filter, $post ) {
// $filter === 'all'
// $page === '3'
$response = [
'items' => get_filtered_posts( $filter, $page),
'current_id' => $post->ID,
];
// Returned data is sent as json-encoded response.
return $response;
}
} ```, (*38)