O processo de desenvolvimento de um Tema WordPress tem início na adequação dos códigos a estrutura do WordPress. Em seguida, a utilização do arquivo functions.php permite a você atribuir novas funcionalidades ao seu Tema sem a necessidade de alterar o código-fonte do WordPress.

Chegou a hora de aplicar o Conteúdo Dinâmico gerenciado pelo WordPress ao seu Tema. Até agora poucas informações vinham sendo recuperadas do painel de controle. Agora você verá justamente como ampliar essa integração, trazendo conteúdo dinâmico do Dashboard para ser aplicado dentro do Tema.

Por dentro do sistema

Para demonstrar de modo prático como recuperar as informações do WordPress e aplicá-las a um Tema, nada melhor que a criação de um blog. O projeto traz as seguintes especificações:

Tema WordPress desenolvido para o jornal Publicações

Tema WordPress desenvolvido para o jornal Publicações

  • Possibilitar o gerenciamento dos itens do menu de navegação
  • Permitir que os visitantes façam uma busca pelo blog
  • Acrescentar links na lateral do blog que permitam ao visitante encontrar melhor a informação pretendida
  • Habilitar em ambiente administrativo a escolha de qual conteúdo exibir na barra lateral do site, bem como a ordenação ou informações dos mesmos
  • Apresentar todos os posts do blog em resumo
  • Inserir uma paginação numérica na listagem dos posts
  • Apresentar um título capaz de situar a área que o visitante está ativo
  • Exibir o conteúdo completo dos posts de modo separado
  • Fornecer um sistema para envio e gerenciamento de comentários e respostas aos comentários

Você já aprendeu qual a estrutura básica de um Tema e conheceu os caminhos para realizar alterações e executar tarefas personalizadas no sistema, sem afetar sua estrutura, através da API de Plugins. Também fez a incorporação de folhas de estilos e scripts de modo seguro e eficaz. Enfim, de posse desses conhecimentos você já é capaz de incorporar um template de conteúdo estático ao WordPress. O processo que inicia-se a partir de então é de aprofundamento nos recursos do CMS, em quais situações e de qual maneira você poderá fazer uso deles.

Esse projeto é uma excelente introdução para as mais diversas funções de conteúdo que o WordPress oferece. De posse do template, realize a integração do mesmo com o WordPress seguindo as diretrizes que você já aplicou nos trabalhos anteriores.

Menus

O próximo elemento do layout a ser trabalhado será o menu de navegação do site. Esse menu possui links para diferentes telas do site e, quando necessário, pode levar o visitante para outros sites ou mesmo direcionar para downloads de arquivos. E assim como a estrutura de pastas e as definições do site, não seria nada bom definir os links de modo manual, diretamente no código. Até porque você ainda não sabe qual conteúdo deverá linkar, ele sequer foi criado.

Atribuição dos menus para as áreas definidas pelo Tema

Atribuição dos menus para as áreas definidas pelo Tema

Nessa situação é essencial fazer uso do gerenciador de Menus nativo do WordPress. Isso garante a integridade dos links internos e facilita a edição das ligações personalizadas. De início, ative o menu inserindo, dentro da função pw_theme_setup, o seguinte código:

register_nav_menu( 'menu-header', 'Menu do Cabeçalho' );

Será registrado um menu identificado como ‘menu-header’ para a programação e descrito como ‘Menu de Cabeçalho’ no Dashboard, o painel de controle do WordPress. Tendo feito o registro, vá até o arquivo do cabeçalho header.php e remova a lista de links. Em seu lugar execute função wp_nav_menu da seguinte forma:

<div id="menu">
    <?php wp_nav_menu( 'menu-header' ); ?>
</div>

Caso não exista nenhum menu atribuído ao local que você definiu em register_nav_menu, por padrão é executada a função wp_page_menu que imprime em tela uma listagem das páginas existentes. Caso não queira que isso aconteça, você pode determinar algumas configurações a essa função via parâmetro:

wp_nav_menu( array(
        'theme_location'    => 'menu-header',
        'fallback_cb'       => null,
        'container'         => 'div',
        'container_id'      => 'menu',
        'container_class'   => null,
        'menu_class'        => 'main-menu',
        'menu_id'           => null
    )
);

A opção fallback_cb recebe o nome da função que será executada; como está definido um valor nulo, nada irá ocorrer nesse caso. Retire do código HTML a definição da div na qual o menu está inserido, pois as opções container, container_id e container_class trazem o mesmo resultado. E do mesmo modo é possível atribuir uma classe e um id a tag ul da lista de links.

Os containers aceitos são <div> e <nav>. Caso necessite de uma outra tag será preciso adicionar um filtro a tag ‘wp_nav_menu_container_allowedtags’. A função de tratamento recebe como único parâmetro ambos os formatos em um array numérico. Adicione sua tag ao array e o retorne para o WordPress identificar a tag desejada. [file-3]

Sidebar e Formulário de Pesquisa

Outro elemento que se destaca dentro da estrutura de um blog é a Sidebar. Essa barra lateral, assim como o cabeçalho e rodapé, também será replicada em vários lugares do site. Nesse caso, evidencie o conteúdo da sidebar em um arquivo separado chamado sidebar.php; e em seu lugar no arquivo index.php de origem, o inclua com:

<?php get_sidebar(); ?>

A informação que é apresentada logo no início da sidebar é um formulário de pesquisa. No local do formulário existente você pode inserir um formulário de pesquisa do WordPress em seu Tema usando apenas:

<?php get_search_form(); ?>

Você verá que automaticamente as marcações HTML do formulário foram geradas. O formulário de pesquisa nada mais é que a definição de uma requisição GET a tela inicial do site com a variável ‘s’ (nome do campo de texto) recebendo o valor a ser pesquisado. Como o projeto já possui sua própria definição de HTML, você deve operar com o formulário original. Crie um novo arquivo em seu Tema com o nome searchform.php e faça os devidos ajustes na definição HTML original de modo que ela passe a funcionar no WordPress:

<form method="get" action="<?php echo PW_URL; ?>">
    <fieldset>
        <input type="text" name="s" placeholder="Pesquisar por:" />
        <input type="submit" value="Pesquisar" />
    </fieldset>
</form>

Dessa maneira a função get_search_form irá reconhecer o arquivo recém-criado e utilizar o seu conteúdo ao invés das marcações padrão.

Recomenda-se usar esse recurso de segmentar o arquivo do formulário de pesquisa apenas se o tal arquivo possuir muitos elementos, se ele apresentar certa dificuldade de atualização ou a fim de organizar o código-fonte. Contudo, lembre-se que serão requisições adicionais sendo feitas em seu servidor e que feito isso em grande escala poderá resultar em perda de performance.

Área de Widgets

Atenda o requisito do projeto em permitir o gerenciamento do conteúdo da sidebar fazendo o registro de uma área de widgets em seu projeto:

add_action( 'widgets_init', 'pw_register_sidebars' );

function pw_register_sidebars()
{
    register_sidebar( array(
            'id'            => 'sidebar_main',
            'name'          => 'Barra lateral',
            'description'   => 'Descrição da área de Widgets'
        )
    );
}

Foi definido um identificador único para área na opção id. Também foi estipulado um nome e uma descrição que serão visíveis na tela de Widgets. Com as demais opções da função você pode ainda determinar instruções HTML para serem exibidas antes e/ou depois do título e conteúdo do widget como um todo. A exibição do conteúdo dos Widgets no Tema ocorre por meio de:

dynamic_sidebar( 'sidebar_main' );

Especifica-se como parâmetro o identificador da área que contém os Widgets a recuperar. Contudo, ocorre por vezes da área registrada não conter nenhum Widget e por fim exibir um espaço vazio no local onde deveria estar o conteúdo. Evite esse problema checando a presença de um Widget ativo em sua área.

if ( is_dynamic_sidebar() )
    dynamic_sidebar( 'sidebar_main' );
else
    // Apresenta um conteúdo padrão

A condição verifica Widgets ativos para todas as áreas de Widgets registradas, logo em um projeto com várias áreas, o ideal seria fazer a verificação unitária de cada uma delas.

if ( is_active_sidebar( 'sidebar_main' ) )

O sistema irá verificar a presença de Widgets ativos para a sidebar cujo identificador foi passado como parâmetro de is_active_sidebar.

Inserindo links com a estrutura de Links Permanentes

Dentro do arquivo recém-criado é preciso trabalhar as listas de links que o template propõe. Não é demais lembrar que os links internos não devem ser inseridos de modo manual, adotar essa prática além de propiciar o surgimento de erros; não estaria efetivamente aproveitando dos recursos que o WordPress está oferecendo.

Listagem de Categorias

De acordo com o template, a primeira lista de links diz respeito as categorias do blog. Antes de realizar a listagem dos links, em um primeiro momento você deverá recuperar as categorias que deseja apresentar ao visitante:

$cats = get_categories();

Assim como em todas as demais funções que você estudar, é muito relevante conhecer os parâmetros aceitos por elas. Em get_categories, por exemplo, é possível determinar a quantidade de resultados obtidos, a ordenação dos mesmos, remover ou incluir determinadas categorias; entre outras opções.

Como seu objetivo com esse projeto é de recuperar apenas as categorias com conteúdo (possuem posts atribuídos a ela) e em ordem alfabética crescente; nenhum parâmetro precisa ser referenciado. Os resultados obtidos serão armazenados na variável em formato de array. Permita a exibição dos links de cada categoria a partir de um laço de repetição capaz de navegar por todas elas:

<?php
foreach ( $cats as $cat ) {
    printf( '<li><a href="%1$s" title="%2$s">%2$s</a></li>',
        get_category_link( $cat->term_id ),
        $cat->name
    );
} ?>

Gerada a lista você poderá notar que o link padrão de uma categoria é

/?cat={id da categoria}

Você pode imaginar então definir a criação do link com:

<a href="<?php echo PW_URL . '?cat=' . $cat->term_ID; ?>">

Também funciona, porém acontece que através do painel de adiministração é possível alterar facilmente as regras de reescrita de URL. Se você se utilizar da função para recuperar o link, a cada mudança nas regras de resscrita de URLs e link também será atualizado. Por outro lado caso você opte pela segunda definição poderá ter em seu site links diferentes apontando para o mesmo lugar. Em estruturas de conteúdo mais complexas a atribuição do link pelo segundo método será pouco prática; portanto é melhor se habituar desde o início a maneira mais correta e prática de se trabalhar.

Funções nativas do WordPress

Fique atento aos recursos que o WordPress oferece. Boa parte das tarefas que você pretende fazer com as informações recuperadas do sistema já foram desenvolvidas e estão disponíveis para serem aplicadas ao seu Tema. Veja por exemplo a listagem dos links das categorias em uma lista pode ser facilmente gerada apenas com:

<ul>
    <?php wp_list_categories( array( 'title_li' => null ) ); ?>
</ul>

A grande diferença em se utilizar instruções próprias e as funções oferecidas pelo WordPress está no fato do primeiro modo permitir a você controle total sobre o resultado pretendido. Ou seja, a informação está em suas mãos e você define exatamente aquilo que pretende fazer com ela. No exemplo das categorias, o WordPress acrescenta classes aos itens da lista e um texto próprio ao atributo title do link.

Relevando a subjetividade da programação e as preferências de cada um, a escolha de qual técnica utilizar varia de acordo com o projeto e a situação que você está enfrentando. Pequenas alterações em classes e identificadores das tags HTML podem arruinar seu trabalho. Por outro lado, na maioria dos casos, as funções que são oferecidas pelo CMS possuem muitas opções que permitem o controle desses atributos. Sem contar que, assim como você já viu anteriormente, a manipulação do resultado obtido também pode ser alterado através dos filtros da Plugin API. Diante da situação apresentada, a função wp_list_categories poderia ser incrementada com o seguinte código:

add_filter( 'wp_list_categories', 'pw_format_list_categories', 10, 2 );
function pw_format_list_categories( $output, $args ) {
    // Tratamento do resultado
    // Sendo $output a lista gerada e $args os parâmetros utilizados
}

Apenas atente-se ao funcionamento completo da função; é possível que os resultados não sejam os esperados e acabe por afetar negativamente o seu trabalho em vez de otimizá-lo. Isso vale para os dois métodos de trabalho, seja através da aplicação de instruções próprias ou oferecidas pelo WordPress. De acordo com os exemplos das categorias, caso você não obtenha nenhuma categoria como resultado de get_categories nada acontece; no entanto ao usar wp_list_categories (do modo apresentado) diante da mesma situação, seria exibido um texto padrão informando ao visitante a inexistência de categorias para aquele contexto.

Como você pode observar são vários fatores que determinam a escolha das funções e métodos de desenvolvimento a fim de se integrar um projeto ao WordPress. Lembre-se que no início dos estudos você substituiu algumas funções pelo fato delas não serem úteis ao projeto ou demandarem mais recursos de servidor do que o necessário.

Listas de Posts e Arquivos de posts

O mesmo processo realizado com as categorias deverá ser empregado para exibição das publicações mais recentes. Ao invés de requisitar as categorias, você deve informar ao sistema que ele retorne os posts. Assim sendo, mesmo sem conhecer as funções que lhe são oferecidas, você arriscaria deduzir que exista uma função get_posts? Exatamente!

<?php $entries = get_posts(); ?>
<ul>
    <?php
    foreach ( $entries as $entry ) {
        printf( '<li><a href="%1$s" title="%2$s">%2$s</a></li>',
            get_permalink( $entry->ID ),
            $entry->post_title
        );
    } ?>
</ul>

Mediante o uso de get_permalink você obtém a URL do post de acordo com a estrutura de links permanentes definida no Dashboard; aplica-se aqui o mesmo raciocínio da obtenção dos links das categorias.

Apesar dessa similaridade da nomenclatura algumas funções podem apresentar comportamentos distintos. Esse é o caso de get_pages, embora muito parecido com get_posts possui opções diferentes.

Esse pensamento lógico pode ser aplicado para encontrar boa parte das funções para captura de informações oriundas do WordPress. Mas nem sempre isso acontece. Note que não existe uma função wp_list_posts. Ainda assim é bem provável que exista outra função nativa do sistema que possa executar as tarefas pretendidas de modo automático; no caso dessa listagem dos últimos posts publicados uma alternativa é o uso de:

<h2>Últimos Posts</h2>
<ul>
    <?php
    wp_get_archives( array(
            'type'  => 'postbypost',
            'limit' => 10
        )
    ); ?>
</ul>

Com wp_get_archives é possível recuperar os conteúdos por períodos de tempo. O valor atribuído a opção type é que define esse filtro dos resultados. Como o valor passado foi postbypost, serão retornados resultado por resultado, ou seja, todos. Se nenhum valor estiver discriminado para essa opção serão retornados os resultados agrupados mês a mês; e é exatamente esse o próximo objetivo da integração do template atual.

<h2>Archives</h2>
<ul>
    <?php wp_get_archives(); ?>
</ul>

Esse agrupamento de resultados poderá ser feito também por ano, dia ou semana de acordo com o valor passado para a opção type. Você pode também exibir uma lista com links para as páginas do projeto usando get_pages (ou get_posts com a opção ‘post_type’ igual a ‘page’) de modo manual ou aplicando wp_list_pages pelo modo direto.

The Loop

O próximo passo do desenvolvimento do Tema proposto é exibir os conteúdos dos posts de acordo com a proposta apresentada pelo template. O conteúdo que será exibido dependerá da solicitação do visitante. Para você saber qual informação exibir é preciso ter em mente que ao acessar um site com seu conteúdo sendo gerenciado pelo WordPress, a cada requisição de URL o sistema recupera o conteúdo referente aquela requisição e a deixa disponível no escopo global da aplicação.

Isso quer dizer que ao requisitar o endereço de uma página, as informações referente aquela página poderá ser facilmente recuperada de valores globais. O mesmo para os posts, paginação de resultados e todo tipo de resultado obtido a partir do endereço informado pelo visitante.

Nos passos anteriores a exibição dos resultados de modo manual seguiu um mesmo procedimento de recuperar as informações e em seguida exibí-las através de um laço de repetição. Pois bem, como você já possui as informações, basta agora informar ao sistema as instruções para realização da segunda etapa do mesmo procedimento: apresentar todo o conteúdo recuperado.

O WordPress possui sua própria estrutura para definir o laço de repetição responsável pela exibição dos resultados, essa estrutura é conhecida como The Loop:

<?php
while ( have_posts() ) {
    the_post();
    global $post;
    // manipulação dos dados
} ?>

Pela tradução literal do laço, você já pôde compreender que enquanto houver resultado a ser exibido o sistema executará as instruções que serão passadas dentro da estrutura de repetição. A função the_post é responsável por atualizar os valores globais da variável $post. Será justamente com o auxílio dessa variável que grande parte das informações poderão ser recuperadas.

Atente ao valor que a variável $post assume a cada requisição feita. Se o endereço consultado for referente a um post em si, a variável trará consigo todos os valores referente aquele post. Em requisições cujo resultado é mais de um conteúdo, o valor assumido pela variável é sempre o primeiro resultado da lista.

funções get e the

A tela inicial do blog exibe os últimos posts publicados. Cada post deve exibir o título, data de publicação, autor, seu resumo e links para o conteúdo completo. Comece pelo título e o link para a publicação completa:

<h2>
    <?php
    printf( '<a href="%1$s" title="%2$s">%2$s</a>',
        get_permalink(),
        get_the_title()
    );?>
</h2>

A função get_permalink já utilizada retorna a URL do post e get_the_title obtém o título do mesmo. Nesse trecho de código você deve tomar nota ao fato da primeira função não receber o ID do post como parâmetro e por ter sido empregado a função get_the_title ao invés de $post->post_title. Acontece que ao executar essas funções, você está dentro do Loop e dentro desse escopo o WordPress assume o valor da variável global $post para as referidas funções.

Se você preferir inserir o título recuperando o valor diretamente da variável global, ele será exibido do mesmo modo. Entretanto, através da função get_the_title esse título é tratado pelo sistema; caso o conteúdo seja privado ou protegido por senha, essa informação é incorporada a ele. E o uso de get_the_title permite ainda a manipulação do filtro ‘the_title’ caso você queira impor uma personalização própria para todos os títulos do seu projeto.

A função get_permalink e get_the_title, tal como algumas outras funções referente a recuperação de conteúdo, possuem funções de atalho capazes de executar o mesmo procedimento (ou muito semelhante) e imprimirem o resultado em tela. São respectivamente the_permalink e the_title. Isto é, para certas funções get_ (de retorno de valores) existe sua correspondente the_ (para impressão de resultados em tela).

Em ambos os casos apresentados as funções get_ aceitam como parâmetro o ID do post que você pretende recuperar o link ou título. Enquanto que em the_permalink a função não permite parâmetros e em the_title os parâmetros são outros. Em geral os parâmetros de funções do tipo get_ são a definição de quais resultados recuperar e para os tipo the_ são de formatação do resultado a ser exibido; já que se utilizam dos valores globais para definir qual dado exibir.

Semelhantes, mas diferentes

Além do título que você já tratou, o template propõe a exibição da data de publicação, o autor (referenciado com seu link pessoal) e resumo de cada post.

<p>
    <span><?php echo get_the_date( 'F d, Y' ); ?></span>
    <span>Posted by <?php the_author_posts_link(); ?></span>
</p>
<div style="clear: both;">&nbsp;</div>
<div>
    <?php the_excerpt(); ?>
    <p>
        <a href="<?php the_permalink(); ?>">Read More</a>
        <a href="<?php the_permalink(); ?>#comentarios" title="b0x">Comments</a>
    </p>
</div>

O uso de get_the_date foi feito em preferência a the_date pois esse último método exibe apenas as datas diferente. Em outras palavras, se existirem vários posts de uma mesma data, essa por sua vez, apenas será exibida ao post da primeira ocorrência. Esse comportamento de the_date é ideal para agrupar conteúdos por data. O formato da data é transmitido via parâmetro, porém você pode utilizar a definição feita no painel do WordPress não especificando nenhum valor a ele.

Através do painel de controle é possível determinar o formato padrão para a exibição de datas dentro do Tema

Através do painel de controle é possível determinar o formato padrão para a exibição de datas dentro do Tema

Ao especificar o nome do autor do post e um link a ele, você tem duas escolhas a fazer: apresentar um link para uma URL personalizada do autor (cujo endereço o próprio pode definir via edição de Perfil) ou então exibir uma ligação para uma lista com as demais publicações desse mesmo autor. Se pretende exibir o link para a URL personalizada utilize the_author_link, ou use the_author_posts_link para ligar a informação ao arquivo de postagens.

Trabalhando com resumos (post_excerpt)

No WordPress o resumo dos conteúdos é tratado como excerpt, e as funções para sua aplicação no tema são the_excerpt e get_the_excerpt. Ambas funcionam devidamente apenas dentro do Loop, pois recuperam o resumo dos valores globais. Além de recuperar o resumo, o uso dessas funções se dá com o tratamento do filtro get_the_excerpt atribuído a função wp_trim_excerpt. Esse tratamento verifica se o campo resumo foi preenchido; caso tenha sido seu valor é apresentado. Do contrário a função recupera o conteúdo original do post e exibe apenas as primeiras palavras. Você pode editar a quantidade de palavras com o filtro ‘excerpt_length’ e os caracteres que simbolizam a continuidade do conteúdo com ‘excerpt_more’.

function custom_excerpt_length( $length ) {
    return 20;
}
add_filter( 'excerpt_length', 'custom_excerpt_length' );

function custom_excerpt_more( $more ) {
    return '[Leia mais...]';
}
add_filter( 'excerpt_more', 'custom_excerpt_more' );

Apenas fique atento ao fato que o resumo não possui limitação de caracteres, ou seja, é possível que ao gerenciar o conteúdo de um site, alguns resumos se apresentem maiores que outros. Tome os devidos cuidados nas definições de estilo para que seu Tema não quebre diante dessa situação.

Paginação de resultados

O fechamento da tela inicial do blog com a listagem de resultados será dado pela inserção de links de navegação entre as telas de resultados. Para todas as consultas ao conteúdo cadastrado no WordPress (posts e páginas a princípio) a definição de quantos resultados são exibidos a cada tela (caso não tenha sido alterado esse comportamento via parâmetros de funções ou filtros) é definida nas Opções de Leitura do painel de controle.

A quantidade de resultados por página pode ser definida através do Dashboard

A quantidade de resultados por página pode ser definida através do Dashboard

O tipo mais simples de navegação entre as telas de resultados é através de links simples que permitem a navegação para a próxima tela ou até a tela anterior a que o visitante está no momento.

<?php previous_posts_link( 'Resultados anteriores' ); ?>
<?php next_posts_link( 'Próximos resultados' ); ?>

Caso a proposta da paginação seja apenas informar ambos os links lado-a-lado sem que exista necessariamente uma formatação especial atribuída ao recurso, você poderá utilizar também:

<?php posts_nav_link( ' | ', 'Resultado anteriores', 'Próximos resultados' ); ?>

Paginação numérica

Uma estrutura diferente de navegação é mediante o uso de links numéricos. Tais links remetem diretamente a tela pretendida sem a necessidade do visitante visitá-las uma a cada vez para chegar aonde deseja. A continuidade desse recurso deriva do seu conhecimento em como efetuar uma paginação de resultados fora do WordPress. Assim como todo algorítmo é preciso inicialmente conhecer as variáveis e também qual o tratamento a ser aplicado.

Para esse recurso você precisaria da quantidade de resultados obtidos, quantidade de resultados exibidos tela, tela atual e a partir desses dados aplicar os cálculos e o procedimento padrão para exibição dos links. Já com o uso dos recursos do WordPress, você precisa apenas definir tais valores de acordo com a requisição feita:

<?php
function pw_paginate_links()
{
    global $wp_query;
    $page_tot = $wp_query->max_num_pages;
    $page_cur = $wp_query->get( 'paged' );

    if ( $page_tot <= 1 )
        return false;

    if ( !$page_cur )
        $page_cur = 1;

    echo '<nav>Página ' . $page_cur . ' de ' . $page_tot . ': ' .
    paginate_links( array(
            'base'      => str_replace( $page_tot, '%#%', get_pagenum_link( $page_tot ) ),
            'format'    => '?paged=%#%',
            'current'   => max( 1, $page_cur ),
            'total'     => $page_tot,
            'prev_next' => false,
            'end_size'  => 1,
            'mid_size'  => 2
        )
    ) . '</nav>';
} ?>

No código em detalhe você recuperou as telas totais e a também a atual. A condição principal para exibir os links, que é justamente a existência de outras telas, você tratou em seguida. No WordPress é possível que a primeira tela de resultados não tenha um valor definido para o valor global paged; logo, nessa situação o valor deverá ser 1, por ser a primeira. Por fim, todo o árduo trabalho é feito por paginate_links de acordo com as configurações a ela atribuídas.

Telas do projeto

Até o momento, todas as requisições feitas ao site estão sendo enviadas para o arquivo index.php do Tema. A busca, os links de categorias e também os arquivos. Por se tratar de uma mesma tela para exibição de conteúdos diferentes, é muito relevante apresentar ao usuário sua localização e qual conteúdo está sendo apresentado. Em resolução a esse problema, você irá especificar um título antes da listagem dos resultados com a informação ‘Resultados de busca’, ou ‘Categoria: Nome da categoria’ e assim por diante. Para tratar dessas informações serão utilizados dois recursos do WordPress; tais recursos estão diretamente ligados e servem para agilizar, organizar e otimizar o desenvolvimento dos Temas WordPress. São eles a hierarquia de templates e as conditional tags.

Hierarquia do WordPress

Na atual situação do seu tema, o arquivo index.php responde a todas as requisições realizadas ao site. Você sabe também que a cada requisição o WordPress recupera a informação a disponibiliza em escopo global. E é justamente em meio a esses processos que o sistema realiza, onde também ocorre a definição dos arquivos do Tema a exibir o conteúdo mediante o uso da hierarquia de templates.

Em prática o que acontece é: a cada tipo de requisição existe um arquivo que corresponde ao conteúdo a ser exibido. Imagine o visitante ter submetido o formulário de busca. Antes da requisição chegar ao index.php ela passa pelo search.php; como tal arquivo ainda não existe, o arquivo utilizado é mesmo o primeiro. O index.php é o arquivo principal e obrigatório de todos os Temas, pois ele é a parada final para todas as requisições. Desse modo se o WordPress não encontrar arquivos relacionados as consultas solicitadas via URL, sempre haverá o template padrão para exibição dos resultados.

Faça um teste simples de modo a confirmar essa lista de prioridades de inserção dos arquivos. Crie um arquivo search.php e dentro dele informe:

<?php
global $title;
$title = 'Resultados da busca por "' . get_search_query() . '"';
get_template_part( 'index' );
?>

Definido o título da requisição, dentro do index determine a exibição do mesmo:

<div id="content">
    <?php
    global $title;
    if ( !$title ) $title = 'Arquivo';
        echo "<h1>{$title}</h1>"; ?>

Você determinou a incorporação do arquivo index.php através de get_template_part porque ao escolher o arquivo de resultados de busca para apresentar os resultados, nenhuma outra inclusão de arquivo é feita; configura o final das verificações por ter sido encontrado o arquivo ideal para tal conteúdo.

Utilizar get_template_part é o modo seguro de fazer requires dentro do WordPress. Isso porquê o sistema antes de incorporar o arquivo aos processos em andamento, ele verifica sua existência e também atribui o caminho correto para tal incorporação. Mesmo sendo recomendável o uso de get_template_part em razão do uso dos ganchos e da praticidade que a função oferece; caso prefira você poderá também fazer esse tratamento de modo manual em seus trabalhos. Faça uso da constante TEMPLATEPATH na incorporação dos arquivos, tal constante possui o caminho completo do Tema ativo no WordPress.

Cada área do site, diferenciadas umas das outras pelos filtros atribuídos de acordo com o endereço solicitado; possui uma definição própria do WordPress. Você viu a tela de busca ser representada pelo arquivo search.php. Da mesma forma o conteúdo das categorias pode ser tratado pelo arquivo category.php.

Seguindo o mesmo raciocínio, o arquivo author.php representa as requisições baseadas no autor das publicações, date.php para agrupamento por datas (independente do filtro ser o dia, mês ou ano) e outros mais. Vale ressaltar que além desses arquivos próprios para cada situação, existem arquivos genéricos por exemplo o archive.php que trata das paginações de resultados e o single.php usado para exibir o conteúdo completo de posts e anexos.

Perceba que o trabalho da hierarquia do WordPress e a inclusão dos arquivos do Tema ocorre de modo sequencial baseado em uma série de verificações, por exemplo: Diante de uma requisição feita referente aos resultados de uma determinada categoria, o WordPress tentará localizar o category.php; em sua ausência será carregado o archive.php (responsável pela paginação dos resultados de modo geral) e por fim se nenhum desses existir, a exibição dos resultados será feito pelo index.php.

Outro detalhe importante a frisar são as verificações feitas pelo sistema para inclusão de arquivos específicos para ocasições próprias de cada Tema. Imagine que seu Tema necessite de uma tela diferente para páginas e outra para posts; para isso o WordPress aceita o uso de page.php e single.php respectivamente. Em uma situação mais específica, o Tema precisa, além de uma tela para exibir resultados dos autores, uma tela especial para o administrador e também autor de conteúdo; nesse caso você poderia utilizar-se dos arquivos author-[nicename].php ou ainda author-[id-do-autor].php. O mesmo procedimento também é aplicado para tags, categorias e tipos de conteúdo.

Conditional tags

As mesmas verificações realizadas a cada requisição pela hierarquia de templates do WordPress podem ser aplicadas no desenvolvimento de um Tema. Isto é, você também pode checar se a requisição atual é referente a categorias, tags, autor e assim por diante. Tais verificações são feitas mediante o uso das Conditional Tags; tal como o nome sugere, são funções para tratamento dessas condições.
As funções condicionais possuem em sua estrutura o prefixo is_ seguido da verificação a ser feita, por exemplo is_category() para checar se o conteúdo é referente a categorias. De posse dessa informação, otimize seu código removendo o arquivo search.php criado e substituindo no index.php as seguintes instruções:

<?php
$title = 'Arquivo';
if ( is_search() )
    $title = 'Resultados da busca por "' . get_search_query() . '"';
else if ( is_category() )
    $title = 'Categoria: ' . single_cat_title( '', false );

echo "<h1>{$title}</h1>"; ?>

Veja que é possível reduzir significativamente a quantidade de arquivos idênticos que devem carregar consigo, como diferenciação entre si, apenas algumas definições da requisição atual. Algumas Conditional Tags permitem também uma verificação mais específica do filtro atual de conteúdo através de seus parâmetros opcionais:

<?php
is_category( 'slug-da-categoria' );
is_category( 9 );
is_category( 'Nome da categoria' );
is_category( array( 1, 2, 3 ) );

is_single( 2 );
is_single( 'post-slug' );
is_page( 5 );
?>

Note que as verificações são feitas baseadas nos conteúdos existentes, seja por slugs, identificadores ou os respectivos nomes. No exemplo, tal como nas demais condições de paginação de resultados; para verificar mais de um resultado específico, além dos identificadores, os slugs e nomes também podem ser determinados dentro do array.

Apesar de bastante útil esse controle é preciso ter alguns cuidados sobre isso, principalmente ao definir como parâmetros os slugs e nomes como parâmetros; já que tais itens são facilmente editáveis pelo painel. Os identificadores por sua vez são únicos e apenas deixarão de funcionar como esperado se os respectivos conteúdos forem apagados.

Recuperando Informações do WordPress

De acordo com a hierarquia de templates do WordPress a exibição de um post pode ser feita através do arquivo single.php. Crie esse arquivo em seu Tema e insira as mesmas instruções da index.php com alguns pequenos ajustes:

  • Retire os links do título e dos botões abaixo do resumo, eles levam o visitante para o conteúdo completo do post que é justamente a tela que você está editando.
  • Ao invés de aplicar a estrutura do Loop do WordPress, determine apenas a atualização dos valores globais com the_post para se certificar que os valores recuperados serão os corretos.
  • No lugar da função responsável por exibir o resumo do post, informe a função para exibir o conteúdo completo.
<?php the_post(); ?>
<div>
    <h2>
        <?php the_title(); ?>
    </h2>
    <p>
        <span><?php echo get_the_date( 'F d, Y' ); ?></span>
        <span>Posted by <?php the_author_posts_link(); ?></span>
    </p>
    <div style="clear: both;">&nbsp;</div>
    <div>
        <?php the_content(); ?>
    </div>
</div>

Comentários

A manipulação de comentários dentro do WordPress possui muitos tópicos a serem seguidos, verificados e aplicados no desenvolvimento de um Tema. Na tela com as opções de discussão do painel de controle é possível determinar quando os comentários serão exibidos, se permitirão respostas, quem poderá enviá-los e uma série de outras configurações. Assim como você fez com o formulário de busca, a listagem e o formulário para envio de comentários também pode ser feita utilizando o formato padrão do WordPress através de uma única função:

<?php comments_template(); ?>

O funcionamento realmente é o mesmo: a função procura nos arquivos do Tema a presença de um arquivo que contenha as instruções sobre a tarefa e caso não encontre exibe as definições padrão. Na ocasião do formulário de busca o nome do arquivo em questão precisa ser searchform.php e para os comentários o arquivo a ser localizado deve ser denominado o comments.php. Crie então um arquivo comments.php e dentro dele faça a verificação se o conteúdo atual possui ou não a opção dos comentários abertos.

<?php if ( comments_open() ) { ?>
Comentários abertos!
<?php } ?>

Listar comentários

A proposta dos comentários requer uma listagem dos resultados. Induzido pela lógica que cerca a nomenclatura de funções do CMS, deduza corretamente que deve ser feito o uso de:

<ul id="comments">
    <?php wp_list_comments(); ?>
</ul>

O uso de wp_list_comments diretamente no arquivo single.php não lhe apresentará resultado algum. Isso acontece pois a função comments_template recupera os comentários do conteúdo atual, definido de acordo com os valores globais da requisição do visitante; e em sequência disponibiliza os comentários recuperados no escopo global da aplicação.

Apesar da listagem dos comentários permitir algumas alterações mediante a definição de suas opções; a marcação HTML gerada será própria do WordPress e talvez não se enquadre a estrutura que o template requere. Nesses casos você pode atribuir o nome de uma função personalizada a opção callback de wp_list_comments. Ao fazer isso, você passa a usar a sua função para exibir os resultados como preferir.

<?php if ( comments_open() ) { ?>
    <ul id="comments">
        <?php wp_list_comments( array( 'callback' => 'pw_list_comments' ) ); ?>
    </ul>
<?php } ?>

Após referenciar a função de callback, informe as rotinas a serem realizadas nesse contexto dentro do arquivo de funções.

<?php
function pw_list_comments( $comment, $args, $depth )
{
    if ( $comment->comment_type == '' )
    {
        $comment_id = (int) $comment->comment_ID;
        $author = get_comment_author_link();

        $content = get_comment_text();
        $avatar = get_avatar( $comment, 80 );
        $date_time = get_comment_date( 'd/m/Y H:i' );

        $reply = get_comment_reply_link(
            array_merge( $args, array(
                    'reply_text'    => 'Responder',
                    'respond_id'    => 'responder',
                    'depth'         => $depth
                )
            )
        );

        echo '<li><div>';

        echo $avatar . $author . '<br />Enviado em ' . $date_time . ' | ' . $reply;
        echo "<div class=\"comment-text\">{$content}</div>";

        echo '</div>';
    }
} ?>

Essa função é executada dentro do laço de repetição responsável por exibir os comentários. Os parêmetros recebidos são, pela ordem; o comentário atual, os argumentos (opções) de wp_list_comments e a profundidade do comentário. A profundidade de um comentário diz respeito a relação desse com o texto sob o qual está inserido, isto é, um comentário direto sobre um post possui profundidade 1; já um comentário resposta a um comentário de profundidade 1, possui profundidade 2 e assim por diante.

A verificação de $comment->comment_type limita a exibição a comentários feitos por visitantes, pois também são armazenados como comentários os pingbacks e trackbacks do conteúdo em questão. Nesses últimos casos o campo recebe os respectivos valores.

Dentro da função são recuperadas as informações que o projeto necessita exibir: a imagem e nome do autor do comentário, a data de envio e comentário em si. Também é gerado um botão de resposta que permitirá trabalhar com as profundidades dos comentários. Nesse botão de resposta é inserido o ID responsável por referenciar a seção do código HTML que contém o formulário de envio dos comentários. Determine essa relação dentro do arquivo comments.php:

<div id="responder">
    <?php comment_form(); ?>
</div>

Enviar comentário

Do mesmo modo que wp_list_comments, o uso de comment_form gera as saídas no formato padrão do WordPress; e da mesma forma, nem sempre essa marcação corresponde ao proposto na criação do template original. Com o intuito de personalizar o formulário você pode escolher entre dois caminhos: configurar as opções e atribuir filtros a comment_form ou gerar suas próprias marcações. No entanto as marcações desse formulário devem ser desenvolvidas com grande atenção, uma vez que as opções de discussão podem sofrer alterações via painel de controle e também pela possibilidade de configurar cada conteúdo para receber ou não tal interação dos visitantes.

Caso você opte pelo uso de comment_form não precisará se preocupar com esse tratamento, ele é feito pelo sistema de modo completo. Por outro lado se preferir estabelecer marcações próprias para esse recurso deverá se preocupar com alguns detalhes importantes:

  • Título do formulário
  • Link para cancelamento das respostas
  • Verificação de usuários logados
  • Campos de controle, essenciais ao funcionamento do recurso

Não foi listada a verificação se o conteúdo possui comentários abertos, pois no projeto tal verificação é feita antes mesmo de listar os comentários existentes. A seguir a definição de um formulário customizado:

<div id="responder">
    <h3>Deixe seu comentário</h3>
    <p>
        <a rel="nofollow" id="cancel-comment-reply-link" href="#responder" style="display: none;">Cancelar Resposta</a>
    </p>

    <form action="<?php echo PW_URL; ?>wp-comments-post.php" method="post">
        <fieldset>
            <?php if ( is_user_logged_in() ) { $current_user = wp_get_current_user(); ?>
            <p>
                Conectado como <a href="<?php echo admin_url( 'profile.php' ); ?>" title="Edite seu perfil"><?php echo $current_user->display_name; ?></a>.
                <a href="<?php echo wp_logout_url( get_permalink() ); ?>" title="Sair do sistema">Desconectar</a>
            </p>
            <?php } else { ?>
            <p><input name="author" type="text" placeholder="Nome" /></p>
            <p><input name="email" type="text" placeholder="Email" /></p>
            <p><input name="url" type="text" placeholder="Endereço URL (Opcional)" /></p>
            <?php } ?>
            <p><textarea name="comment" cols="45" rows="8" placeholder="Comentário"></textarea></p>
            <p><input type="submit" value="Comentar" /></p>
            <input type="hidden" name="comment_post_ID" value="<?php global $post; echo $post->ID; ?>" id="comment_post_ID" />
            <input type="hidden" name="comment_parent" id="comment_parent" value="<?php echo ( $_GET[ 'replytocom' ] ) ? $_GET[ 'replytocom' ] : 0; ?>" />
        </fieldset>
    </form>
</div>

Em detalhes, são exibidos o título e o link capaz de cancelar respostas; inicialmente não exibido já que por padrão ao carregar o conteúdo, a resposta será direta, de profundidade 1. A definição do form deve receber em seus atributos o envio do tipo POST e ser destinado ao arquivo wp-comments-post.php localizado na raiz da instalação do WordPress.

Verifica-se a situação do usuário diante do sistema. Se o usuário estiver logado não será preciso solicitar nome, email ou url; tais informações já estão contidas no perfil desse usuário. Por outro lado, se ele for um visitante desconhecido, solicitam-se esses dados.

Em seguida são apresentados o campo de comentário e o botão de enviar. Os campos ocultos definem as opções de controle do WordPress, sendo que o primeiro determina para qual conteúdo o comentário será relacionado e o outro o identificador do comentário cuja mensagem atual pretende responder. Se um comentário enviado não ter sido feito em resposta a outro, esse último campo permanece com o valor 0; porém se o inverso ocorrer, o campo assume o identificador do comentário a ser respondido.

O envio dos dados via POST assim como a nomenclatura dos campos serão reconhecidos e tratados pelo referido arquivo do WordPress; tal arquivo é usado pelo sistema nativo de comentários. No entanto nada lhe impede de criar suas próprias instruções para efetuar esse processo; apenas atente-se as informações que devem ser armazendas em banco de dados e ao tratamento do formulário. Tenha muito cuidado para não recolher SPAM ou até mesmo eventuais tentativas de envio de códigos mal-intencionados.

Respondendo a Comentários

Mesmo com o sistema de comentários funcionando bem, existe uma situação a ser otimizada: Ao optar por responder um comentário, a tela está sendo recarregada pelo navegador. Essa nova requisição não é necessária, já que o conteúdo exibido será o mesmo e a partir do clique no link responder você já consegue definir facilmente para qual comentário a resposta será dirigido.

Para essa otimização não será preciso criar códigos personalizados, pois o próprio WordPress disponibiliza essas interações de JavaScript; no entanto serão precisos alguns ajustes no código responsável por listar os comentários. Atribua os identificadores como descrito:

echo '<li id="li-comment-' . $comment_id . '">';
echo '<div id="comment-' . $comment_id . '">';

Logo em seguida no arquivo de funções, juntamente com as demais incorporações de estilo e script, determine o uso das interações dos comentários:

if ( is_singular( 'post' ) ) // ou então is_single()
    wp_enqueue_script( 'comment-reply' );

Para não esquecer

  • Uso dos recursos inerentes ao WordPress: Menus, Formulário e resultados de busca, Widgets e funções prontas
  • Nomenclatura das funções
  • O Loop do WordPress e as funções get e the
  • Paginação dos resultados
  • Hierarquia do WordPress e as Conditional Tags
  • Manipulação dos comentários dentro do Tema