Pedro Kehl - Webdesigner

Uma forma otimizada de incluir blocos de conteúdo no WordPress

04/03/2019

Nesse post mostro uma solução bastante flexível ao get_template_part do Wordpress.

O WordPress é bastante flexível quanto a forma de incluir parciais.

Pode-se usar funções nativas do PHP como include() ou include_once() ou mesmo require() e require_once(), ou funções exclusivas do próprio WordPress como get_template_part().

Inclusão com get_template_part

A solução usando get_template_part é mais interessante, pois permite ao desenvolvedor mais flexibilidade para lidar com temas pai e temas filho. Se você por exemplo criar um tema filho e tentar chamar um bloco PHP pertencente ao tema pai, você precisaria inserir o caminho relativo completo do tema filho (onde por exemplo um pedaço do layout está sendo chamado) para o tema pai.

O get_template_part resolve isso de maneira inteligente e automática. Se você chamar alguma parcial usando essa função, ele primeiro checará se o tema filho a possui. Não encontrando, ele ira subir para o tema pai e tentar encontrar lá.

Se preciso incluir uma parcial chamada loop.php por exemplo, posso usar get_template_part(loop.php). Se loop.php existir no tema filho, o WordPress sempre irá inseri-lo (pois essa é a premissa de ter temas pai e filhos), mas caso não encontre o loop.php será procurado no tema pai.

Mas o get_template_part não resolve tudo

Mas digamos que a sua necessidade não seja apenas inserir uma parcial, mas parametrizá-la para poder mudar variáveis na inserção. Nesse caso, encontraríamos um problema. A única forma de passar parâmetros para o template herdado do pai seria usando variáveis globais.

Seu loop.php original poderia ser o seguinte:

<?php
$the_query = new WP_Query(array(
        'post_type' => 'posts',
        'posts_per_page' => 10
    )
);
if ($the_query->have_posts()):
    while ($the_query->have_posts()):
        
        // Faça algo aqui

    endwhile;
endif;
wp_reset_postdata();
?>

Nesse exemplo o loop tem uma query onde procuro pelos 10 últimos posts  do tipo “posts”.

Mas digamos que no tema filho eu tenha um tipo de post customizado, chamado livros. Gostaria de usar o mesmo loop.php – pois a estrutura seria a mesma –  mas gostaria de substituir o post_type da minha query pelo post_type livros.

Poderia tentar algo assim:

<?php
$post_type = 'livros'; 
get_template_part( 'loop.php' );
?>

E dentro do meu loop, chamaria a variável $post_type. Infelizmente essa solução não funcionaria. $post_type apareceria como não definida.

<?php
$the_query = new WP_Query(array(
        'post_type' => $post_type, // Variável não definida
        'posts_per_page' => 10
    )
);
if ($the_query->have_posts()):
    while ($the_query->have_posts()):
        
        // Faça algo aqui

    endwhile;
endif;
wp_reset_postdata();
?>

Uma forma de resolver o problema é usar o include com outra função nativa do WordPress, a locate_template junto com o include nativo do PHP.

<?php
$post_type = 'livros'; 
include( locate_template( 'loop.php', false, false ) ); 
?>

Nesse caso, a variável $post_type dentro do loop.php ficaria definida. Meu código funcionaria e teria um loop reutilizável.

Uma solução ainda melhor

Mas é possível tornar o código ainda mais limpo, tornando todas as variáveis locais dentro da parcial, evitando variáveis “soltas” dentro do código.

Encontrei essa solução há algum tempo atrás, e ele ainda existe no gitHub em: https://github.com/Smartik89/SMK-Theme-View/blob/master/functions.php

A função seguinte usa o locate_template mas localiza as variáveis dentro do escopo da parcial. Eu preservei o nome da classe original, mas mudei o nome da função, por considerar mais simples:

<?php
if (!class_exists('Smk_ThemeView')) {
    class Smk_ThemeView {
        private $args;
        private $file;
        public function __get($name) {
            return $this->args[$name];
        }
        public function __construct($file, $args = array()) {
            $this->file = $file;
            $this->args = $args;
        }
        public function __isset($name) {
            return isset($this->args[$name]);
        }
        public function render() {
            if (locate_template($this->file)) {
                include( locate_template($this->file) ); //Theme Check free. Child themes support.
            }
        }
    }
}
if (!function_exists('get_template_obj')) {
    function get_template_obj($file, $args = array()) {
        $template = new Smk_ThemeView($file, $args);
        $template->render();
    }
}
?>

O uso é muito simples. Para usar as variáveis com a parcial, faria o seguinte:

<?php
get_template_obj('loop.php', array(
    'post_type'  => 'livros'
));
?>

Dentro do loop.php, teríamos a seguinte situação:

<?php
$the_query = new WP_Query(array(
        'post_type' => $this->post_type, // Use o $this para acessar a variável
        'posts_per_page' => 10
    )
);
if ($the_query->have_posts()):
    while ($the_query->have_posts()):
        
        // Faça algo aqui

    endwhile;
endif;
wp_reset_postdata();
?>

Como no exemplo do uso da função nativa get_template_part, temos todas as vantagens do uso entre temas pai e filhos, inserção automática e ainda a opção de inserir parâmetros localizados!