Adicionar link personalizado à tela de todas as postagens com base nos metadados da postagem
TL;DR: Este artigo descreve o código necessário para adicionar um link personalizado na tela Todas as postagens que usa uma parte personalizada de metadados de postagem.
Nota: Alguns meses atrás, escrevi um artigo sobre como adicionar uma visualização personalizada à tela Todas as postagens. Este artigo não é todos iguais, mas nem todos juntos são diferentes. Pense nisso como uma implementação mais detalhada e talvez mais prática do conceito.
Suponha que você tenha um tipo de postagem padrão ou um tipo de postagem personalizado e simplesmente filtre por um título que você define usando um mecanismo que permite salvar dados na post_metadatatabela.
Por exemplo, digamos que você tenha uma postagem e ela como um pedaço de metadados com:
- a
meta_keycom o valor dearticle_attribute - a
meta_valuecom o valor deheadline
E você deseja usar essas informações para adicionar um novo link de manchetes que filtra automaticamente tudo, exceto artigos com esses metadados.
Aqui está como fazê-lo.
Link personalizado na tela de todas as postagens
Antes de começar, vale a pena notar que existem duas maneiras de lidar com esse problema:
- Poderíamos adicionar o link na parte superior da página Todas as postagens primeiro e depois adicionar a funcionalidade para filtrar os dados em segundo lugar,
- Ou podemos fazer o contrário, onde adicionamos a lógica de back-end primeiro e depois adicionamos o link da página Todas as postagens .
Vou optar por começar com a segunda opção. Não há nenhuma razão para que tenha que ser feito desta forma. É minha preferência.
Primeiro, preciso me conectar ao [pre_get_posts](https://developer.wordpress.org/reference/hooks/pre_get_posts/)gancho fornecido pelo WordPress. Eu não vou usar nenhuma classe com namespace ou funções prefixadas neste exemplo (dado que eu cobri esse conteúdo o suficiente neste site), mas terei um plugin de demonstração para este link na parte inferior do post.
De qualquer forma, começarei adicionando uma função anônima anexada ao gancho mencionado acima:
add_action(
'pre_get_posts',
function (WP_Query $query) {
}
);
Observe que a função anônima aceita um único argumento que é uma referência à instância atual WP_Queryque está sendo executada na página. Se você não estiver familiarizado com essa classe, recomendo ler qualquer um desses artigos ou a página de recursos do desenvolvedor.
Na função, preciso verificar a presença de a meta_valuena string de consulta. Isso é fácil de fazer graças à [filter_input](https://www.php.net/manual/en/function.filter-input.php)função fornecida pelo PHP.
add_action(
'pre_get_posts',
function (WP_Query $query) {
$meta_value = 'headline';
if (filter_input( INPUT_GET, 'meta_value') === $meta_value) {
$query->set( 'meta_key', 'article_attribute' );
$query->set( 'meta_value', $meta_value );
}
}
);
Este gancho verificará se o headlinevalor é chave para a meta_valuechave na string de consulta. Em caso afirmativo, ele adiciona um meta_keye meta_valueà instância do WP_Queryqual instruirá o WordPress a recuperar todas as postagens apenas com esses metadados.
Depois disso, preciso adicionar um link no topo da página Todas as postagens para acionar essa funcionalidade. Para fazer isso, vou aproveitar o [views_edit-posts](https://tommcfarlin.com/add-a-custom-view/)gancho. Esta função aceitará uma matriz de âncoras que serão exibidas na parte superior da página.
Eu me refiro a isso, $viewsentão é isso que a função aceitará quando eu a apagar:
add_action(
'views_edit-post',
function (array $views) {
return $views;
}
);
Observe que é importante retornar o array de volta ao WordPress para que ele saiba o que renderizar, mesmo que nenhuma modificação seja feita.
Primeiro, preciso determinar se estou atualmente na página personalizada. Nesse caso, preciso adicionar os atributos apropriados à âncora adicionada ao topo da página:
$attributes = 'class=""';
if (filter_input(INPUT_GET, 'meta_value') === 'headline') {
$attributes ='class="current aria-current="page"';
}
Depois disso, preciso realmente adicionar a visualização Headlines à página. Isso exigirá o uso de várias funções:
[array_push](https://www.php.net/manual/en/function.array-push.php)para adicionar um novo link à lista de$views[sprintf](https://www.php.net/manual/en/function.sprintf.php)para adicionar com segurança uma nova string[add_query_arg](https://developer.wordpress.org/reference/functions/add_query_arg/)para adicionar um conjunto de argumentos de consulta personalizados à página atual.
A próxima seção de código ficará assim:
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s
<span class="count">(%4$s)</span>
</a>
',
add_query_arg([
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headline',
], 'edit.php'),
$attributes
__('Headlines'),
count( );
);
Mas ainda não terminei. Observe especificamente que estou fazendo uma chamada para [count](https://www.php.net/manual/en/function.count.php)no final da função. Isso é para que eu possa exibir corretamente o número de posts que possuem esse atributo.
Vou escrever duas funções auxiliares para isso e depois retornarei à sizeofchamada.
Aqui está uma função auxiliar para encontrar o número de resultados que tem o especificado meta_keye meta_valueque temos para este tipo de post. Observe que estou usando [$wpdb](https://developer.wordpress.org/reference/classes/wpdb/)para fazer uma chamada direta ao banco de dados e que estou usando especificamente [prepare](https://developer.wordpress.org/reference%2Fclasses%2Fwpdb%2Fprepare%2F/)para garantir que faço isso com segurança.
function get_headline_results(): array {
global $wpdb;
return $wpdb->get_results(
$wpdb->prepare(
"
SELECT post_id FROM $wpdb->postmeta
WHERE meta_key = %s AND meta_value = %s
",
'article_attribute',
'headline'
),
ARRAY_A
);
}
Observe que ele retorna todos os resultados (não apenas o número) porque esse valor será passado para outra função momentaneamente.
Neste ponto, poderíamos parar e simplesmente olhar para o conteúdo que é retornado da consulta, mas se estivermos preocupados apenas com o posttipo de postagem, precisaremos considerar isso. Aqui está uma maneira de fazer isso:
function filter_posts_from_pages( array $results ): array {
$post_ids = array();
foreach ($results as $result) {
if ('post' === get_post_type( $result['post_type'])) {
$post_ids[] = $result['post_id'];
}
}
return $post_ids;
}
Com isso, podemos retornar esse valor de volta para a countfunção acima.
A versão final do bloco que iniciamos acima deve ser algo assim:
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s <span class="count">(%4$s)</span></a>',
add_query_arg(
array(
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headlines',
),
'edit.php'
),
$attributes,
__( 'Headlines' ),
count(
filter_posts_from_pages( get_headline_results()) )) );
O que significa que a versão completa da função para adicionar um novo título se parece com isso:
add_action(
'views_edit-post',
function (array $views) {
$attributes = 'class=""';
if (filter_input( INPUT_GET, 'meta_value') === 'headline') {
$attributes = 'class="current aria-current="page"';
}
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s <span class="count">(%4$s)</span></a>',
add_query_arg(
array(
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headline',
),
'edit.php'
),
$attributes,
__( 'Headlines' ),
count(
filter_posts_from_pages( get_headline_results()) )) );
return $views;
}
);
E, como mencionado desde o início, este plugin não tem namespace ou está organizado de uma forma que eu normalmente escrevo código. Em vez disso, pretende demonstrar uma forma de alcançar algo rapidamente – uma espécie de protótipo.
Então, se você estiver interessado em ver algo assim em ação, você pode conferir o repositório no GitHub. Observe que é o ramo de desenvolvimento no momento. Lembre-se de ver o [README](https://github.com/tommcfarlin/custom-metadata-filter/blob/develop/README.md), pois ele fornecerá instruções sobre como adicionar dados ao banco de dados para postagens para que a âncora Headlines realmente funcione, em vez de mostrar incondicionalmente um valor zero.