Atualização : O código foi atualizado recentemente para funcionar no WordPress 4.7+
Você já quis criar seus próprios templates de página, mas não teve acesso ao tema em si? Eu, como autor de plugins do WordPress, achei esse problema particularmente irritante ao desenvolver meus plugins. Felizmente a solução é bem simples! Vou levá-lo rapidamente através das poucas linhas de código que você precisará para criar dinamicamente WordPress Page Templates diretamente através do PHP.
A inspiração para este artigo e o gênio por trás da solução de código vem de Tom McFarlin : estou usando minha versão editada de seu código original, que você pode encontrar em seu GitHub. Eu mantive os comentários dele (assim como adicionei alguns dos meus), pois acho muito útil para explicar o que está acontecendo – eu não poderia ter dito melhor!
Você pode encontrar o código na íntegra e um plugin de exemplo na parte inferior deste post.
Começaremos?
O código
Vamos criar nossa função PHP usando uma classe PHP. Para aqueles que não são bem versados
Nosso wrapper precisará apenas de 3 variáveis:
- O Plugin Slug: Este é simplesmente usado como um identificador exclusivo para o plugin.
- Instância de classe: Como estamos adicionando uma instância dessa classe ao head do WordPress, é melhor armazená-la.
- Template Array: Como você provavelmente pode adivinhar, este é um array contendo os nomes e títulos dos templates.
Aqui estão eles em código:
class PageTemplater {
/**
* A Unique Identifier
*/
protected $plugin_slug;
/**
* A reference to an instance of this class.
*/
private static $instance;
/**
* The array of templates that this plugin tracks.
*/
protected $templates;
Obter instância de classe
Como eu disse anteriormente, adicionaremos uma instância de nossa classe ao cabeçalho do WordPress usando a função add_filter() . Portanto, precisaremos de um método que retornará (ou criará) essa instância para nós.
Para isso, precisaremos de um método simples, que será chamado de ‘get_instance’. Confira abaixo;
/**
* Returns an instance of this class.
*/
public static function get_instance() {
if( null == self::$instance ) {
self::$instance = new PageTemplater();
}
return self::$instance;
}
Este será o método chamado quando nossa classe for adicionada ao cabeçalho do WordPress usando ‘add_action()’.
Filtros do WordPress
Agora que resolvemos o método ‘get_instance’, precisamos resolver o que acontece quando ele é realmente instanciado.
Usaremos a função add_filter() embutida do WordPress para adicionar uma instância de nossa classe em pontos-chave ao longo da linha do tempo de inicialização do WordPress. Usando esse método, inseriremos os dados dos nossos modelos de página em slots relevantes, como informar ao WordPress qual arquivo usar como modelo quando a página for chamada e o título a ser exibido no menu suspenso no Editor de página.
Para isso precisamos usar o método ‘__construct’ (isso será executado quando a classe for instanciada).
/**
* Initializes the plugin by setting filters and administration functions.
*/
private function __construct() {
$this->templates = array();
// Add a filter to the attributes metabox to inject template into the cache.
if ( version_compare( floatval( get_bloginfo( ‘version’ ) ), ‘4.7’, ‘<‘ ) ) {
// 4.6 and older
add_filter(
‘page_attributes_dropdown_pages_args’,
array( $this, ‘register_project_templates’ )
);
} else {
// Add a filter to the wp 4.7 version attributes metabox
add_filter(
‘theme_page_templates’, array( $this, ‘add_new_template’ )
);
}
// Add a filter to the save post to inject out template into the page cache
add_filter(
‘wp_insert_post_data’,
array( $this, ‘register_project_templates’ )
);
// Add a filter to the template include to determine if the page has our
// template assigned and return it’s path
add_filter(
‘template_include’,
array( $this, ‘view_project_template’)
);
// Add your templates to this array.
$this->templates = array(
‘goodtobebad-template.php’ => ‘It\’s Good to Be Bad’,
);
}
Existem 4 coisas diferentes acontecendo aqui (ignorando ‘ $this->templates = array();’, que está apenas preparando a variável para uso);
- Linhas 9 – 13 : Este filtro está adicionando o ‘register_project_templates’ ao gancho ‘page_attributes_dropdown_pages_args’. Isso está preenchendo o cache do WordPress com nossos novos modelos, ‘enganando’ o WordPress fazendo-o acreditar que os arquivos de modelo de página realmente existem no diretório de modelos. Isso adiciona os modelos de página à lista suspensa na caixa meta de atributos de página no editor de página.
- Linhas 16 – 20 : Aqui estamos fazendo essencialmente o mesmo que o bloco de código anterior, exceto que desta vez estamos adicionando nosso modelo de página (se selecionado) aos dados de postagem salvos também.
- Linhas 23 – 28 : Este filtro está adicionando o ‘template_include’ ao gancho ‘view_project_template’. Esta é uma função muito importante; isso informa ao WordPress onde seu arquivo de modelo de página realmente está. O WordPress usará o caminho fornecido por isso para renderizar a página final.
- Linhas 31 – 34 : Embora seja simples, é muito importante. É aqui que você especifica os modelos de página que deseja adicionar e o caminho relativo ao arquivo onde está o arquivo de modelo de página ( ex. ‘algo.php’ ). Incluí um exemplo (que será usado no plugin de exemplo). Confira abaixo um exemplo geral:
$this->templates = array(
‘FILE_PATH_AND_NAME’ => ‘TEMPLATE_TITLE’,
‘awesome-template.php’ => ‘Awesome’,
‘templates/organised-template.php’ => ‘Organised’,
);
(Comer, Dormir,) Codificar, Repita conforme necessário.
registrar_projeto_modelos()
Já fiz alusão a esse método anteriormente; vamos ver o que ele realmente faz.
Essencialmente, o objetivo deste método é manipular o cache do WordPress, inserindo os dados relevantes sobre nossos modelos de página nos lugares certos. Dê uma olhada no código primeiro, e eu vou falar com você depois.
public function register_project_templates( $atts ) {
// Create the key used for the themes cache
$cache_key = ‘page_templates-‘ . md5( get_theme_root() . ‘/’ . get_stylesheet() );
// Retrieve the cache list.
// If it doesn’t exist, or it’s empty prepare an array
$templates = wp_get_theme()->get_page_templates();
if ( empty( $templates ) ) {
$templates = array();
}
// New cache, therefore remove the old one
wp_cache_delete( $cache_key , ‘themes’);
// Now add our template to the list of templates by merging our templates
// with the existing templates array from the cache.
$templates = array_merge( $templates, $this->templates );
// Add the modified cache to allow WordPress to pick it up for listing
// available templates
wp_cache_add( $cache_key, $templates, ‘themes’, 1800 );
return $atts;
}
Certo então. A linha 4 é o primeiro lugar a procurar. Como você deve ter adivinhado, estamos gerando uma ‘chave de cache’. Isso será usado como um identificador exclusivo para nossos dados de modelo de página. Usar a função md5() simplesmente cria um identificador de string exclusivo para evitar conflitos.
Em seguida, na linha 8, estamos procurando e recuperando o cache do modelo de página (se já existir): isso retornará uma matriz de caminhos e títulos. Nas linhas 9-11, verificamos se houve alguma saída da consulta de cache. Se sim, ótimo. Caso contrário, crie um array local para armazenar os dados que serão mesclados no cache.
O próximo passo é crucial. Na linha 14, excluímos o cache do modelo de página existente. Não se preocupe, nenhum dado é perdido – ele é armazenado na variável $templates.
Na linha 18, mesclamos o cache de templates de página existente com nossas novas entradas e, na linha 22, reinserimos todo o cache de template de página no sistema do WordPress.
Simples!
view_project_template()
Estamos agora em nosso método final; é aqui que informamos ao WordPress onde está o arquivo de modelo de página real.
/**
* Checks if the template is assigned to the page
*/
public function view_project_template( $template ) {
// Get global post
global $post;
// Return template if post is empty
if ( ! $post ) {
return $template;
}
// Return default template if we don’t have a custom one defined
if ( !isset( $this->templates[get_post_meta(
$post->ID, ‘_wp_page_template’, true
)] ) ) {
return $template;
}
$file = plugin_dir_path(__FILE__). get_post_meta(
$post->ID, ‘_wp_page_template’, true
);
// Just to be safe, we check if the file exist first
if ( file_exists( $file ) ) {
return $file;
} else {
echo $file;
}
// Return template
return $template;
}
Ok, então, este método estará verificando a variável global $post (linha 6). Ele verifica se um modelo de página ( ‘_wp_page_template’ ) foi definido para o post (o que significa que deve ser uma página). Se não, então não importa – não páginas não podem ter modelos de página.
A linha 16 especifica o local do arquivo de modelo de página. Como eu estabeleci acima, ele verifica o arquivo de modelo de página especificado no diretório raiz do seu plugin. (Isso pode ser facilmente alterado; veja abaixo.)
// Just changing the page template path
// WordPress will now look for page templates in the subfolder ‘templates’,
// instead of the root
$file = plugin_dir_path(__FILE__). ‘templates/’ .get_post_meta(
$post->ID, ‘_wp_page_template’, true
);
Depois disso, nas linhas 21 – 24, temos apenas um pouco de validação que verifica se o arquivo realmente existe. Se sim, incrível! Se não, oh querida… Você provavelmente receberá uma mensagem de erro do PHP se o WordPress não encontrar o arquivo de modelo, ou mesmo uma tela em branco. Se algum desses sintomas parecer familiar, verifique o caminho do arquivo de modelo imprimindo a variável $file na tela.
Se você planeja usar este código comercialmente (o que você é livre para fazer – minha versão do código vem sem licença, portanto, você é livre para fazer o que quiser), eu realmente recomendo investir algum tempo no tratamento de erros para obter o máximo confiabilidade.
Isso é isso. Com a nossa aula concluída, resta apenas uma coisa a fazer – adicioná-la à cabeça do WordPress.
add_action( ‘plugins_loaded’, array( ‘PageTemplater’, ‘get_instance’ ) );
Parabéns se você conseguiu chegar até o fim! Espero que você tenha achado útil o que eu tinha a dizer e que você se beneficie disso no futuro!
Código inteiro
Abaixo está todo o código do plugin para copiar e colar facilmente.
<?php
/*
Plugin Name: Page Template Plugin : ‘Good To Be Bad’
Plugin URI: http://www.wpexplorer.com/wordpress-page-templates-plugin/
Version: 1.1.0
Author: WPExplorer
Author URI: http://www.wpexplorer.com/
*/
class PageTemplater {
/**
* A reference to an instance of this class.
*/
private static $instance;
/**
* The array of templates that this plugin tracks.
*/
protected $templates;
/**
* Returns an instance of this class.
*/
public static function get_instance() {
if ( null == self::$instance ) {
self::$instance = new PageTemplater();
}
return self::$instance;
}
/**
* Initializes the plugin by setting filters and administration functions.
*/
private function __construct() {
$this->templates = array();
// Add a filter to the attributes metabox to inject template into the cache.
if ( version_compare( floatval( get_bloginfo( ‘version’ ) ), ‘4.7’, ‘<‘ ) ) {
// 4.6 and older
add_filter(
‘page_attributes_dropdown_pages_args’,
array( $this, ‘register_project_templates’ )
);
} else {
// Add a filter to the wp 4.7 version attributes metabox
add_filter(
‘theme_page_templates’, array( $this, ‘add_new_template’ )
);
}
// Add a filter to the save post to inject out template into the page cache
add_filter(
‘wp_insert_post_data’,
array( $this, ‘register_project_templates’ )
);
// Add a filter to the template include to determine if the page has our
// template assigned and return it’s path
add_filter(
‘template_include’,
array( $this, ‘view_project_template’)
);
// Add your templates to this array.
$this->templates = array(
‘goodtobebad-template.php’ => ‘It\’s Good to Be Bad’,
);
}
/**
* Adds our template to the page dropdown for v4.7+
*
*/
public function add_new_template( $posts_templates ) {
$posts_templates = array_merge( $posts_templates, $this->templates );
return $posts_templates;
}
/**
* Adds our template to the pages cache in order to trick WordPress
* into thinking the template file exists where it doens’t really exist.
*/
public function register_project_templates( $atts ) {
// Create the key used for the themes cache
$cache_key = ‘page_templates-‘ . md5( get_theme_root() . ‘/’ . get_stylesheet() );
// Retrieve the cache list.
// If it doesn’t exist, or it’s empty prepare an array
$templates = wp_get_theme()->get_page_templates();
if ( empty( $templates ) ) {
$templates = array();
}
// New cache, therefore remove the old one
wp_cache_delete( $cache_key , ‘themes’);
// Now add our template to the list of templates by merging our templates
// with the existing templates array from the cache.
$templates = array_merge( $templates, $this->templates );
// Add the modified cache to allow WordPress to pick it up for listing
// available templates
wp_cache_add( $cache_key, $templates, ‘themes’, 1800 );
return $atts;
}
/**
* Checks if the template is assigned to the page
*/
public function view_project_template( $template ) {
// Get global post
global $post;
// Return template if post is empty
if ( ! $post ) {
return $template;
}
// Return default template if we don’t have a custom one defined
if ( ! isset( $this->templates[get_post_meta(
$post->ID, ‘_wp_page_template’, true
)] ) ) {
return $template;
}
$file = plugin_dir_path( __FILE__ ). get_post_meta(
$post->ID, ‘_wp_page_template’, true
);
// Just to be safe, we check if the file exist first
if ( file_exists( $file ) ) {
return $file;
} else {
echo $file;
}
// Return template
return $template;
}
}
add_action( ‘plugins_loaded’, array( ‘PageTemplater’, ‘get_instance’ ) );
O plug-in
Você também pode baixar o código completo como um plugin no Github .
Close do editor de postagem
Aqui está um close do plugin em ação. Veja o modelo de página adicionado em Atributos de página?