
A vitrine ordenada por preço mostra 1200 logo antes de 89, e não é bug do tema. O valor mora na wp_postmeta, cuja coluna meta_value é longtext, e texto ordena caractere por caractere: “1200” vem antes de “89” pelo mesmo motivo que “ab” vem antes de “b”. A correção é uma palavra: troque meta_value por meta_value_num no orderby.
<?php
$q = new WP_Query( [
'post_type' => 'produto',
'posts_per_page' => 12,
'meta_key' => 'preco',
'orderby' => 'meta_value_num',
'order' => 'ASC',
] ); O meta_key é obrigatório aqui, senão o WordPress não sabe qual linha da postmeta juntar. Por baixo, o WP_Query 6.9 monta o ORDER BY como meta_value+0, o que joga a string para número no próprio MySQL 8. Efeito colateral: esse meta_key gera um INNER JOIN, então produto sem o campo preco some da lista.
<?php
$q = new WP_Query( [
'post_type' => 'produto',
'posts_per_page' => 12,
'meta_query' => [
'relation' => 'OR',
'com_preco' => [
'key' => 'preco',
'type' => 'DECIMAL(10,2)',
'compare' => 'EXISTS',
],
'sem_preco' => [
'key' => 'preco',
'compare' => 'NOT EXISTS',
],
],
'orderby' => [ 'com_preco' => 'ASC' ],
] ); Dando nome à cláusula, o orderby aceita esse nome direto. E aqui mora a pegadinha que me pegou: ordenando por cláusula nomeada, o WordPress usa CAST(meta_value AS ...) com o type que você declarou — e NUMERIC vira SIGNED lá dentro, que corta os centavos. Com preço, peça DECIMAL(10,2); o 19,90 e o 19,99 dependem disso.
Quem cai no ramo NOT EXISTS entra com valor nulo e, em ASC, o MySQL 8 coloca nulo na frente de tudo. Se esses tiverem que ficar no fim da vitrine, ordene DESC ou grave zero no campo na hora de salvar o produto. E confira o valor cru na tabela antes de caçar plugin: campo gravado com R$ na frente ou vírgula no lugar do ponto continua saindo torto, porque a conversão para no primeiro caractere que não é número.
Padrão registrado no functions.php que não aparece na aba Padrões. O caminho curto do WordPress 6.9: um arquivo PHP na…
Disco lotando por causa do banco? Uma query no information_schema mostra qual tabela cresceu, quanto é dado, quanto é índice…
Sistema em CodeIgniter 3.1.13 morre no primeiro request depois do upgrade. Os três pontos que quebram no PHP 8.3 e…
Metade do seu pub/media é miniatura descartável. Veja o rsync com os excludes certos e o comando que reconstrói o…
Tire os snippets do functions.php e coloque num must-use plugin: carrega sempre, sobrevive à atualização do tema e ninguém desativa…
Quando o valor novo depende do que a regex achou, preg_replace não resolve. Exemplo real aplicando 10% de desconto em…