Sua pergunta não é realmente sobre WordPress, é mais sobre PHP e refatoração. Mas vemos muito código ruim aqui, e o padrão que explicarei abaixo (MVC) pode ajudar muitos outros desenvolvedores, então decidi escrever uma pequena resposta. Lembre-se de que existe um site dedicado a essas perguntas em nossa rede: Revisão de código . Infelizmente, muito poucos desenvolvedores do WordPress estão ativos lá.
Como refatorar código
- Remova o código inútil. Embeleze o resto.
- Encontre todas as expressões repetidas e crie rotinas (funções ou classes) para abstrair e encapsular essas.
- Separe a manipulação de dados, o modelo (armazenar, buscar, conversão, interpretação), da saída, a visualização (HTML, CSV, qualquer que seja).
1. Remova o código inútil. Embeleze o resto.
A saída
Você tem este trecho repetido:
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
Você executa o bastante caro the_post()
cada vez para obter a miniatura da postagem. Mas isso não é necessário, basta ligar para:
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
A pergunta
Então, tudo que você precisa é o ID da postagem, e isso está disponível sem ligar the_post()
. Ainda melhor: você pode restringir a consulta para buscar apenas os IDs.
Um exemplo simples:
$post_ids = array();
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'fields' => 'ids'
);
$query = new WP_Query( $args );
if ( ! empty ( $query->posts ) )
$post_ids = $query->posts; // just the post IDs
Agora você tem os IDs e pode escrever:
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
Sem custos adicionais, seu código já é mais rápido e fácil de ler.
A sintaxe
Observe como eu alinhei o =
? Isso ajuda a entender o código, porque a mente humana é especializada em reconhecimento de padrões. Apoie isso e podemos fazer coisas incríveis. Crie uma bagunça, e ficamos presos muito rápido.
Esta é também a razão pela qual eu removi endwhile
e endif
. A sintaxe alternativa é confusa e difícil de ler. Além disso, torna o trabalho em um IDE muito mais difícil: dobrar e pular do início ao fim de uma expressão é mais fácil com aparelhos.
Os valores padrão
Sua $args
matriz possui alguns campos que você usa em qualquer lugar. Crie uma matriz padrão e escreva esses campos apenas uma vez :
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
)
)
);
Mais uma vez, observe o alinhamento. E observe também como mudei o posts_per_page
valor.
Nunca peça-1
. O que acontece quando há um milhão de postagens correspondentes? Você não deseja eliminar sua conexão com o banco de dados toda vez que essa consulta for executada, não é? E quem deve ler todos esses posts? Sempre defina um limite razoável.
Agora tudo que você precisa mudar é o campo $args[ 'tax_query' ][ 'terms' ]
. Nós vamos cobrir isso em um momento.
2. Encontre todas as expressões repetidas e crie rotinas
Já limpamos alguns códigos repetidos, agora a parte mais difícil: a avaliação dos parâmetros do POST. Obviamente, você criou alguns rótulos como resultado de alguns parâmetros. Sugiro renomeá-los para algo mais fácil de entender, mas, por enquanto, trabalharemos com seu esquema de nomes.
Separe esses grupos dos demais, crie uma matriz que você possa gerenciar posteriormente separadamente:
$groups = array(
'fashion-follower' => array(
'q1' => 'party',
'q2' => 'clothes',
'q3' => 'shopping',
'q4' => FALSE,
'q5' => 'sunbathing',
'q6' => 'mini',
),
'the-homemaker' => array(
'q1' => 'drink',
'q2' => 'candles',
'q3' => 'house',
'q4' => 'diy',
'q5' => FALSE,
'q6' => FALSE,
)
);
Para preencher o terms
campo ausente na matriz padrão, você percorre a
$groups
matriz até encontrar uma correspondência:
function get_query_term( $groups )
{
foreach ( $groups as $term => $values )
{
if ( compare_group_values( $values ) )
return $term;
}
return FALSE;
}
function compare_group_values( $values )
{
foreach ( $values as $key => $value )
{
// Key not sent, but required
if ( empty ( $_POST[ $key ] ) and ! empty ( $value ) )
return FALSE;
// Key sent, but wrong value
if ( ! empty ( $_POST[ $key ] ) and $_POST[ $key ] !== $value )
return FALSE;
}
// all keys matched the required values
return TRUE;
}
Separei até a execução da lista de termos e a comparação dos valores, porque essas são operações diferentes. Cada parte do seu código deve fazer apenas uma coisa, e você deve manter o nível de indentação plano para melhor legibilidade.
Agora temos todas as partes, vamos juntá-las.
3. Organização: separe o modelo da visualização
Quando escrevi model e view , eu tinha algo em mente: a abordagem MVC. Representa o Model View Controller , um padrão conhecido para organizar componentes de software. A parte que faltava até agora era o controlador, veremos como usá-lo mais tarde.
Você disse que não sabe muito sobre PHP, então espero que saiba mais sobre a saída. :) Vamos começar com isso:
class Thumbnail_List
{
protected $source;
public function set_source( Post_Collector_Interface $source )
{
$this->source = $source;
}
public function render()
{
$post_ids = $this->source->get_post_ids();
if ( empty ( $post_ids ) or ! is_array( $post_ids ) )
return print 'Nothing found';
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
}
}
Agradável e simples: temos dois métodos: um para definir a origem dos nossos IDs de postagem, um para renderizar as miniaturas.
Você pode se perguntar o que Post_Collector_Interface
é isso . Chegamos a isso em um momento.
Agora, a fonte da nossa visão, o modelo.
class Post_Collector implements Post_Collector_Interface
{
protected $groups = array();
public function set_groups( Array $groups )
{
$this->groups = $groups;
}
public function get_post_ids()
{
$term = $this->get_query_term();
if ( ! $term )
return array();
return $this->query( $term );
}
protected function query( $term )
{
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $term
)
)
);
$query = new WP_Query( $args );
if ( empty ( $query->posts ) )
return array();
return $query->posts;
}
protected function get_query_term()
{
foreach ( $this->groups as $term => $values )
{
if ( compare_group_values( $values ) )
return $term;
}
return FALSE;
}
protected function compare_group_values( $values )
{
foreach ( $values as $key => $value )
{
// Key not sent, but required
if ( empty ( $_POST[ $key ] ) and ! empty ( $value ) )
return FALSE;
// Kent sent, but wrong value
if ( ! empty ( $_POST[ $key ] ) and $_POST[ $key ] !== $value )
return FALSE;
}
// all keys matched the required values
return TRUE;
}
}
Isso não é mais tão trivial, mas já tínhamos a maioria das partes. Os protected
métodos (funções) não são acessíveis externamente, porque precisamos deles apenas para a lógica interna.
Os public
métodos são simples: o primeiro obtém nossa $group
matriz de cima, o segundo retorna uma matriz de IDs de postagem. E novamente encontramos esse duvidoso Post_Collector_Interface
.
Uma interface é um contrato . Pode ser assinado (implementado) por classes. Exigir uma interface, como a nossa classe Thumbnail_List
, significa: a classe espera alguma
outra classe com esses métodos públicos.
Vamos construir essa interface. É realmente simples:
interface Post_Collector_Interface
{
public function set_groups( Array $groups );
public function get_post_ids();
}
Sim, isso é tudo. Código fácil, não é?
O que fizemos aqui: tornamos nossa visão Thumbnail_List
independente de uma classe concreta, enquanto ainda podemos confiar nos métodos da classe que obtivemos $source
. Se você mudar de idéia mais tarde, poderá escrever uma nova classe para buscar os IDs de postagem ou usar uma com valores fixos. Contanto que você implemente a interface, a visualização será satisfeita. Você pode até testar a exibição agora com um objeto simulado:
class Mock_Post_Collector implements Post_Collector_Interface
{
public function set_groups( Array $groups ) {}
public function get_post_ids()
{
return array ( 1 );
}
}
Isso é muito útil quando você deseja testar a exibição. Você não deseja testar as duas classes concretas juntas, porque não verá de onde vem um erro. O objeto simulado é muito simples para erros, ideal para testes de unidade.
Agora temos que combinar nossas aulas de alguma forma. É aqui que o controlador entra no palco.
class Thumbnail_Controller
{
protected $groups = array(
'fashion-follower' => array(
'q1' => 'party',
'q2' => 'clothes',
'q3' => 'shopping',
'q4' => FALSE,
'q5' => 'sunbathing',
'q6' => 'mini',
),
'the-homemaker' => array(
'q1' => 'drink',
'q2' => 'candles',
'q3' => 'house',
'q4' => 'diy',
'q5' => FALSE,
'q6' => FALSE,
)
);
public function __construct()
{
// not a post request
if ( 'POST' !== $_SERVER[ 'REQUEST_METHOD' ] )
return;
// set up the model
$model = new Post_Collector;
$model->set_groups( $this->groups );
// prepare the view
$view = new Thumbnail_List;
$view->set_source( $model );
// finally render the tumbnails
$view->render();
}
}
O controlador é a única parte real real de uma aplicação; o modelo e a vista podem ser reutilizados aqui e ali, mesmo em partes completamente diferentes. Mas o controlador existe apenas para esse propósito único, é por isso que colocamos $group
aqui.
E agora você precisa fazer apenas uma coisa:
// Let the dogs out!
new Thumbnail_Controller;
Ligue para essa linha sempre que precisar da saída.
Você pode encontrar todo o código desta resposta nesta lista no GitHub .