Isenção de responsabilidade importante: a maneira correta de fazer isso NÃO é modificar a estrutura da tabela, mas usar wp_usermeta. Então você não precisará criar nenhum SQL personalizado para consultar suas postagens (embora ainda precise de um SQL personalizado para obter uma lista de todos os que se reportam a um supervisor específico - na seção Admin, por exemplo). No entanto, como o OP perguntou sobre a criação de SQL personalizado, eis a melhor prática atual para injetar SQL personalizado em uma Consulta WordPress existente.
Se você estiver fazendo junções complexas, não poderá usar apenas o filtro posts_where, porque precisará modificar a junção, a seleção e, possivelmente, o grupo ou as seções da consulta.
Sua melhor aposta é usar o filtro 'posts_clauses'. Este é um filtro muito útil (que não deve ser abusado!) Que permite acrescentar / modificar as várias partes do SQL que são geradas automaticamente pelas muitas linhas de código no núcleo do WordPress. A assinatura de retorno de chamada do filtro é:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
e espera que você retorne $clauses
.
As Cláusulas
$clauses
é uma matriz que contém as seguintes chaves; cada chave é uma string SQL que será usada diretamente na instrução SQL final enviada ao banco de dados:
- Onde
- groupby
- Junte-se
- ordenar por
- distinto
- Campos
- limites
Se você estiver adicionando uma tabela ao banco de dados (faça isso apenas se absolutamente não puder aproveitar post_meta, user_meta ou taxonomias), provavelmente precisará tocar em mais de uma dessas cláusulas, por exemplo, o fields
(o "SELECT" parte da instrução SQL), a join
(todas as suas tabelas, exceto a da cláusula "FROM") e talvez a orderby
.
Modificando as cláusulas
A melhor maneira de fazer isso é sub-referenciar a chave relevante da $clauses
matriz que você obteve do filtro:
$join = &$clauses['join'];
Agora, se você modificar $join
, na verdade você estará modificando diretamente, $clauses['join']
para que as alterações entrem $clauses
quando você a devolver.
Preservando as cláusulas originais
As chances são (não, sério, ouça) que você deseje preservar o SQL existente que o WordPress gerou para você. Caso contrário, você provavelmente deve olhar para o posts_request
filtro - essa é a consulta mySQL completa antes de ser enviada ao banco de dados, para que você possa utilizá-lo totalmente. Por que você quer fazer isso? Você provavelmente não.
Portanto, para preservar o SQL existente nas cláusulas, lembre-se de anexar às cláusulas, não atribuí-las (por exemplo: use $join .= ' {NEW SQL STUFF}';
not $join = '{CLOBBER SQL STUFF}';
. Note que, como cada elemento da $clauses
matriz é uma string, se você desejar anexá-la, você provavelmente desejará inserir um espaço antes de quaisquer outros tokens de caracteres, caso contrário, provavelmente criará algum erro de sintaxe SQL.
Você pode simplesmente assumir que sempre haverá algo em cada uma das cláusulas e, portanto, lembre-se de iniciar cada nova sequência com um espaço, como em:, $join .= ' my_table
ou, você sempre pode adicionar uma pequena linha que só adiciona um espaço se você precisar:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Isso é uma coisa estilística mais do que qualquer outra coisa. O ponto importante a ser lembrado é: sempre deixe um espaço ANTES da sua string se você estiver anexando a uma cláusula que já tenha algum SQL nela!
Juntar as peças
A primeira regra do desenvolvimento do WordPress é tentar usar o máximo de funcionalidade possível. Esta é a melhor maneira de provar seu trabalho no futuro. Suponha que a equipe principal decida que o WordPress agora estará usando SQLite ou Oracle ou alguma outra linguagem de banco de dados. Qualquer mySQL escrito à mão pode se tornar inválido e quebrar seu plugin ou tema! É melhor deixar o WP gerar o máximo de SQL possível por conta própria e apenas adicionar os bits necessários.
Portanto, a primeira ordem de negócios está se aproveitando WP_Query
para gerar o máximo possível de sua consulta básica. O método exato que usamos para fazer isso depende em grande parte de onde essa lista de postagens deve aparecer. Se for uma subseção da página (não sua consulta principal), você usaria get_posts()
; se for a consulta principal, suponho que você possa usar query_posts()
e terminar com ela, mas a maneira correta de fazer isso é interceptar a consulta principal antes que ela atinja o banco de dados (e consuma ciclos do servidor), portanto, use o request
filtro.
Ok, você gerou sua consulta e o SQL está prestes a ser criado. Bem, de fato, ele foi criado, apenas não enviado para o banco de dados. Usando o posts_clauses
filtro, você adicionará sua tabela de relacionamentos com funcionários à mistura. Vamos chamar esta tabela {$ wpdb-> prefix}. 'user_relationship' e é uma tabela de interseção. (A propósito, eu recomendo que você genere essa estrutura da tabela e a transforme em uma tabela de interseção adequada com os seguintes campos: 'ID_de_relacionamento', 'ID_ do usuário', 'ID_usuário_id' ',' tipo_de_relação ',' tipo_de_relação '; isso é muito mais flexível e poderoso. .. mas eu discordo).
Se eu entendo o que você quer fazer, você passa a ID do Líder e vê apenas as postagens dos Seguidores desse Líder. Espero ter acertado. Se não estiver certo, você terá que pegar o que eu digo e adaptá-lo às suas necessidades. Vou ficar com a estrutura da sua mesa: temos a leader_id
e a follower_id
. Portanto, o JOIN será {$wpdb->posts}.post_author
ativado como uma chave estrangeira para o 'follower_id' na sua tabela 'user_relationship'.
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}