web-dev-qa-db-fra.com

Développement d'un plugin de recherche Wordpress - Meilleures pratiques

En cherchant environ deux jours pour trouver une réponse à ma question, je me suis finalement inscrit à ce StackExchange. :)

Ma question n’est pas simple, je dois donc commencer au tout début. Mais pour vous donner une idée de la teneur de cet article: En attendant, mon plug-in fonctionne, mais je n'aime pas le code. Je pense qu'il existe de meilleurs moyens de résoudre ce problème et je suis donc à la recherche de ninjas wordpress pouvant m'aider avec de bons conseils et de meilleures pratiques. J'essaie vraiment d'entrer dans les profondeurs de Wordpress, mais c'est un peu difficile. Merci d'avance!


Ce que mon plugin devrait faire

L'utilisateur de ce plugin devrait pouvoir utiliser un shortcode pour afficher un formulaire de recherche pour des types de publications spécifiques. Le plugin n'est nécessaire que sur les pages contenant ce shortcode.

Les types de publication sont créés via la page des paramètres du plug-in. Chaque publication de ce type a un titre, un contenu et plusieurs champs personnalisés du plugin acf. Il existe un shortcode pour chaque type de message. Le formulaire de recherche comporte un champ pour rechercher tous les champs de publication du type de publication spécifié. Les deux autres peuvent être utilisés pour limiter les résultats à l'aide de deux mots-clés (par exemple, l'emplacement, qui est un champ acf).

Les résultats sont chargés via ajax et affichés sous le formulaire de recherche.


Ce que j'ai déjà fait

J'essaie de garder cette question pas trop grande. Je ne spécifie donc pas tous les aspects. Ce qui suit devrait bien fonctionner:

  • Créer sur poste tapez le fichier php du plugin. Pour le moment, un type de post statique est enaugh.
  • Créez un shortcode qui imprime le formulaire de recherche et un conteneur vide pour les résultats.
  • La requête Ajax fonctionne via javascript et donne les résultats attendus.

Rechercher des champs personnalisés

C'était assez difficile, mais j'ai trouvé un extrait de code qui fonctionne et je comprends ce qu'il fait. Le problème ici est que je veux juste rechercher des champs acf avec mon formulaire de recherche spécifique. Je ne veux pas toucher à la recherche du site existant.

J'ai d'abord essayé de vérifier le site sur lequel l'utilisateur se trouve et d'utiliser une instruction if avec is_page () avant de modifier la requête de recherche. Mais comme j'utilise ajax, cela ne semble pas fonctionner pour moi ici ...

Ma solution consiste à définir une variable globale au début de chaque requête de recherche ajax. Maintenant, je vérifie si cette variable est définie avant de modifier la requête de recherche. À la fin de ma fonction ajax, je redonne la valeur false à cette variable. Oui, je pense qu'il existe un meilleur moyen de résoudre ce problème, mais je ne sais pas comment ...

Les fonctions qui modifient ma requête de recherche sont les suivantes:

/** 
 * Étendre la recherche WordPress pour inclure des champs personnalisés 
 * 
 * Http://adambalee.com 
 */
 
/** 
 * Joindre des publications et des tables postmeta 
 * 
 * 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. = 'LEFT JOIN'. $ wpdb-> postmeta. ' SUR '. $ wpdb-> posts. '.ID ='. $ wpdb-> postmeta. '.post_id'; 
} 
 
 return $ join; 
} 
 add_filter ('posts_join', 'cf_search_join'); 
 
/** 
 * Modifiez la requête de recherche avec posts_where 
 * 
 * Http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where 
 */
 fonction cf_search_where ($ where) {
 global $ pagenow, $ wpdb; 
 // $ cwlistpage = (is_page ('list')); 
 
 global $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if ($ cwlistpage) {
 $ où = preg_replace ( 
 "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[•\''++''\\\\\\ '/", 
 "(". $ wpdb-> posts. ". post_title LIKE $ 1) OR (". $ wpdb-> postmeta. ". meta_value LIKE $ 1)", $ où); .____.]} 
 
 renvoie $ où; 
} 
 add_filter ('posts_where', 'cf_search_where'); 
 
/** 
 * Prévenir les doublons 
 * 
 * Http://codex.wordpress.org/Plugin_API/Filter_Reference/ posts_distinct 
 */
 fonction cf_search_distinct ($ where) {
 global $ wpdb; 
 // $ cwlistpage = (is_page ('list')); 
 
 global $ testcheck; 
 $ cwlistpage = $ testcheck; 
 
 if ($ cwlistpage) {
 renvoyer "DISTINCT"; 
} 
 
 renvoie $ où; 
} 
 add_filter ('posts_distinct', 'cf_search_distinct'); 

Limiter les résultats par champs personnalisés

Tous les champs du formulaire sont facultatifs. Un formulaire vide renverra tous les messages de ce type. Le premier champ doit rechercher le mot clé dans tous les champs des publications. Les deuxième et troisième champs doivent limiter les résultats à celui contenant ce mot clé. J'ai résolu ce problème avec des déclarations if et je sais qu'il doit y avoir une meilleure solution.

/**
* 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

Lorsque j'active le plugin, de nombreuses lignes telles que les suivantes apparaissent sur la page d'accueil:

Remarque: essayer d'obtenir la propriété de non-objet dans C:\Utilisateurs\CWalt\Documents\gitlab\steuerazubi\motpress\wp-includes\query.php à la ligne 4520 Remarque: Essayer d'obtenir la propriété de non-objet dans C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.php à la ligne 4522 Avertissement: tentative d'obtention de la propriété de non-objet dans C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp- inclut\query.php à la ligne 4524 ...

J'ai activé le débogage pour créer un bon plugin. Que pouvais-je faire de mal?


Plus de types de messages

Connaissez-vous une bonne approche pour permettre à l'utilisateur de spécifier davantage de types de publication via le backend wordpress? L'utilisateur doit pouvoir créer différentes pages de recherche pour différents types de publication via des codes abrégés.


Merci beaucoup d'avoir lu. Je suis reconnaissant pour chaque petit indice.

7
Christoph

J'ai lu votre article dans son intégralité, je ne vois certes rien qui cloche, mais il me semble que vous êtes plus frustré de la manière dont il a été présenté.

J'ai personnellement une grande expérience de la programmation orientée objet, cela me permet d'établir une structure et rend mon code beaucoup plus réutilisable. Ma suggestion serait de tenter une approche orientée objet pour votre prochain plugin ou la restructuration de ce plugin que vous avez décrite dans la question initiale.

Wordpress Plugin Boiler Plate est ce que je recommande vivement. Je commence habituellement par aller sur wwpb.me pour générer un squelette de plugin qui est fonctionnel en dehors de la porte, il suffit de remplir le formulaire, de le télécharger et de l'extraire dans votre répertoire plugins de votre installation wordpress.

Une fois que votre squelette de course est en place, je vous suggère de lire ce tutoriel, c’est un excellent guide pour savoir comment construire le squelette de marche que vous venez de télécharger:

Accélérer le développement en utilisant le plugin WordPress Boilerplate pt1

Le WordPress Plugin Boilerplate Partie 2: Développement d'un plugin

Le plugin WordPress Plugin Boilerplate Partie 3: Les dernières étapes

Après une lecture rapide de ce document, j’aime généralement créer une classe de données qui stocke toutes les requêtes de base de données personnalisées, telles que:

<?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;
  }

Ensuite, pour utiliser ceci dans vos contrôleurs face à l’administration/au public, il vous suffit de:

    <?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();

}

J'aime aussi créer moi-même une classe utilitaire qui héberge des fonctions très communes dans tout mon plugin, telles que les règles de validation de formulaire, implémentées et utilisées exactement de la même manière.

Vous les incluez simplement dans votre fichier de plugin principal avec require_once et instanciez si nécessaire.

L'utilisation de la classe de données me permet de centraliser tous mes appels de données en un seul endroit et de les utiliser tout au long du développement du plug-in.

L'utilisation de ces pratiques a considérablement réduit mon temps de développement et facilité la maintenance de mes plugins.

J'espère que vous trouverez cette réponse utile!

1
Ryan Fletcher