Su pregunta no es realmente sobre WordPress, es más sobre PHP y refactorización. Pero vemos mucho código malo aquí, y el patrón que explicaré a continuación (MVC) podría ayudar a muchos otros desarrolladores, así que decidí escribir una pequeña respuesta. Tenga en cuenta que hay un sitio dedicado para tales preguntas en nuestra red: Revisión de código . Desafortunadamente, muy pocos desarrolladores de WordPress están activos allí.
Cómo refactorizar el código
- Eliminar código inútil. Embellecer el resto.
- Encuentre todas las expresiones repetitivas y cree rutinas (funciones o clases) para abstraerlas y encapsularlas.
- Separar el manejo de datos, el modelo (almacenar, buscar, conversión, interpretación), de salida, la vista (HTML, CSV, lo que sea).
1. Eliminar el código inútil. Embellecer el resto.
La salida
Tienes este fragmento de repetición:
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
Ejecutas el bastante caro the_post()
cada vez para obtener la miniatura de la publicación. Pero eso no es necesario, solo puede llamar:
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
La consulta
Entonces, todo lo que necesita es la ID de publicación, y está disponible sin llamar the_post()
. Aún mejor: puede restringir la consulta para obtener solo los ID.
Un simple ejemplo:
$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
Ahora tiene las ID y puede escribir:
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
Sin gastos generales, su código ya es más rápido y fácil de leer.
La sintaxis
Tenga en cuenta cómo alineé el =
? Esto ayuda a comprender el código, porque la mente humana está especializada en el reconocimiento de patrones. Apoye eso y podemos hacer cosas increíbles. Crea un desastre y nos quedamos atrapados muy rápido.
Esta es también la razón por la que eliminé endwhile
y endif
. La sintaxis alternativa es desordenada y difícil de leer. Además, hace que trabajar en un IDE mucho más difícil: doblar y saltar desde el principio hasta el final de una expresión es más fácil con llaves.
Los valores por defecto
Su $args
matriz tiene algunos campos que usa en todas partes. Cree una matriz predeterminada y escriba esos campos solo una vez :
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
)
)
);
Nuevamente, observe la alineación. Y observe también cómo cambié el posts_per_page
valor.
Nunca pidas-1
. ¿Qué sucede cuando hay un millón de publicaciones coincidentes? No desea eliminar la conexión de su base de datos cada vez que se ejecuta esta consulta, ¿verdad? ¿Y quién debería leer todas estas publicaciones? Siempre establezca un límite razonable.
Ahora todo lo que tienes que cambiar es el campo $args[ 'tax_query' ][ 'terms' ]
. Lo cubriremos en un momento.
2. Encuentra todas las expresiones repetitivas y crea rutinas
Ya limpiamos un código repetitivo, ahora la parte difícil: la evaluación de los parámetros POST. Obviamente, ha realizado algunas etiquetas como resultado de algunos parámetros. Sugiero cambiarles el nombre a algo más fácil de entender, pero por ahora trabajaremos con su esquema de nombres.
Separe estos grupos del resto, cree una matriz que pueda administrar más adelante por separado:
$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 completar el terms
campo que falta en su matriz predeterminada, recorra la
$groups
matriz hasta encontrar una coincidencia:
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;
}
Separé incluso la ejecución de la lista de términos y la comparación de los valores, porque estas son operaciones diferentes. Cada parte de su código debe hacer una sola cosa, y debe mantener el nivel de sangría plano para una mejor legibilidad.
Ahora que tenemos todas las partes, peguémoslas juntas.
3. Organización: separe el modelo de la vista
Cuando escribí modelo y vista , tenía algo en mente: el enfoque MVC. Es sinónimo de Model View Controller , un patrón bien conocido para organizar componentes de software. La parte que faltaba hasta ahora era el controlador, veremos cómo lo usamos más adelante.
Dijiste que no sabes mucho sobre PHP, así que espero que sepas más sobre el resultado. :) Comencemos con eso:
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' );
}
}
Agradable y simple: tenemos dos métodos: uno para establecer la fuente de nuestras ID de publicaciones, otro para representar las miniaturas.
Quizás te preguntes qué Post_Collector_Interface
es esto . Llegamos a eso en un momento.
Ahora la fuente de nuestra vista, el 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;
}
}
Esto ya no es tan trivial, pero ya teníamos la mayor parte. Los protected
métodos (funciones) no son accesibles desde el exterior, porque los necesitamos solo para la lógica interna.
Los public
métodos son simples: el primero obtiene nuestra $group
matriz de arriba, el segundo devuelve una matriz de ID de publicación. Y de nuevo nos encontramos con este dudoso Post_Collector_Interface
.
Una interfaz es un contrato . Puede ser firmado (implementado) por clases. Que requiere una interfaz, como nuestra clase Thumbnail_List
hace, mediante: la clase espera alguna
otra clase con estos métodos públicos.
Construyamos esa interfaz. Es realmente simple:
interface Post_Collector_Interface
{
public function set_groups( Array $groups );
public function get_post_ids();
}
Sí, eso es todo. Código fácil, ¿no?
Lo que hicimos aquí: hicimos nuestra opinión Thumbnail_List
independiente de una clase concreta, mientras que todavía podemos confiar en los métodos de la clase que obtuvimos $source
. Si cambia de opinión más adelante, puede escribir una nueva clase para obtener los ID de las publicaciones o usar una con valores fijos. Mientras implemente la interfaz, la vista estará satisfecha. Incluso puede probar la vista ahora con un objeto simulado:
class Mock_Post_Collector implements Post_Collector_Interface
{
public function set_groups( Array $groups ) {}
public function get_post_ids()
{
return array ( 1 );
}
}
Esto es muy útil cuando quieres probar la vista. No desea probar ambas clases concretas juntas, porque no vería de dónde proviene un error. El objeto simulado es demasiado simple para errores, ideal para pruebas unitarias.
Ahora tenemos que combinar nuestras clases de alguna manera. Aquí es donde el controlador entra en escena.
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();
}
}
El controlador es la única parte real de una aplicación; el modelo y la vista pueden reutilizarse aquí y allá, incluso en partes completamente diferentes. Pero el controlador existe solo para este único propósito, es por eso que ponemos el$group
aquí.
Y ahora solo tienes que hacer una cosa:
// Let the dogs out!
new Thumbnail_Controller;
Llame a esta línea donde necesite la salida.
Puede encontrar todo el código de esta respuesta en esta esencia en GitHub .