Desenvolvimento de um plug-in de pesquisa do Wordpress - Best Practices

8

Procurando cerca de dois dias para encontrar uma resposta para a minha pergunta, eu finalmente me registrei neste StackExchange. :)

Minha pergunta não é simples, então preciso começar do começo. Mas para lhe dar uma ideia do que é este Post: Enquanto isso, meu Plugin está funcionando, mas eu não gosto do código. Acho que há maneiras melhores de resolver isso e estou procurando por ninjas que podem me ajudar com boas dicas e práticas recomendadas. Eu realmente tento entrar nas profundezas do wordpress, mas é meio difícil. Obrigado antecipadamente!

O que meu plug-in deve fazer

O usuário deste plug-in deve poder usar um shortcode para mostrar um formulário de pesquisa para tipos de postagem específicos. O Plugin é necessário apenas nas páginas que contêm esse shortcode.

Os tipos de postagem são criados por meio da página de configurações do plug-in. Cada post deste tipo tem um título, conteúdo e vários campos personalizados do plugin acf. Há um código curto para cada tipo de postagem. O formulário de pesquisa tem um campo para pesquisar todos os campos de postagem do tipo de postagem especificado. Os outros dois podem ser usados para limitar os resultados por duas palavras-chave (por exemplo, o local, que é um campo ACF).

Os resultados são carregados via ajax e mostrados abaixo do formulário de pesquisa.

O que eu já fiz

Eu tento não deixar essa pergunta tão grande. Então eu não especifico cada aspecto. O seguinte deve funcionar bem:

  • Crie no tipo de postagem no arquivo php do plug-in. No momento, um tipo de post estático está garantido.
  • Crie um código de acesso que imprima o formulário de pesquisa e um contêiner vazio para os resultados.
  • A solicitação do Ajax está funcionando via javascript e fornece os resultados esperados.

Pesquisar campos personalizados

Isso foi muito difícil, mas encontrei um trecho de código de trabalho e entendi o que ele está fazendo. O problema aqui é que eu só quero pesquisar campos acf com o meu formulário de pesquisa específico. Eu não quero tocar na pesquisa do site existente.

Primeiro, tentei verificar em qual site o usuário está e usar uma declaração if com is_page () antes de modificar a consulta de pesquisa. Mas como eu uso ajax, isso parece não funcionar para mim aqui ...

Minha solução alternativa é definir uma variável global no início de cada consulta de pesquisa do ajax. Agora eu verifico se esta variável está definida antes de modificar a consulta de pesquisa. No final da minha função ajax, eu configurei essa variável de volta para false. Sim, acho que há uma maneira melhor de resolver isso, mas não sei como ...

As funções que modificam minha consulta de pesquisa são as seguintes:

/**
 * Extend WordPress search to include custom fields
 *
 * http://adambalee.com
 */

/**
 * Join posts and postmeta tables
 *
 * 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. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }

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

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;
    //$cwlistpage=(is_page('list'));

    global $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' );

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

    global $testcheck;
    $cwlistpage=$testcheck;

    if ( $cwlistpage ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );

Limite os resultados por campos personalizados

Todos os campos do formulário são opcionais. Um formulário vazio retornará todas as postagens deste tipo de postagem. O primeiro campo deve pesquisar todos os campos das postagens da palavra-chave. O segundo e terceiro campo deve limitar os resultados ao que contenha essa palavra-chave. Eu resolvi isso com declarações if e sei que deve haver uma solução melhor.

/**
* 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' );

Depuração do WP

Quando eu ativo o plug-in, muitas linhas como a seguinte aparecem na primeira página:

  

Aviso: Tentativa de obter propriedade de não objeto em C: \ Usuários \ CWalt \ Documentos \ gitlab \ steuerazubi \ wordpress \ wp-includes \ query.php na linha 4520   Aviso: Tentando obter propriedade de não objeto em C: \ Users \ CWalt \ Documentos \ gitlab \ steuerazubi \ wordpress \ wp-includes \ query.php na linha 4522   Aviso: Tentando obter propriedade de não objeto em C: \ Users \ CWalt \ Documentos \ gitlab \ steuerazubi \ wordpress \ wp-includes \ query.php na linha 4524   ...

Eu ativei a depuração para criar um bom plugin. O que eu poderia fazer errado?

Mais tipos de postagem

Você conhece uma boa abordagem para permitir que o usuário especifique mais tipos de postagem por meio do back-end do wordpress? O usuário deve poder criar diferentes páginas de pesquisa para diferentes tipos de postagem por meio de códigos de acesso.

Muito obrigado pela leitura. Eu sou grato por cada pequena dica.

    
por Christoph 05.05.2016 / 19:34

1 resposta

1

Eu li o seu post na íntegra, eu certamente não vejo nada particularmente errado com isso, mas parece-me que você está mais frustrado com a forma como foi apresentado.

Pessoalmente, tenho um grande background de programação orientada a objetos, que me permite estabelecer uma estrutura e tornar meu código muito mais reutilizável. Minha sugestão para você seria tentar uma abordagem orientada a objetos para o seu próximo plugin, ou a reestruturação deste plugin que você escreveu na pergunta original.

Wordpress Plugin Boiler Plate é o que eu recomendo vivamente. Eu costumo começar indo até o wwpb.me para gerar um esqueleto de plug-in para mim que é funcional desde o início, simplesmente preencha o formulário, faça o download e extraia para o diretório de plugins da sua instalação do wordpress.

Uma vez que você tenha o seu esqueleto funcionando, sugiro dar uma leitura a este tutorial, é uma ótima cartilha sobre como construir o esqueleto que você acabou de baixar:

Acelerar o desenvolvimento usando o plugin WordPress Boilerplate pt1

O Plugin WordPress Boilerplate Parte 2: Desenvolvendo um Plugin

O Plugin WordPress Boilerplate Parte 3: Os Últimos Passos

Depois de dar a si mesmo uma leitura rápida, eu geralmente gosto de criar uma classe de dados que armazene todas as minhas consultas de banco de dados personalizadas, como:

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

Em seguida, para usar isso em seus controladores de administração pública / pública, é tão simples quanto:

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

}

Eu também gosto de criar uma classe de utilitário que hospede funções muito comuns em todo o meu plugin, como regras de validação de formulário, implementadas e usadas exatamente da mesma maneira.

Você simplesmente os inclui no seu arquivo de plug-in principal com require_once e instanciar onde necessário.

Usar a classe de dados me permite centralizar todas as minhas chamadas de dados em um único lugar e usá-las em todo o desenvolvimento do plug-in.

O uso dessas práticas reduziu significativamente o tempo de desenvolvimento e facilitou bastante a manutenção dos meus plug-ins.

Espero que você ache essa resposta útil!

    
por Nebri 02.06.2016 / 04:07