Entwicklung eines WordPress Search Plugins – Best Practices

Nach ungefähr zwei Tagen suchend, um eine Antwort auf meine Frage zu finden, habe ich mich für diesen StackExchange registriert. 🙂

Meine Frage ist nicht einfach, also muss ich ganz am Anfang anfangen. Aber um dir eine Vorstellung davon zu geben, worum es in dieser Post geht: Mittlerweile funktioniert mein Plugin, aber ich mag den Code nicht. Ich denke, es gibt bessere Möglichkeiten, dies zu lösen, und so suche ich nach WordPress Ninjas, die mir mit guten Tipps und Best Practices helfen können. Ich versuche wirklich, in die Tiefen von WordPress zu kommen, aber es ist irgendwie hart. Vielen Dank im Voraus!


Was mein Plugin tun sollte

Der Benutzer dieses Plugins sollte einen Shortcode verwenden können, um ein Suchformular für bestimmte Post-Typen anzuzeigen. Das Plugin wird nur auf den Seiten benötigt, die diesen Shortcode enthalten.

Die Post-Typen werden über die Plugin-Einstellungsseite erstellt. Jeder Beitrag dieses Typs hat einen Titel, einen Inhalt und mehrere benutzerdefinierte Felder aus dem acf-Plugin. Es gibt einen Shortcode für jeden Posttyp. Das Suchformular hat ein Feld, um alle Post-Felder des angegebenen Post-Typs zu durchsuchen. Die anderen beiden können verwendet werden, um die Ergebnisse durch zwei Schlüsselwörter zu begrenzen (zum Beispiel den Ort, der ein acf-Feld ist).

Die Ergebnisse werden über Ajax geladen und unterhalb des Suchformulars angezeigt.


Was ich schon gemacht habe

Ich versuche diese Frage nicht zu groß zu halten. Ich spezifiziere also nicht jeden einzelnen Aspekt. Folgendes sollte gut funktionieren:

  • Erstellen Sie bei Post-Typ in der PHP-Datei des Plugins. Für den Moment ist ein statischer Posttyp enaug.
  • Erstellen Sie einen Shortcode, der das Suchformular und einen leeren Container für die Ergebnisse ausgibt.
  • Die Ajax-Anfrage funktioniert über Javascript und liefert die erwarteten Ergebnisse.

Suche nach benutzerdefinierten Feldern

Das war ziemlich schwierig, aber ich fand einen funktionierenden Code-Ausschnitt und ich verstehe, was er macht. Das Problem hier ist, dass ich nur acf Felder mit meiner spezifischen Suchform suchen möchte. Ich möchte die Suche der vorhandenen Website nicht berühren.

Zuerst habe ich versucht zu überprüfen, auf welcher Seite der Benutzer ist und eine if-statement mit is_page () zu verwenden, bevor ich die Suchanfrage ändere. Aber wenn ich Ajax benutze, scheint das hier nicht zu funktionieren …

Meine Problemumgehung besteht darin, zu Beginn jeder Ajax-Suchanfrage eine globale Variable festzulegen. Jetzt überprüfe ich, ob diese Variable gesetzt ist, bevor ich die Suchanfrage ändere. Am Ende meiner Ajax-function setze ich diese Variable auf false zurück. Ja, ich denke es gibt einen besseren Weg dies zu lösen, aber ich weiß nicht wie …

Die functionen, die meine Suchanfrage ändern, sind folgende:

 / **
  Erweitern Sie die WordPress-Suche um benutzerdefinierte Felder
  *
  * http://adambalee.com
  * /

 / **
  * Join Beiträge und postmeta Tabellen
  *
  * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
  * /
 function cf_search_join ($ join) {
     global $ wpdb;
     // $ cwlistpage = (is_page ('list'));

     global $ testcheck;
     $ cwlistpage = $ testcheck;

     if ($ cwlistpage) {    
         $ join. = 'LINKE VERBINDUNG'. $ wpdb-> postmeta.  ' AUF '.  $ wpdb-> Beiträge.  '.ID ='.  $ wpdb-> postmeta.  '.post_id';
     }

     return $ beitreten;
 }
 add_filter ('posts_join', 'cf_search_join');

 / **
  * Ändern Sie die Suchanfrage mit posts_where
  *
  * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
  * /
 function cf_search_where ($ wo) {
     global $ pagenow, $ wpdb;
     // $ cwlistpage = (is_page ('list'));

     global $ testcheck;
     $ cwlistpage = $ testcheck;

     if ($ cwlistpage) {
         $ wo = preg_replace (
             "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
             "(". $ wpdb-> Beiträge. ". post_title LIKE $ 1) ODER (". $ wpdb-> postmeta. ". meta_value LIKE $ 1)", $ where);
     }

     Rückgabe $ wo;
 }
 add_filter ('posts_where', 'cf_search_where');

 / **
  * Duplikate verhindern
  *
  * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
  * /
 function cf_search_distinct ($ wo) {
     global $ wpdb;
     // $ cwlistpage = (is_page ('list'));

     global $ testcheck;
     $ cwlistpage = $ testcheck;

     if ($ cwlistpage) {
         Rückgabe "DISTINCT";
     }

     Rückgabe $ wo;
 }
 add_filter ('posts_distinct', 'cf_search_distinct');

Begrenzen Sie die Ergebnisse nach benutzerdefinierten Feldern

Alle Felder des Formulars sind optional. Ein leeres Formular gibt alle Posts dieses Post-Typs zurück. Das erste Feld sollte jedes Feld der Posts nach dem Schlüsselwort durchsuchen. Das zweite und dritte Feld sollte die Ergebnisse auf dasjenige beschränken, das dieses Schlüsselwort enthält. Ich habe das mit if-statements getriggers und weiß, dass es eine bessere Lösung geben muss.

/** * Search with AJAX */ function cwlist_click_search() { global $testcheck; $testcheck = true; $searchterm = $_POST['query']; $searchlocation = $_POST['location']; $searchdegree = $_POST['degree']; // WP_Query arguments $args = array ( 'post_type' => 'offers', 'post_status' => 'publish', 's' => $searchterm ); $query = new WP_Query( $args ); ob_start(); // The Loop if ( $query->have_posts() ) : ?> 

have_posts() ) : $query->the_post(); if( ($searchlocation == NULL) || in_array(trim(strtolower($searchlocation)), array_map('strtolower', get_field('offer_location')))): if( ($searchdegree == NULL) || (trim(strtolower($searchdegree)) === strtolower(get_field('offer_degree')))):?> Titel:
Abschluss:
Ort:
Anbieter:
-

Keine Angebote gefunden <?php endif; // Restore original Post Data wp_reset_postdata(); $content = ob_get_clean(); echo $content; die(); $testcheck = false; } add_action( 'wp_ajax_nopriv_cwlist_click_search', 'cwlist_click_search' ); add_action( 'wp_ajax_cwlist_click_search', 'cwlist_click_search' );

WP Debug

Wenn ich das Plugin aktiviere, erscheinen auf der Titelseite viele Zeilen wie die folgende:

Hinweis: Versuch, Eigenschaft von Nicht-Objekt in C: \ Benutzer \ CWalt \ Dokumente \ gitlab \ steurerazubi \ wordpress \ wp-includes \ query.php in Zeile 4520 zu erhalten Hinweis: versucht, Eigenschaft von Nichtobjekt in C: \ zu erhalten Users \ CWalt \ Dokumente \ gitlab \ steurerazubi \ wordpress \ wp-includes \ query.php in Zeile 4522 Hinweis: Der Versuch, die Eigenschaft von non-object in C: \ Benutzer \ CWalt \ Documents \ gitlab \ steurerazubi \ wordpress \ wp- zu erhalten enthält \ query.php in Zeile 4524 …

Ich habe das Debuggen aktiviert, um ein gutes Plugin zu erstellen. Was könnte ich möglicherweise falsch gemacht haben?


Mehr Beitragstypen

Kennen Sie einen guten Ansatz, um dem Benutzer mehr Post-Typen über das WordPress-Backend zu geben? Der Benutzer sollte in der Lage sein, verschiedene Suchseiten für verschiedene Beitragstypen über Kurzwahlnummern zu erstellen.


Vielen Dank fürs Lesen. Ich bin dankbar für jeden kleinen Hinweis.

Solutions Collecting From Web of "Entwicklung eines WordPress Search Plugins – Best Practices"

Ich habe deinen Beitrag in seiner Gesamtheit durchgelesen, ich sehe sicherlich nichts besonders falsch, aber es klingt für mich eher frustriert darüber, wie es angelegt wurde.

Ich persönlich habe einen großen objektorientierten Programmierhintergrund, es erlaubt mir, eine Struktur aufzubauen und macht meinen Code viel wiederverwendbarer. Mein Vorschlag an Sie wäre, einen objektorientierten Ansatz für Ihr nächstes Plugin zu versuchen, oder die Umstrukturierung dieses Plugins, über das Sie in der ursprünglichen Frage geschrieben haben.

WordPress Plugin Boiler Plate ist was ich von ganzem Herzen empfehle. Ich fange normalerweise an, zu wwpb.me zu gehen , um ein Modul für mich selbst zu erzeugen, das funktionstüchtig ist, fülle einfach das Formular aus, lade es herunter und entpacke es in dein Plugins-Verzeichnis deiner WordPress-Installation.

Sobald Sie Ihr Laufskelett an Ort und Stelle haben, würde ich vorschlagen, dieses Tutorial zu lesen, es ist eine großartige Anleitung, wie Sie das gerade heruntergeladene Laufskelett aufbauen können:

Beschleunigen Sie die Entwicklung mit dem WordPress Plugin Boilerplate pt1

Das WordPress Plugin Boilerplate Teil 2: Ein Plugin entwickeln

Das WordPress Plugin Boilerplate Teil 3: Die letzten Schritte

Nachdem ich mich selbst kurz eingelesen habe, möchte ich normalerweise eine Datenklasse erstellen, in der alle meine benutzerdefinierten databaseabfragen gespeichert sind, wie:

 < ?php class example_Events_Data { private $wpdb; public function __construct() { global $wpdb; $this->wpdb = $wpdb; } public function get_events($start_date = null, $end_date = null) { $query = "SELECT wp_example_event.id, wp_example_event.name, wp_example_event.description, wp_example_event.date, wp_example_event.end_date, wp_example_event_type.id as event_type_id, wp_example_event_type.type as event_type FROM wp_example_event JOIN wp_example_event_type on wp_example_event.type_id = wp_example_event_type.id ORDER BY wp_example_event.name ASC"; $events = $this->wpdb->get_results($query, ARRAY_A); return $events; } 

Dann, um dies in Ihren Admin / Public-Controller zu verwenden, ist es so einfach wie:

  < ?php class Example_Events_Admin { /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; private $data; private $utils; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. */ public function __construct( $plugin_name, $version ) { $this->plugin_name = $plugin_name; $this->version = $version; $this->data = new example_Events_Data(); } 

Ich mag es auch, mir selbst eine Utility-class zu erstellen, die sehr häufige functionen in meinem Plugin enthält, wie zum Beispiel Formularvalidierungsregeln, die auf die gleiche Weise implementiert und verwendet werden.

Sie fügen sie einfach in Ihre Hauptplugin-Datei mit require_once ein und instanziieren sie wo nötig.

Die Verwendung der Datenklasse ermöglicht es mir, alle meine Datenanrufe an einer Stelle zu zentralisieren und sie während der Entwicklung des Plugins zu verwenden.

Die Verwendung dieser Methoden hat meine Entwicklungszeit erheblich verkürzt und meine Plugins wesentlich einfacher zu pflegen.

Ich hoffe, Sie finden diese Antwort hilfreich!