Extendiendo la clase WP_User y usando esta subclase durante todo el ciclo de vida

4

Lo que estoy tratando de lograr es lo siguiente: para cada usuario de nuestro sitio web, quiero hacer una solicitud de API a un servicio (API REST local que interactúa con otra base de datos) una vez y luego almacenar en caché el resultado en el Usuario WP (sub ) hasta que el usuario cierre la sesión y vuelva a iniciar sesión (ya que este valor se usa en todas las páginas de la aplicación una vez, de lo contrario, tendría que recuperarse una vez por cada carga de página, lo cual es muy indeseable en cuanto al rendimiento).

La forma más elegante en términos de Separación de Preocupaciones que he encontrado hasta ahora, se realiza extendiendo (subclasificando) la clase WP_User como en el ejemplo presentado en el libro de O'Reilly Construyendo aplicaciones web con WordPress Por Brian Messenlehner & Jason Coleman .

El código de ejemplo se puede ver aquí: vea este archivo en Gitre del autor .

Sin embargo, el problema es que todavía no tenemos este Estudiante (amplía WP_User, por lo tanto, subclase) disponible en nuestro código, todavía necesitamos crear una instancia de la siguiente manera para obtener una instancia de Estudiante para el usuario actual:

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

Si hacemos eso en una página, la instancia siempre se volverá a crear (por lo tanto, me referiré al ciclo de vida en el título) y la llamada a $student->assignments nunca se almacenará en caché dentro de la subclase WP_User después de navegar a una nueva página y / o volver a cargar la página, por lo que para cada carga de página estamos llegando a la API y la base de datos que probablemente nunca se desempeñarán en nuestro entorno de producción de alto tráfico.

Sin embargo, parece que la variable global $current_user dentro de WordPress (que es una instancia WP_User ) se crea directamente después de iniciar sesión y está disponible en toda la aplicación hasta donde entiendo. Lo que realmente quiero es la misma disponibilidad en toda la aplicación, pero luego para mi subclase (Estudiante) en lugar de la clase WP_User , pero lo más importante es que quiero asegurarme de que para cada usuario registrado, el resultado de la API solo se haga. una vez (al igual que para $current_user->user_login que está en WP_User por ejemplo).

También he estudiado la adición de user_meta a WP_User , y he comprobado esta pregunta relacionada con la que me pareció parcialmente útil: ¿Obtiene el caché de WordPress get_user_meta ()?

Sin embargo, esto se recupera a través de wp_cache_get , que es el Caché de Objetos de WordPress que indica claramente:

  1. El caché no persistente está disponible solo durante la carga de la página actual; una vez que se cargue la siguiente página, volverá a estar en blanco.
  2. El tamaño del almacenamiento está limitado por la memoria total disponible para PHP en el servidor. No almacene grandes conjuntos de datos, o podría terminar con un mensaje de "Memoria insuficiente".
  3. Utilizar este tipo de caché solo tiene sentido para las operaciones que se repiten más de una vez en la creación de una página.

No estamos usando los valores en la subclase de Estudiante más de una vez en la creación de la página, sin embargo, el valor se usa en todas las páginas de la aplicación una vez, por lo que debería recuperarse una vez por cada carga de página.

¿Estoy pensando en la dirección equivocada aquí, o cómo sería posible dentro de WordPress? Realmente necesito una buena solución a largo plazo que debería funcionar en un entorno de producción de alto tráfico. ¡Gracias por todos los comentarios y ayuda por adelantado!

    
pregunta Daniel 28.04.2015 - 23:44

3 respuestas

1

Si entendí bien, necesitamos almacenar en caché un valor recuperado de otro servicio REST, desde el inicio de sesión hasta el cierre de sesión del usuario en la instalación de wordpress, por lo que nos conectamos a este wp_login para obtener el valor y guardarlo en la memoria caché. utilizando API transitoria , API de opciones o un caché 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
}

Luego podemos extender el objeto WP_User y configurar nuestras llamadas mágicas para obtener los datos que deseamos del caché.

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 esto ayude a alguien y saluda a @Daniel.

    
respondido por el JBoulhous 14.03.2018 - 01:31
0

Su pregunta es un poco amplia, pero el problema principal parece ser que para cada nuevo estudiante al que desea acceder a una API externa, solo una vez .

Para hacer esto, debes enlazar con wp_insert_user , que es la función principal que registra una nueva usuario. Por definición, esta función solo se llama una vez para cada nuevo usuario. Al final de esta función, verá un enlace user_register , que es donde puede acercarse a la 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 );
    }
  }

Probablemente querrías hacer esto en un complemento, no en tu tema.

    
respondido por el cjbj 21.09.2016 - 11:02
0

Lo que sigue no responde a toda la pregunta, pero sí aborda esta parte:

  

@Daniel: La variable global $current_user ... está disponible en toda la aplicación en lo que a mi entender se refiere. Lo que realmente quiero es la misma disponibilidad en toda la aplicación ...

Tenía una necesidad similar, y esto es lo que se me ocurrió.

Hay un gancho set_current_user (dentro de la función wp_set_current_user () ), y porque el% La variable global $current_user se establece en una instancia de WP_User en el momento en que se activa la acción, puedes usar este gancho para "hacer cosas".

Las llamadas a wp_get_current_user () básicamente devuelven el valor del $current_user global, pero podrían terminar llamar a wp_set_current_user() bajo ciertas condiciones, lo que provocará que se desate su acción personalizada.

Entonces, en un complemento personalizado (no creo que esto funcione en un archivo de función function.php), puedes definir una acción:

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

Y luego su acción puede sobrescribir el $current_user global:

public function extend_current_user()
{
    global $current_user;

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

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

Su clase de Estudiante podría implementar la API Transitoria para almacenar en caché los datos RESTful y ofrecer métodos o propiedades que expondrán esos datos. Y como el $current_user global permanecerá como una instancia de Student, esos métodos / propiedades siempre estarán disponibles desde wp_get_current_user() en cualquier momento que los necesite.

Por supuesto, al hacer esto, un programador defensivo querrá verificar que cualquier llamada a wp_get_current_user() regrese una instancia de Student antes de llamar a cualquier método.

    
respondido por el Matthew Clark 02.09.2018 - 21:50

Lea otras preguntas en las etiquetas