Ao longo da minha carreira de desenvolvedor web, sempre me preocupei em deixar meus sites customizáveis e dinâmicos. Lá no início, usando apenas HTML e PHP, fui descobrindo ferramentas como o CuteNews, que permitiam a atualização do conteúdo das páginas de maneira fácil. Depois veio o Joomla e, por fim, o WordPress.
Mesmo gostando muito do WordPress, faltava uma ferramenta que permitisse atualizar qualquer parte do site de maneira fácil. Foi aí que aprendi a trabalhar com a Customize API (também conhecida como Theme Customizer).
A Customize API está disponível no WordPress desde a versão 3.4, de junho de 2012, ano em que eu comecei a trabalhar com o WordPress.
Trata-se de uma API super poderosa, que permite criar uma série de controles suportados nativamente, como caixas de seleção, caixas de texto, textarea, menus suspensos de páginas, inputs de vários tipos etc. Além disso, a classe WP_Customize_Control pode ser estendida para criação de novos tipos de controles.
Eu utilizo o Theme Customizer em todos os meus projetos e faço questão de incluir uma seção dedicada ao tema em todos os meus cursos e livros. Geralmente é o conteúdo que os alunos mais esperam aprender, devido ao potencial que ele traz a qualquer tema.
Neste artigo, vamos aprender o básico do funcionamento desta ferramenta.
Você pode ver uma versão em vídeo deste tutorial caso prefira:
Organização do Theme Customizer
O Theme Customizer é organizado em objetos, que são quatro:
Controls (controles): representam os diversos tipos de controles (campos) da interface de usuário, como caixas de textos, checkboxes, áreas de textos, inputs etc.
Settings: são responsáveis, entre outras coisas, por salvar o valor informado para cada controle no banco de dados. Também fazem a sanitização desses valores.
Sections (seções): na interface do usuário, correspondem a grupos de controles. Por exemplo, a seção “Identidade do Site” agrupa os controles para o logotipo do site, o título, a descrição e o ícone do site.
Panels (painéis): na interface do usuário, são grupos de seções. Por exemplo, dentro do painel “Widgets” você pode encontrar cada uma das seções que controlam a aparência de cada área de widgets do seu tema. Visualmente não existe diferença entre seções e painéis.
Internamente, cada objeto do Customizer é representado por uma classe PHP. Todos eles são administrados por um objeto da classe WP_Customize_Manager, responsável por chamar o método de acordo com o que está sendo criado (método add_section para criar seções; add_setting para settings; add_control para controles e add_panel para painéis). Veremos como isso acontece na prática criando um controle bastante simples para um texto de copyright, que poderia estar no rodapé de um tema.
Eu não falarei dos painéis, não apenas porque eles tornam a compreensão do código muito mais difícil, mas também porque é uma recomendação encontrada na documentação oficial. A equipe do WordPress recomenda que os temas não registrem seus próprios painéis na maioria dos casos.
Para que o código fique mais modularizado, crie uma pasta chamada inc na raiz do seu tema e, dentro dele, um arquivo com o nome de customizer.php. Inicie o arquivo apenas com a abertura das tags PHP. Assim:
<?php // O resto do código irá aqui
Agora, para integrar o arquivo ao fluxo do WordPress, pegaremos carona no arquivo functions.php, que é carregado automaticamente. Adicione esta linha para carregar o arquivo:
require_once get_template_directory() . '/inc/customizer.php';
Criando seções
Seções são containers para controles. Para adicionar uma seção para o copyright do tema, começamos criando uma função. Essa função deve receber como parâmetro um objeto chamado $wp_customize e ser disparada num gancho de ação de nome customize_register. Por exemplo, vamos criar a função codigowp_customizer:
function codigowp_customizer( $wp_customize ){ $wp_customize->add_section( 'sec_copyright', array( 'title' => 'Copyright Settings', 'description' => 'Copyright Section', ) ); } add_action( 'customize_register', 'codigowp_customizer' );
O primeiro parâmetro indicado é o identificador da seção. Costumo sempre identificar meus objetos com nomes que dizem respeito ao tipo de cada um. Para as seções, meus identificadores sempre começam com sec_. Para as settings, uso set_. Note que o id da primeira seção criada é sec_copyright.
O segundo parâmetro é um array, para o qual você pode passar alguns argumentos. No exemplo acima, usei os seguintes argumentos:
- title: string contendo o título da seção. Este texto é o que identificará visualmente a seção no Customizer.
- description: string contendo a descrição da seção. Aparecerá ao clicar na seção. Você pode optar por não passar esta opção caso o título da seção seja óbvio demais.
Existem argumentos adicionais. Você pode saber quais são eles lendo a documentação do WordPress em https://developer.wordpress.org/themes/customize-api/customizer-objects/#sections
Criando settings
Settings são os elementos de ligação entre os campos (controles) e o banco de dados. Sem elas é impossível persistir qualquer valor informado pelo usuário do tema. Elas também são essenciais para manter o banco de dados limpo e a salvo, uma vez que também servem para sanitizar as informações passadas pelo usuário.
Cada setting corresponde a um controle (campo). Logo, dentro de uma mesma seção, você terá um número de settings correspondente ao número de controles que desejar criar. No exemplo do copyright, teremos apenas uma setting, uma vez que precisaremos apenas de um controle, que será uma caixa de texto na qual o usuário informará algo.
Vamos registrar uma setting para o nosso controle único usando o método add_setting(). O código deve vir logo abaixo da seção, criada anteriormente, ainda dentro da função codigowp_customizer():
$wp_customize->add_setting( 'set_copyright', array( 'type' => 'theme_mod', 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ) );
O primeiro parâmetro é o identificador da setting (set_copyright). O segundo é um array de argumentos:
- type: settings podem ser de dois tipos, ‘theme_mod’ ou ‘option’. A diferença é que o primeiro tipo diz respeito apenas ao tema que está registrando a setting e está ativo. O segundo é mais abrangente e se aplica ao site como um todo, independente do tema que está ativo. Valores das settings do tipo ‘option’ ficam guardados diretamente na tabela wp_options. O primeiro tipo também guarda valores na mesma tabela, mas de forma serializada num campo que inicia com theme_mods_, seguido pelo nome do diretório correspondente ao tema ativo (por exemplo: theme_mods_diretoriodoseutema). De acordo com a documentação, temas devem adicionar settings do tipo ‘option’ muito raramente. Prefira sempre ‘theme_mod’.
- default: um valor padrão para o controle. Ele aparecerá no controle quando o usuário não tiver informado nenhum valor, mas apenas no backend.
- sanitize_callback: nome de uma função callback para sanitizar o valor passado pelo usuário. Este argumento merece um pouco mais de atenção.
Sanitize Callback
Você está criando uma interface entre o usuário do tema e o banco de dados. Portanto, você nunca deve confiar no tipo de dados que o usuário informará. Como um bom desenvolvedor, você deverá sanitizar (limpar) ao máximo os dados que o dono do site envia para o banco usando qualquer tipo de controle.
O argumento sanitize_callback nada mais é do que o nome de uma função que limpa, sanitiza, os dados inseridos pelo usuário.
Por exemplo, vamos supor que o seu tema ofereça um controle para que o usuário informe o ID válido de uma categoria. Uma vez que um ID deve ser um valor numérico, você não deve permitir que o campo seja salvo com valores de tipo diferente (strings, por exemplo).
O WordPress possui uma série de filtros nativos (funções) que podem ser utilizados para isso. Tais filtros são definidos globalmente e podem ser chamados em qualquer lugar do código. Exemplos de filtros que podem ser usados são:
- absint: sanitiza valores que devem ser numéricos. Serve também para o controle do tipo dropdown-pages.
- wp_filter_nohtml_kses: para campos do tipo text e textarea.
- sanitize_text_field: também sanitiza campos do tipo texto.
- sanitize_email: sanitiza campos de email.
- esc_url_raw: sanitiza URLs.
- wp_strip_all_tags: sanitiza CSS.
- sanitize_hex_color: sanitiza códigos retornados por seletores de cores.
- wp_kses_post: sanitiza conteúdo HTML deixando apenas tags válidas.
Além destas existem várias outras possibilidades. Uma lista com exemplos pode ser encontrada na página da equipe de revisão de temas do WordPress (WPTRT) no GitHub: https://github.com/WPTRT/code-examples/tree/master/customizer
É possível também criar as suas próprias funções callback. Muitas vezes será necessário fazer isso, já que você não encontrará um filtro nativo capaz de sanitizar o controle que você está criando. O site DivPusher tem alguns exemplos muito bons:
https://divpusher.com/blog/wordpress-customizer-sanitization-examples/
No último trecho de código (acima), a função sanitizadora escolhida foi sanitize_text_field, uma vez que a setting criada corresponderá a um simples campo de texto. A sanitize_text_field retira todo o HTML do conteúdo digitado pelo usuário, deixando apenas texto simples. Assim, se o usuário escrever código HTML, ele será sanitizado e apenas conteúdo em formato texto será enviado para o banco de dados.
Criando controles
Controles são os objetos principais da interface do usuário. Grosso modo, são os campos para os quais o usuário passará algum valor.
Cada um deles é associado a uma setting e criado através do método add_control.
Vamos registrar um controle tipo texto para a seção copyright:
$wp_customize->add_control( 'set_copyright', array( 'label' => 'Copyright', 'description' => 'Please, add your copyright information here', 'section' => 'sec_copyright', 'type' => 'text', ) );
O primeiro parâmetro do método é o identificador da setting a qual pertence o controle. No caso do código acima, o controle registrado pertence à setting que possui o identificador ‘set_copyright’.
O segundo parâmetro é um array com os seguintes argumentos:
- label: uma string que define um rótulo para o controle.
- description: uma string com uma descrição para o controle.
- section: id da section a qual pertence o controle. No caso, indicamos ‘sec_copyright’, já que o controle deve aparecer ao clicar nesta seção.
- type: tipo de controle. Os tipos disponíveis no core do WordPress (até o momento em que escrevo este post) são: checkbox, textarea, radio, select, dropdown-pages (lista de páginas da instalação), campos do tipo input como text, hidden, number, range, url, tel, email, search, time, date, datetime, e week.
É possível registrar novos tipos de campos extendendo a classe WP_Customize_Control, ou usar alguns campos mais complexos já disponíveis no core. Alguns exemplos podem ser encontrados aqui https://developer.wordpress.org/themes/customize-api/customizer-objects/#core-custom-controls e aqui https://make.wordpress.org/core/2015/07/16/new-customizer-media-controls-in-4-3-and-4-2/
O código final do nosso primeiro campo ficará assim:
<?php function codigowp_customizer( $wp_customize ){ $wp_customize->add_section( 'sec_copyright', array( 'title' => 'Copyright Settings', 'description' => 'Copyright Section', 'priority' => 160, ) ); $wp_customize->add_setting( 'set_copyright', array( 'type' => 'theme_mod', 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ) ); $wp_customize->add_control( 'set_copyright', array( 'label' => 'Copyright', 'description' => 'Please, add your copyright information here', 'section' => 'sec_copyright', 'type' => 'text' ) ); } add_action( 'customize_register', 'codigowp_customizer' );
Abrindo o Customizer, você observará uma nova seção chamada “Copyright Settings”:
Clicando nela, você verá o primeiro e único campo desta seção:
Mostrando valores no frontend
A esta altura, você apenas tem a estrutura pronta para receber dados na interface do usuário. Neste momento não existe nenhuma informação guardada no banco de dados.
Se você checar a tabela wp_options, encontrará uma opção de nome theme_mods_diretoriodoseutema, mas nenhuma informação relativa ao campo que acabou de registrar. Essa informação só estará disponível quando você digitar algo na caixa de texto e publicar.
Ao fazer isso, a setting sanitizará a informação passada no formulário e guardará a informação no banco de maneira serializada. Por exemplo:
s:13:"set_copyright";s:45:"Copyright 2020 - Todos os direitos reservados";
A partir deste momento, podemos manipular essa informação, mostrando-a no rodapé da página ou em qualquer outro lugar do tema.
Para isso, você poderá usar o arquivo footer.php do seu tema. Mas pode usar qualquer arquivo de template para realizar o teste. Um exemplo:
<div class="copyright-text"> <p><?php echo get_theme_mod( 'set_copyright', 'Copyright X - All Rights Reserved' ); ?></p> </div>
Perceba que estamos dando echo numa função chamada get_theme_mod(). Esta função deve ser usada todas as vezes que você desejar mostrar o conteúdo de um campo cuja setting correspondente é do tipo ‘theme_mod’. Para settings do tipo ‘option’ (menos comum em temas) você deve usar get_option().
Tanto uma quanto outra aceitam dois parâmetros. O primeiro é o id da setting correspondente ao controle cujo valor você quer recuperar. No nosso caso, ‘set_copyright’.
O segundo parâmetro (opcional) é um valor padrão para o campo quando ainda não existe nenhum valor definido para ele.
Ao definir um valor padrão, o usuário do seu tema poderá ver algo na tela, mesmo antes de ele ter entrado no Customizer e informado algum valor para o campo. Lembre-se que só existem valores no banco de dados quando a informação é salva pela primeira vez. Antes disso, não existe nada.
De acordo com a documentação, este parâmetro pode ser uma string ou booleano. Porém, na minha experiência prática, notei que também funciona com valores inteiros.
Agora você pode fazer os testes diretamente no personalizador. Você perceberá que a informação no rodapé mudará automaticamente, conforme você digita a informação desejada.
Pronto! Você tem o primeiro campo altamente dinâmico do seu tema! Com base no que você aprendeu até aqui, pode começar a pensar em várias possibilidades para os seus próprios temas, criando controles de tipos diferentes, para aplicações igualmente distintas.
O que achou da ideia?
Você pode ver um exemplo um pouco mais prático neste post, que ensina a adicionar um mapa no tema sem o uso de plugins.
Complimenti per il video spiegato bene e con codice lineare e pulito
Grazie Mille 🙂
Melhor artigo sobre o assunto que consegui encontrar, muito obrigado.
Que bom, caro Augusto! Fico contente por poder ser útil.
Cara! Você é demais. Mesmo quando procuro soluções na net sobre WordPress, acabo encontrando em seu site. Seus cursos são excelentes. Mas, queria incluir novas opções para o tema do site. Procurei muito. Muito mesmo, pois não queria incomodá-lo fazendo perguntas no próprio curso. Qual não foi minha surpresa de encontrar a solução aqui. Só ai me dei conta que era você. Como já virou rotina, muito obrigado.
Abraços,
Léo
Sério!?!?!? Hahahaha, é muito bom saber disso. Me dá mais vontade de continuar botando material aqui no blog.
Obrigado pelas mensagens e elogios, como sempre, meu amigo Léo!