it-swarm.com.de

Entwicklung eines Wordpress Search Plugins - Best Practices

Nachdem ich ungefähr zwei Tage lang nach einer Antwort auf meine Frage gesucht hatte, habe ich mich schließlich für diesen StackExchange registriert. :)

Meine Frage ist nicht einfach, also muss ich ganz am Anfang beginnen. Aber um Ihnen eine Vorstellung davon zu geben, worum es in diesem Beitrag geht: In der Zwischenzeit funktioniert mein Plugin, aber ich mag den Code nicht. Ich denke, es gibt bessere Möglichkeiten, dies zu lösen, und deshalb suche ich nach WordPress-Ninjas, die mir mit guten Tipps und bewährten Methoden helfen können. Ich versuche wirklich, in die Tiefe von WordPress zu kommen, aber es ist irgendwie schwierig. Danke im Voraus!


Was mein Plugin machen soll

Der Benutzer dieses Plugins sollte in der Lage sein, einen Shortcode zu verwenden, um ein Suchformular für bestimmte Beitragstypen anzuzeigen. Das Plugin wird nur auf den Seiten benötigt, die diesen Shortcode enthalten.

Die Beitragstypen 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 Beitragstyp. Das Suchformular enthält ein Feld zum Durchsuchen aller Post-Felder des angegebenen Post-Typs. Die anderen beiden können verwendet werden, um die Ergebnisse durch zwei Schlüsselwörter einzuschränken (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 funktionieren:

  • Erstellen Sie auf Post-Typ in der PHP-Datei des Plugins. Im Moment ist ein statischer Beitragstyp enaugh.
  • Erstellen Sie einen Shortcode, der das Suchformular und einen leeren Container für die Ergebnisse druckt.
  • Die Ajax-Anfrage funktioniert über Javascript und liefert die erwarteten Ergebnisse.

Benutzerdefinierte Felder durchsuchen

Das war ziemlich schwierig, aber ich habe ein funktionierendes Code-Snippet gefunden und verstehe, was es tut. Das Problem hierbei ist, dass ich nur mit meinem speziellen Suchformular nach ACF-Feldern suchen möchte. Ich möchte die Suche auf der vorhandenen Website nicht berühren.

Zuerst habe ich versucht zu überprüfen, auf welcher Site sich der Benutzer befindet und eine if-Anweisung mit is_page () zu verwenden, bevor ich die Suchabfrage ändere. Aber da ich Ajax benutze, scheint dies hier nicht für mich zu funktionieren ...

Meine Problemumgehung besteht darin, zu Beginn jeder Ajax-Suchabfrage eine globale Variable festzulegen. Jetzt überprüfe ich, ob diese Variable gesetzt ist, bevor ich die Suchabfrage ändere. Am Ende meiner Ajax-Funktion 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 ...

Folgende Funktionen ändern meine Suchanfrage:

/** 
 * WordPress-Suche um benutzerdefinierte Felder erweitern 
 * 
 * Http://adambalee.com 
 */
 
/** 
 * Beitreten zu Posts und Postmeta-Tabellen 
 * 
 * Http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join 
 */
 Funktion cf_search_join ($ join) {
 globales $ wpdb; 
 //$cwlistpage=(is_page('list'));
 
 globaler $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if ($ cwlistpage) {
 $ join. = 'LEFT JOIN'. $ wpdb-> postmeta. ' AUF '. $ wpdb-> posts. '.ID ='. $ wpdb-> postmeta. '.post_id'; 
} 
 
 return $ join; 
} 
 add_filter ('posts_join', 'cf_search_join'); 
 
/** 
 * Ändern Sie die Suchanfrage mit posts_where 
 * 
 * Http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where 
 */
 Funktion cf_search_where ($ where) {
 globales $ pagenow, $ wpdb; 
 // $ cwlistpage = (is_page ('list')); 
 
 globaler $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if ($ cwlistpage) {
 $ where = preg_replace ( 
 "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\'‹+\')\s*\)/", 
 "(". $ wpdb-> posts. ". post_title LIKE $ 1) OR (". $ wpdb-> postmeta. ". meta_value LIKE $ 1)", $ where); 
} 
 
 return $ where; 
} 
 add_filter ('posts_where', 'cf_search_where'); 
 
/** 
 * Duplikate verhindern 
 * 
 * Http://codex.wordpress.org/Plugin_API/Filter_Reference/ posts_distinct 
 */
 function cf_search_distinct ($ where) {
 global $ wpdb; 
 // $ cwlistpage = (is_page ('list')); 
 
 globaler $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if ($ cwlistpage) {
 return "DISTINCT"; 
} 
 
 return $ where; 
} 
 add_filter ('posts_distinct', 'cf_search_distinct'); 

Begrenzen Sie die Ergebnisse durch benutzerdefinierte Felder

Alle Felder des Formulars sind optional. Ein leeres Formular gibt alle Beiträge dieses Beitragstyps zurück. Das erste Feld sollte in jedem Feld der Beiträge nach dem Schlüsselwort suchen. Das zweite und dritte Feld sollten die Ergebnisse auf das mit diesem Schlüsselwort beschränken. Ich habe dies mit if-Anweisungen gelöst 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() ) : ?>
  <br><br><p>
   <?php while ( $query->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: <?php the_title(); ?> <br>
     Abschluss: <?php the_field('offer_degree'); ?> <br>
     Ort: <?php the_field('offer_location'); ?> <br>
     Anbieter: <?php the_field('offer_provider'); ?> <br>
     <?php if(get_field('offer_subtitle')): ?>
     - <?php the_field('offer_subtitle'); ?> <br>
     <?php endif; ?>
     <br>

    <?php endif; endif; endwhile; ?>
    </p>
<?php else: ?>
    <!-- no posts found -->
    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 Startseite viele Zeilen wie die folgenden:

Hinweis: Es wird versucht, die Eigenschaft eines Nichtobjekts in C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.php in Zeile 4520 abzurufen. Hinweis: Es wird versucht, die Eigenschaft eines Nichtobjekts in C:\abzurufen. Benutzer\CWalt\Dokumente\gitlab\steuerazubi\wordpress\wp-includes\query.php in Zeile 4522 Hinweis: Es wird versucht, die Eigenschaft eines Nichtobjekts in C:\Benutzer\CWalt\Dokumente\gitlab\steuerazubi\wordpress\wp- abzurufen. Beinhaltet\query.php in Zeile 4524 ...

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


Weitere Beitragstypen

Kennen Sie einen guten Ansatz, um den Benutzer mehr Beitragstypen über das WordPress-Backend festlegen zu lassen? Der Benutzer sollte in der Lage sein, über Shortcodes verschiedene Suchseiten für verschiedene Beitragstypen zu erstellen.


Vielen Dank für das Lesen. Für jeden kleinen Hinweis bin ich dankbar.

7
Christoph

Ich habe Ihren Beitrag vollständig durchgelesen, ich sehe sicher nichts besonders Falsches daran, aber es klingt für mich so, als ob Sie mehr frustriert darüber sind, wie er aufgebaut wurde.

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

Wordpress Plugin Boiler Plate ist das, was ich von ganzem Herzen empfehlen kann. Normalerweise gehe ich zu wwpb.me , um ein Plugin-Skelett für mich zu generieren, das von Anfang an funktioniert. Fülle einfach das Formular aus, lade es herunter und extrahiere es in das Plugin-Verzeichnis deiner WordPress-Installation.

Sobald Sie Ihr Laufskelett installiert haben, empfehle ich Ihnen, dieses Tutorial zu lesen. Es ist eine gute Einführung in den Aufbau des soeben heruntergeladenen Laufskeletts:

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 Sie sich einen kurzen Überblick verschafft haben, möchte ich normalerweise eine Datenklasse erstellen, in der alle meine benutzerdefinierten Datenbankabfragen gespeichert sind, z.

<?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 ist es so einfach, dies in Ihren Admin-/Public-Facing-Controllern zu verwenden:

    <?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 erstelle mir auch gerne eine Utility-Klasse, die in meinem Plugin sehr häufig verwendete Funktionen enthält, z. B. Regeln zur Formularüberprüfung, die genauso implementiert und verwendet werden.

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

Durch die Verwendung der Datenklasse kann ich alle meine Datenanrufe an einem Ort zentralisieren und sie während der gesamten Plug-in-Entwicklung verwenden.

Die Verwendung dieser Methoden hat meine Entwicklungszeit erheblich verkürzt und die Wartung meiner Plugins erheblich vereinfacht.

Ich hoffe, Sie finden diese Antwort hilfreich!

1
Ryan Fletcher