Já passei dias com esse problema agora. Inicialmente, era como armazenar os dados de seguidores de um usuário no banco de dados, para os quais recebi algumas boas recomendações aqui no WordPress Answers. Depois, seguindo as recomendações, adicionei uma nova tabela como esta:
id leader_id follower_id
1 2 4
2 3 10
3 2 10
Na tabela acima, a primeira linha possui um usuário com um ID 2 que está sendo seguido por um usuário com um ID 4. Na segunda linha, um usuário com um ID 3 é seguido por um usuário com um ID de 10. A mesma lógica se aplica à terceira linha.
Agora, basicamente quero estender o WP_Query para limitar as postagens buscadas, apenas pelo (s) líder (es) de um usuário. Portanto, levando em consideração a tabela acima, se eu passar o ID do usuário 10 para WP_Query, os resultados deverão conter apenas postagens pelo ID do usuário 2 e pelo ID do usuário 3.
Eu pesquisei muito tentando encontrar uma resposta. Também não vi nenhum tutorial para me ajudar a entender como estender a classe WP_Query. Vi as respostas de Mike Schinkel (estendendo o WP_Query) para perguntas semelhantes, mas realmente não entendi como aplicá-las às minhas necessidades. Seria ótimo se alguém pudesse me ajudar com isso.
Links para respostas de Mike, conforme solicitado: Link 1 , Link 2
WP_Query
é para obter postagens, e não estou conseguindo entender como isso está relacionado às postagens.Respostas:
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: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), ajoin
(todas as suas tabelas, exceto a da cláusula "FROM") e talvez aorderby
.Modificando as cláusulas
A melhor maneira de fazer isso é sub-referenciar a chave relevante da
$clauses
matriz que você obteve do filtro: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: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ê usariaget_posts()
; se for a consulta principal, suponho que você possa usarquery_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 orequest
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 afollower_id
. Portanto, o JOIN será{$wpdb->posts}.post_author
ativado como uma chave estrangeira para o 'follower_id' na sua tabela 'user_relationship'.fonte
Estou respondendo a esta pergunta extremamente tarde e peço desculpas pelo mesmo. Eu estava muito ocupado com prazos para atender a isso.
Um grande obrigado a @ m0r7if3r e @kaiser por fornecer as soluções básicas que eu poderia estender e implementar em meu aplicativo. Esta resposta fornece detalhes sobre minha adaptação das soluções oferecidas por @ m0r7if3r e @kaiser.
Primeiro, deixe-me explicar por que essa pergunta foi feita em primeiro lugar. A partir da pergunta e dos comentários dela, pode-se concluir que estou tentando fazer com que o WP_Query puxe postagens de todos os usuários (líderes) que um determinado usuário (seguidor) segue. O relacionamento entre o seguidor e o líder é armazenado em uma tabela personalizada
follow
. A solução mais comum para esse problema é extrair da tabela a seguir os IDs de usuário de todos os líderes de um seguidor e colocá-lo em uma matriz. Ver abaixo:Depois de ter a matriz de líderes, você pode transmiti-la como argumento para o WP_Query. Ver abaixo:
A solução acima é a maneira mais simples de alcançar os resultados desejados. No entanto, não é escalável. No momento em que você tem um seguidor seguindo dezenas e milhares de líderes, a matriz resultante de IDs de líderes ficaria extremamente grande e forçaria seu site WordPress a usar 100 MB - 250 MB de memória em cada carregamento de página e, eventualmente, travar o site. A solução para o problema é executar a consulta SQL diretamente no banco de dados e buscar postagens relevantes. Foi quando a solução do @ m0r7if3r veio resgatar. Seguindo a recomendação do @ kaiser, decidi testar as duas implementações. Eu importei cerca de 47 mil usuários de um arquivo CSV para registrá-los em uma nova instalação de teste do WordPress. A instalação estava executando o tema Twenty Eleven. Depois disso, executei um loop for para fazer com que cerca de 50 usuários sigam todos os outros usuários. A diferença no tempo de consulta para a solução @kaiser e @ m0r7if3r foi impressionante. A solução do @ kaiser normalmente levava de 2 a 5 segundos para cada consulta. A variação que presumo acontece quando o WordPress armazena em cache as consultas para uso posterior. Por outro lado, a solução da @ m0r7if3r demonstrou um tempo de consulta de 0,02 ms em média. Para testar as duas soluções, eu tive a indexação ON na coluna leader_id. Sem indexação, houve um aumento dramático no tempo de consulta.
O uso de memória ao usar a solução baseada em matriz ficou em torno de 100-150 MB e caiu para 20 MB ao executar um SQL direto.
Eu bati com a solução do @ m0r7if3r quando precisei passar o ID do seguidor para a função de filtro posts_where. Pelo menos, de acordo com meu conhecimento, o WordPress não permite passar uma variável às funções do arquivador. Você pode usar variáveis globais, mas eu queria evitar globais. Acabei estendendo o WP_Query para finalmente resolver o problema. Então, aqui está a solução final que eu implementei (com base na solução do @ m0r7if3r).
Nota: Eu finalmente tentei a solução acima com 1,2 milhão de entradas na tabela a seguir. O tempo médio de consulta ficou em torno de 0,060 ms.
fonte
Você pode fazer isso com uma solução totalmente SQL usando o
posts_where
filtro. Aqui está um exemplo disso:Eu acho que também pode haver uma maneira de fazer isso
JOIN
, mas não consigo. Continuarei brincando com ele e atualizarei a resposta, se o conseguir.Como alternativa, como o @kaiser sugeriu, você pode dividi-lo em duas partes: obter os líderes e fazer a consulta. Sinto que isso pode ser menos eficiente, mas certamente é o caminho mais compreensível a seguir. Você precisaria testar a eficiência para determinar qual método é melhor, pois as consultas SQL aninhadas podem ficar muito lentas.
DOS COMENTÁRIOS:
Você deve colocar a função no seu
functions.php
e fazer oadd_filter()
direito antes que oquery()
método deWP_Query
seja chamado. Imediatamente após isso, você deve fazerremove_filter()
isso para que não afete as outras consultas.fonte
prepare()
. Espero que você não se importe com a edição. E sim: o desempenho deve ser medido pelo OP. Enfim: eu ainda acho que isso deve ser simplesmente usermeta e nada mais.functions.php
e fazer oadd_filter()
direito antes que oquery()
método deWP_Query
seja chamado. Imediatamente após isso, você deve fazerremove_filter()
isso para que não afete as outras consultas. Eu não tenho certeza qual é o problema com a reescrita de URL seria, eu useiposts_where
em muitas ocasiões e nunca vi isso ...Tag de modelo
Basta colocar as duas funções no seu
functions.php
arquivo. Em seguida, ajuste a 1ª função e adicione seu nome de tabela personalizado. Então você precisa de alguma tentativa / erro para se livrar do ID do usuário atual dentro da matriz resultante (consulte o comentário).Dentro do modelo
Aqui você pode fazer o que quiser com seus resultados.
fonte
JOIN
é muito mais caro. Além disso: como eu mencionei, não temos dados de teste; portanto, teste as duas respostas e nos esclareça com seus resultados.Aqui está o código de OP dos comentários, para adicionar o primeiro conjunto de usuários de teste. Eu tenho que ser modificado para um exemplo do mundo real.
Minha resposta a este teste ↑:
Eu também tenho que afirmar que o ↑ tempo acima do rastreamento não pode ser realmente medido, pois também levaria tempo para calcular o loop juntos. Melhor seria fazer um loop pelo conjunto resultante de IDs em um segundo loop.
processo adicional aqui
fonte