Onde é o lugar apropriado para adicionar um filtro para pre_get_table_charset?

4

Pergunta:

Onde está o lugar do proper WordPress para adicionar um filtro para pre_get_table_charset , antes de ser executado?

O filtro pre_get_table_charset é acionado em wp-db.php::get_table_charset() .

Atualização: solução

Mark Kaplun apontou na direção certa, que é colocar o filtro em um drop-in. Como estamos usando uma configuração de MU (como evidenciado pelo meu nome de tabela), o drop-in mais fácil e mais simples foi o sunrise.php , que, no meu entender, foi projetado para ser carregado super cedo de qualquer maneira.

Atualização: advertência

Depois de ter o filtro carregado com sucesso, você começará a receber esses erros:

PHP Notice:  Undefined index: wp_2_options in /srv/www/wordpress/web/wp/wp-includes/wp-db.php on line 25xx

Isso acontece porque o wp-db.php não armazena em cache o resultado da mesma forma que seria feito se fosse necessário pesquisá-lo no banco de dados, e esse cache é usado tanto por wp-db.php::get_table_charset() como por wp-db.php::get_col_charset() . / p>

Solução: defina um segundo filtro, pre_get_col_charset , com 3 parâmetros, que retornam o mesmo valor que o filtro pre_get_table_charset .

add_filter('pre_get_col_charset', function($charset, $table, $column) {
    return 'utf8mb4'; 
}, 10, 2);

Histórico:

O WordPress gera uma consulta consistentemente lenta em nosso servidor:

SHOW FULL COLUMNS FROM 'wp_2_options'

Isso é gerado em wp-db.php::get_table_charset() e é usado para determinar o conjunto de caracteres de uma tabela. É, obviamente, totalmente desnecessário, porque sabemos qual é o charset. A atualização mais recente do WordPress garantiu que todas as nossas tabelas fossem utf8mb4 , então certamente podemos codificar isso e reduzir a velocidade de carregamento da página?

Sim, nós podemos. O WordPress até fornece um filtro para isso.

    /**
     * Filters the table charset value before the DB is checked.
     *
     * Passing a non-null value to the filter will effectively short-circuit
     * checking the DB for the charset, returning that value instead.
     *....
     */
    $charset = apply_filters( 'pre_get_table_charset', null, $table );

Escrever o código para isso é trivial:

add_filter('pre_get_table_charset', function($charset, $table) {return 'utf8mb4'; }, 10, 2);

No entanto, esse filtro é chamado MUITO no início da pilha de execução do Wordpress. É chamado antes que os plugins sejam carregados e antes que os plug-ins mu sejam carregados.

É chamado de AFTER config/application.php , mas a função add_filter() ainda não está definida.

Eu sei que há um bilhão e um lugares onde eu posso hackear o núcleo do WordPress e inserir essa linha, mas eu prefiro não fazer isso se eu puder.

Além disso, estamos usando uma configuração do Wordpress Bedrock, se isso ajudar em tudo.

    
por haz 23.11.2016 / 07:26

2 respostas

2

Parece que sua avaliação está correta e que essa função específica será chamada antes que você tenha a chance de adicionar o filtro de maneira tradicional. O fluxo de código relacionado é uma chamada relativamente cedo no momento da inicialização para wp_not_installed para verificar se o wordpress está instalado, o qual chama is_blog_active , que tenta ler a opção siteurl , e portanto uma consulta DB é feita e a validação de a estrutura da tabela é feita.

Parece haver duas maneiras de contornar isso

  1. Tenha um cache de objetos. Você deve, em qualquer caso, mas neste caso específico, a opção provavelmente será recuperada do cache e nenhum acesso ao banco de dados terá que ser feito, pelo menos não tão cedo.

  2. Escreva um drop-in . Os drop-ins são carregados muito antes no boot, e você provavelmente tem duas opções aqui, para substituir a classe DB pelo drop-in db.php ou adicionar um drop-in de cache avançado e configurar seu filtro lá.

Embora seja horrível alterar o driver DB, na prática é relativamente seguro, já que a unidade não muda muito entre as versões. Obviamente, o caminho mais fácil é o cache avançado, se você não tiver cache de objetos.

Obviamente, você provavelmente deve primeiro investigar por que a consulta está lenta. de a descrição não parece algo que pode ficar lento.

    
por Mark Kaplun 23.11.2016 / 12:55
2

Atualização : Depois de pensar sobre isso, percebi que, embora minha abordagem prove que você pode anexar um filtro em algum momento, isso não exclui a função que já está sendo executada antes desse ponto. Então, essa resposta é pelo menos incompleta, mas deixarei aqui caso alguém tenha a mesma ideia.

Pergunta interessante. Me fez pensar: por que o WordPress inseria um filtro em um lugar onde ele ainda não está disponível? Eles não teriam testado isso? Por isso, escrevi um filtro para get_table_charset e coloquei-o no functions.php do meu desenvolvimento tema.

add_filter('pre_get_table_charset', 'wpse247109_charset', 10, 2);

function wpse247109_charset($charset, $table) {
  var_dump ($table . ' | ');
  return 'utf8mb4';
  }

Isso me deu dumps erráticos no frontend (provavelmente relacionados a alguma forma de cache), mas mensagens consistentes no backend:

  

string (15) "myprefix_options |" Aviso: Índice indefinido: myprefix_options em   /home/example.com/public_html/install/wp-includes/wp-db.php na linha 2569

     

string (15) "myprefix_options |" Aviso: Índice indefinido: myprefix_options em   /home/example.com/public_html/install/wp-includes/wp-db.php na linha 2569

     

string (15) "myprefix_options |"

Então parece que o filtro é chamado allright três vezes. As primeiras duas vezes aparentemente não podem encontrar a tabela de opções do tema, a terceira vez que pode. Eu também coloquei o filtro no meu plugin de desenvolvimento, com os mesmos resultados.

Resumindo: não há problema em colocar o filtro no arquivo de funções do seu tema ou no arquivo principal do seu plugin. Você pode querer desligar qualquer cache durante o desenvolvimento.

    
por cjbj 23.11.2016 / 10:28

Tags