Bei Ihrer Frage geht es nicht wirklich um WordPress, sondern eher um PHP und Refactoring. Aber wir sehen hier so viel schlechten Code, und das Muster, das ich unten erläutern werde (MVC), könnte vielen anderen Entwicklern helfen. Deshalb habe ich beschlossen, eine kleine Antwort zu schreiben. Beachten Sie, dass es in unserem Netzwerk eine spezielle Website für solche Fragen gibt: Code Review . Leider sind dort nur sehr wenige WordPress-Entwickler aktiv.
So überarbeiten Sie Code
- Entfernen Sie nutzlosen Code. Verschönere den Rest.
- Finden Sie alle sich wiederholenden Ausdrücke und erstellen Sie Routinen (Funktionen oder Klassen), um diese zu abstrahieren und zu kapseln.
- Trennen Sie die Datenverarbeitung, das Modell (Speichern, Abrufen, Konvertieren, Interpretieren) von der Ausgabe, die Ansicht (HTML, CSV, was auch immer).
1. Entfernen Sie unbrauchbaren Code. Verschönere den Rest.
Die Ausgabe
Sie haben dieses sich wiederholende Snippet:
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
Sie führen the_post()
jedes Mal das ziemlich teure aus , um das Post-Thumbnail zu erhalten. Aber das wird nicht benötigt, Sie können einfach anrufen:
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
Die Abfrage
Alles, was Sie brauchen, ist die Post-ID, die ohne Anruf verfügbar ist the_post()
. Noch besser: Sie können die Abfrage so einschränken, dass nur die IDs abgerufen werden.
Ein einfaches Beispiel:
$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
Jetzt haben Sie die IDs und können schreiben:
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
Kein Overhead, Ihr Code ist bereits schneller und einfacher zu lesen.
Die Syntax
Beachten Sie, wie ich das ausgerichtet habe =
? Dies hilft beim Verständnis des Codes, da der menschliche Geist auf die Mustererkennung spezialisiert ist. Unterstützen Sie das und wir können großartige Dinge tun. Erstellen Sie ein Chaos, und wir bleiben sehr schnell stecken.
Dies ist auch der Grund, warum ich endwhile
und entfernt habe endif
. Die alternative Syntax ist chaotisch und schwer zu lesen. Außerdem wird die Arbeit in einer IDE dadurch erheblich erschwert : Das Falten und Springen vom Anfang bis zum Ende eines Ausdrucks ist mit geschweiften Klammern einfacher.
Die Standardwerte
Ihr $args
Array enthält einige Felder, die Sie überall verwenden. Erstellen Sie ein Standardarray und schreiben Sie diese Felder nur einmal :
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
)
)
);
Beachten Sie auch hier die Ausrichtung. Und beachte auch, wie ich den posts_per_page
Wert geändert habe .
Fragen Sie niemals danach-1
. Was passiert, wenn es eine Million übereinstimmende Beiträge gibt? Sie möchten Ihre Datenbankverbindung nicht jedes Mal beenden, wenn diese Abfrage ausgeführt wird, oder? Und wer sollte all diese Beiträge lesen? Setzen Sie immer ein angemessenes Limit.
Jetzt müssen Sie nur noch das Feld ändern $args[ 'tax_query' ][ 'terms' ]
. Wir werden das gleich behandeln.
2. Finden Sie alle sich wiederholenden Ausdrücke und erstellen Sie Routinen
Wir haben bereits einige sich wiederholende Codes bereinigt, jetzt der schwierige Teil: die Auswertung der POST-Parameter. Offensichtlich haben Sie aufgrund einiger Parameter einige Beschriftungen vorgenommen. Ich schlage vor, diese in etwas umbenennenderes umzubenennen, aber im Moment werden wir mit Ihrem Namensschema arbeiten.
Trennen Sie diese Gruppen vom Rest und erstellen Sie ein Array, das Sie später separat verwalten können:
$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,
)
);
Um das fehlende terms
Feld in Ihrem Standardarray zu füllen , durchlaufen Sie das
$groups
Array, bis Sie eine Übereinstimmung finden:
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;
}
Ich habe sogar den Durchlauf durch die Termliste und den Vergleich der Werte getrennt, da es sich um unterschiedliche Operationen handelt. Jeder Teil Ihres Codes sollte nur eines tun, und Sie müssen die Einrückungsstufe flach halten, um die Lesbarkeit zu verbessern.
Jetzt haben wir alle Teile, lassen Sie uns sie zusammenkleben.
3. Organisation: Trennen Sie das Modell von der Ansicht
Als ich Modell und Ansicht schrieb , hatte ich etwas im Sinn: den MVC-Ansatz. Es steht für Model View Controller , ein bekanntes Muster zum Organisieren von Softwarekomponenten. Der bisher fehlende Teil war der Controller, wir werden später sehen, wie wir ihn verwenden.
Sie sagten, Sie wissen nicht viel über PHP, also hoffe ich, dass Sie mehr über die Ausgabe wissen. :) Fangen wir damit an:
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' );
}
}
Schön und einfach: Wir haben zwei Methoden: eine zum Festlegen der Quelle für unsere Post-IDs und eine zum Rendern der Miniaturansichten.
Sie fragen sich vielleicht, was das Post_Collector_Interface
ist. Wir kommen gleich dazu.
Nun die Quelle für unsere Ansicht, das Modell.
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;
}
}
Das ist nicht mehr so trivial, aber wir hatten schon die meisten Teile. Die protected
Methoden (Funktionen) sind von außen nicht zugänglich, da wir sie nur für die interne Logik benötigen.
Die public
Methoden sind einfach: Die erste ruft unser $group
Array von oben ab, die zweite gibt ein Array von Post-IDs zurück. Und wieder treffen wir diesen zweifelhaften Post_Collector_Interface
.
Eine Schnittstelle ist ein Vertrag . Es kann von Klassen signiert (implementiert) werden. Das Erfordernis einer Schnittstelle, wie es unsere Klasse Thumbnail_List
tut, bedeutet: Die Klasse erwartet eine
andere Klasse mit diesen öffentlichen Methoden.
Lassen Sie uns diese Schnittstelle erstellen. Es ist wirklich einfach:
interface Post_Collector_Interface
{
public function set_groups( Array $groups );
public function get_post_ids();
}
Ja, das ist alles. Einfacher Code, nicht wahr?
Was wir hier gemacht haben: Wir haben unsere Sichtweise Thumbnail_List
unabhängig von einer konkreten Klasse gemacht, während wir uns immer noch auf die Methoden der Klasse verlassen können, als die wir wurden $source
. Wenn Sie es sich später anders überlegen, können Sie eine neue Klasse schreiben, um die Post-IDs abzurufen, oder eine mit festen Werten verwenden. Solange Sie die Schnittstelle implementieren, ist die Ansicht zufriedenstellend. Sie können die Ansicht jetzt sogar mit einem Scheinobjekt testen:
class Mock_Post_Collector implements Post_Collector_Interface
{
public function set_groups( Array $groups ) {}
public function get_post_ids()
{
return array ( 1 );
}
}
Dies ist sehr nützlich, wenn Sie die Ansicht testen möchten . Sie möchten nicht beide konkreten Klassen zusammen testen, da Sie dann nicht sehen würden, woher ein Fehler kommt. Das Scheinobjekt ist zu einfach für Fehler, ideal für Unit-Tests.
Jetzt müssen wir unsere Klassen irgendwie kombinieren. Hier betritt der Controller die Bühne.
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();
}
}
Der Controller ist der einzig einzigartige Teil einer Anwendung. Das Modell und die Ansicht können hier und da auch in völlig anderen Teilen wiederverwendet werden. Aber der Controller existiert nur für diesen einen Zweck, deshalb setzen wir den $group
hier.
Und jetzt müssen Sie nur noch eines tun:
// Let the dogs out!
new Thumbnail_Controller;
Rufen Sie diese Leitung an, wo immer Sie die Ausgabe benötigen.
Sie finden den gesamten Code aus dieser Antwort in dieser Übersicht auf GitHub .