Estendendo a classe WP_User e usando esta subclasse durante todo o ciclo de vida

4

O que estou tentando alcançar é o seguinte: para cada usuário em nosso site, desejo fazer uma solicitação de API a um serviço (API REST local interagindo com outro banco de dados) e depois armazenar em cache o resultado no WP_User (sub ) class até que o usuário efetue logout e login novamente (como este valor é usado em todas as páginas do aplicativo uma vez, caso contrário, ele teria que ser recuperado uma vez para cada carregamento de página, o que é muito indesejável em termos de desempenho).

A maneira mais elegante em termos de Separação de Interrogações que encontrei até agora, é feita estendendo (subclassificando) a classe WP_User conforme exemplo apresentado no livro da O'Reilly Construindo Web Apps com WordPress By Brian Messenlehner & Jason Coleman .

O código de exemplo pode ser visto aqui: veja este arquivo no GitHub do autor .

No entanto, o problema é que ainda não temos esse Student (estende WP_User, subclass) disponível em nosso código, ainda precisamos instanciá-lo da seguinte maneira para obter uma instância de Student para o usuário atual:

$student = new Student($current_user->ID);

Se fizermos isso em uma página, a instância sempre será criada novamente (daí referindo-se ao ciclo de vida no título) e a chamada para $student->assignments parece nunca ser armazenada em cache dentro da própria subclasse WP_User após navegar para uma nova página e / ou recarregar a página, portanto, para cada carregamento de página, estamos atingindo a API e o banco de dados que provavelmente nunca serão executados em nosso ambiente de produção de alto tráfego.

A variável global $current_user no próprio WordPress, no entanto (que é uma instância WP_User ), parece ser criada diretamente após o login e, em seguida, está disponível em todo o aplicativo, até onde vai meu entendimento. O que eu realmente quero, é a mesma disponibilidade em todo o aplicativo, mas para minha subclasse (Student) em vez da classe WP_User , mas, mais importante, quero garantir que, para cada usuário conectado, o hit da API seja feito uma vez (assim como para $current_user->user_login , que está em WP_User , por exemplo).

Também procurei adicionar user_meta a WP_User e verifiquei essa questão relacionada a ela, que me pareceu parcialmente útil: Os resultados get_user_meta () do cache do WordPress?

No entanto, isso é recuperado por wp_cache_get , que é o cache de objetos do WordPress, que afirma claramente:

  1. O cache não persistente está disponível somente durante o carregamento da página atual; Quando a próxima página for carregada, ela ficará em branco novamente.
  2. O tamanho do armazenamento é limitado pelo total de memória disponível para PHP no servidor. Não armazene grandes conjuntos de dados, ou você pode acabar com uma mensagem "Sem memória".
  3. O uso desse tipo de cache só faz sentido para operações repetidas mais de uma vez na criação de uma página.

Não estamos usando os valores na subclasse Student mais de uma vez na criação da página, no entanto, o valor é usado em todas as páginas do aplicativo uma vez, portanto, ele deve ser recuperado uma vez para cada carregamento de página. / p>

Estou apenas pensando na direção errada aqui, ou como isso seria possível no WordPress? Eu realmente preciso de uma boa solução de longo prazo aqui que deve funcionar em um ambiente de produção de alto tráfego. Obrigado por todos os contributos e ajuda antecipadamente!

    
por Daniel 28.04.2015 / 23:44

3 respostas

1

Se eu entendi bem, precisamos armazenar em cache um valor recuperado de outro serviço REST, do login ao logout do usuário na instalação do wordpress, então nos conectaremos a este wp_login para obter o valor e armazená-lo em cache usando API temporária , API de opções ou um plugin cache persistente .

add_action('wp_login', 'my_get_and_cache_rest_value');
function my_get_and_cache_rest_value ($user_login, $user) {
    // do your rest call
    // cache it using Transient API, Options API or a persistent caching plugin
}

Podemos, então, estender o objeto WP_User e definir nossas chamadas mágicas para obter os dados que desejamos do cache.

class MY_User extends WP_User {
    // no constructor so WP_User's constructor is used

    // method to get cached data
    function getMyCachedData() {
        // get data via my cache solution
        if ( ! isset( $this->data->myData ) )
            $this->data->myData = my_get_cached_data( $this->ID );

        return $this->data->myData;
    }

    // magic method to detect $user->my_data
    function __get( $key ) {
        if ( $key == 'my_data' )
        {
            return $this->getMyCachedData();
        }
        else
        {
            // fallback to default WP_User magic method
            return parent::__get( $key );
        }
    }    
}

Espero que isso ajude alguém e torça para @Daniel.

    
por JBoulhous 14.03.2018 / 01:31
0

Sua pergunta é um pouco ampla, mas o principal problema parece ser que para cada novo aluno você quer abordar uma API externa, apenas uma vez .

Para fazer isso, você precisa se conectar a wp_insert_user , que é a função principal que registra um novo do utilizador. Por definição, esta função é chamada apenas uma vez para cada novo usuário. No final desta função, você verá um gancho user_register , que é onde você pode se aproximar da API.

add_action ('user_register','wpse185731_approach_api');
function wpse185731_approach_api ($user_id) {
  $userdata = get_userdata( $user_id );
  if ( some condition based on $userdata) {
    ... approach API with $userdata, then store with:
    add_user_meta( $user_id, $meta_key, $meta_value, $unique );
    }
  }

Você provavelmente desejaria fazer isso em um plug-in, não em seu tema.

    
por cjbj 21.09.2016 / 11:02
0

O que se segue não responde a toda a questão, mas aborda esta parte:

  

@Daniel: A variável global $current_user ... está então disponível em todo o aplicativo, no que diz respeito ao meu entendimento. O que eu realmente quero é a mesma disponibilidade em todo o aplicativo ...

Eu tive uma necessidade semelhante, e é isso que eu criei.

Existe um set_current_user hook (dentro da função wp_set_current_user () ) e porque a $current_user variável global é definida para uma instância de WP_User no momento em que a ação é disparada, você pode usar este gancho para "fazer coisas" para ele.

As chamadas para wp_get_current_user () basicamente retornam o valor global $current_user , mas podem acabar chamando wp_set_current_user() sob certas condições, o que fará com que sua ação personalizada seja acionada.

Então, em um plugin personalizado (eu não acho que isso funcionaria em um arquivo theme.php), você pode definir uma ação:

add_action( 'set_current_user', 'extend_current_user', PHP_INT_MAX );

E, em seguida, sua ação pode substituir o global $current_user :

public function extend_current_user()
{
    global $current_user;

    if( $current_user->ID == 0 )
        return;

    $current_user = new Student( $current_user->ID );
}

Sua turma de alunos pode, então, implementar a API temporária para armazenar em cache os dados RESTful e oferecer métodos ou propriedades que exporão esses dados. E como o $current_user global permanecerá como uma instância do Student, esses métodos / propriedades estarão sempre disponíveis em wp_get_current_user() sempre que você precisar deles.

É claro que, ao fazer isso, um programador defensivo desejará verificar se qualquer chamada para wp_get_current_user() retornará uma instância de Student antes de chamar qualquer método.

    
por Matthew Clark 02.09.2018 / 21:50