Skip to main content

Session validation failed en Laminas

Desarrollando el módulo de Authentication en Laminas me encontré con el siguiente problema.

Error:

Laminas\ServiceManager\Exception\ServiceNotCreatedException

Message:

Service with name «Laminas\Authentication\AuthenticationService» could not be created. Reason: Session validation failded

Solución

La solución que he realizando es la siguiente:

Compruebo que en el fichero de config/autoload/global.php esta la siguiente configuración:

...
'session_manager' => [
     // Session validators (used for security).
     'validators' => [
         RemoteAddr::class,
         HttpUserAgent::class,
     ]
],
...

En mi caso me dirijo a la función onBootstrap (Module.php) de módulo que estoy implementando para forzar el inicio de sessión.

use Laminas\Session\SessionManager;

public function onBootstrap(MvcEvent $event) {
   ...
   $application = $event->getApplication();
   $serviceManager = $application->getServiceManager();

   $sessionManager = $serviceManager->get(SessionManager::class);
   $this->forgetInvalidSession($sessionManager);
   ...
}

protected function forgetInvalidSession($sessionManager) {
   try {
        $sessionManager->start();
         return;
   } catch (\Exception $e) {}
   /**
   * Session validation failed: toast it and carry on.
   */
   // @codeCoverageIgnoreStart
   session_unset();
   // @codeCoverageIgnoreEnd
}

Con la función forgetInvalidSession conseguiremos iniciar la sessión y sino es válida, la eliminaremos con session_unset();

Espero que os sea útil.

La solución la pude encontrar en el aquí.

Crear una tabla en wordpress

En este ejemplo nos ha surgido la necesidad de crear una tabla en la base de datos de wordpress para guardar unos registros, para ello vamos a utilizar la función dbDelta, el código sería el siguiente:

require './wp-load.php';
require './wp-admin/includes/upgrade.php';

global $wpdb;

$prefix = $wpdb->prefix;

$crearTabla = "CREATE TABLE IF NOT EXISTS `".$prefix."bloques_datos2` (
  `id_bloque_dato` int(11) NOT NULL AUTO_INCREMENT,
  `id_post` int(11) NOT NULL,
  `id_bloque` int(11) NOT NULL,
  `bloque` varchar(255) NOT NULL,
  `key_bloque` varchar(255) NOT NULL,
  `valor_bloque` longtext NOT NULL,
  `id_subbloque` int(11) NOT NULL,
  `key_subbloque` varchar(255) NOT NULL,
  `valor_subbloque` longtext NOT NULL,
  PRIMARY KEY (`id_bloque_dato`),
  KEY `id_bloque` (`id_bloque`),
  KEY `id_post` (`id_post`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8";

dbDelta($crearTabla);

Explicación del código

Lo primero que hay que hacer es cargar los ficheros wp-load.php y upgrade.php (en el caso de que ya estén cargados no es necesario, en este ejemplo el código esta en un fichero fuera de la jerarquía de wordpress).

Con «$prefix = $wpdb->prefix;» obtenemos el prefijo de las tablas para incorporarlo a la query.

$crearTabla contiene el «Create table» que va a ejecutar dbDelta, que es la función que se encargara de ejecutar la consulta pasada.

Pruebas realizadas con la versión 5.4.1 de wordpress.

PD: En el caso de no funcionar, comprobar que el «Create table» es correcto.

Mostrar consultas realizadas por mi WordPress

Si lo que estamos buscando es optimizar nuestro wordpress, esta función te puede venir bien para saber cuantas consultas realiza a la base de datos.

Lo primero que tenemos que hacer es habilitar SAVEQUERIES en nuestro fichero «wp-config.php«

define('SAVEQUERIES', true);

Esto le dice a WordPress que guarde todas las consultas.

Para obtener la consultas realizadas hay que utilizar $wpdb->query, añadimos este código a nuestra página (por ejemplo en el footer)

global $wpdb;
echo '<pre>';
print_r($wpdb->queries);
echo '</pre>';

Obtendremos:

[0] => Array
        (
            [0] => SELECT option_name, option_value FROM dg_options WHERE autoload = 'yes'
            [1] => 0.00107002258301
            [2] => require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), wp_not_installed, is_blog_installed, wp_load_alloptions
            [3] => 1588409077.08
            [4] => Array
                (
                )

        )

Pruebas realizadas en la versión de WordPress 5.4.1

Cuantas consulta a la base de datos realiza mi WordPress

WordPress nos facilita una función (get_num_queries()) para obtener el número de consultas a la base de datos:

get_num_queries()

Ejemplo:

Añado este código al fichero footer.php justo antes de cerrar el body (</body).

<?php echo '<!-- ' . get_num_queries() . ' consultas a la base de datos -->'; ?>

Para ver la cantidad tienes que ver el código fuente puesto que esta comentado en el html.

Resetear key de un array en PHP

En el siguiente ejemplo vamos a resetear las keys de un array en php.

$array[4] = 'PHP';
$array[6] = 'CSS';
$array[10] = 'Javascript';
$array[10] = 'Angular';

$arrayK = array_values($array);

$arrayK[0] = 'Apple';
$arrayK[1] = 'Orange';
$arrayK[2] = 'Peach';

Para resetear las key de un array vamos a utilizar la función array_values() de php, dicha función recibe por parámetro un array, retorna el array con las key reseteadas.

array_values ( array $array ) : array

Consultar los posts de wordpress desde un fichero externo

En este ejemplo vamos a realizar una consulta a la base de datos de wordpress utilizando $wpdb desde un fichero externo php (fuera de la estructura de wordpress)

WordPress $wpdb nos proporciona un objeto global para realizar las consultas a la base de datos, dicho objeto es una instancia de /wp-includes/wp-db.php.

Empécemos con el ejemplo:

Creamos un fichero php, yo le llamare exportacion.php y pegamos el siguiente código:

<?php
require './wp-load.php';
global $wpdb;

$prefix = $wpdb->prefix;
$table = $prefix . "posts";

$posts = $wpdb->get_results("SELECT * FROM $table");

print_r($posts);

Detallo, mi ejemplo esta creado en la raiz de ficheros:

require './wp-load.php';

Con este require añadimos toda la infraestructura de wordpress.

global $wpdb;

Invocamos a la variable global $wpdb (es el objeto que se va a encargar de realizar la consulta)

$prefix = $wpdb->prefix;

El atributo prefix nos devuelve el prefijo de las tablas (wp_), esto es necesario si has cambiado el prefijo de las tablas (yo lo suelo hacer).

$table = $prefix . "posts";

Prepara una variable con el nombre de la tabla que voy a realizar la consulta.

$posts = $wpdb->get_results("SELECT * FROM $table");

$wpdb->get_results realiza la consulta a la base de datos y me añade los registro a la variable $posts.

Ya podríamos recorrer la variable $posts y obtener los post.

Cómo eliminar un elemento de un array en Javascript

Para borrar un elemento de un array en Javascript sin saber su posición, habría que primero buscar la posición y después aplicar la función split.

var nombres = ["Jose","Pepe","Carlos"];
var posicion = nombres.indexOf("Pepe");

if (posicion > -1) {
   nombres.splice(posicion, 1);
}

[array].indexOf(valor) obtenemos la posición el array, hacemos un if para comprobar de que existe en caso contrario no entrar en el if.

Si lo que hemos pasado a indexOf esta en el array, aplicamos la función splice que se encarga de eliminar el elemento.

Activar/Enable en Mamp only_full_group_by (Mysql)

Como activar (enable) el parámetro de mysql only_full_group_by

Este es el error que daba el servidor mamp al realizar una consulta con group by:

Statement could not be executed (42000 - 1055 - Expression #15 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'basededatos.tabla.campo' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by)

Entramos al Phpmyadmin normalmente esta en «http://localhost/phpmyadmin», ahí nos dirigimos a la base de datos «mysql» vamos a la pestaña «Sql»

Ejecutamos:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

Solucionado ya podemos realizar consultas con group_by.

Pruebas realizadas con:

  • Mamp Versión 5.1
  • Mysql Versión 5.7.23
  • PhpMyAdmin 4.8.3

Obtener parámetros de la url con Javascript

Para obtener un parámetro de la url con el lenguaje de programación Javascript hay que implementar el siguiente código:

Url del ejemplo:

http://tecnicoweb.es/?idUsuario=3&pelo=rubio&ojos=verdes

Código para obtener el valor del parámetro «idUsuario».

var queryString = window.location.search;
var urlParams = new URLSearchParams(queryString);
var anuncioParam = urlParams.get('idUsuario');

Paso a paso.

window.location.search;

Obtenemos «?idUsuario=3&pelo=rubio&ojos=verdes»

var urlParams = new URLSearchParams(queryString);

URLSearchParams es un objeto y te proporciona diferentes funcionalidades, podemos ver todas su opciones aquí

var anuncioParam = urlParams.get('idUsuario');

Se extra el parametro que le pasamos al .get.

console.log(anuncioParam);

Consulta una colección (firebase) desde javascript

Vamos a consulta una colección de firebase (Cloud Firestore) desde javascript.

Lo primero que necesitamos es los datos de configuración que nos lo va a proporciona el mismo firebase, entramos en https://console.firebase.google.com/ seleccionamos el proyecto, a continuación pinchamos en rulina de la izquierda (ver la imagen)

Una vez dentro de la configuración bajamos hasta el apartado «Firebase SDK snippet» copiamos el código javascript y nos lo llevamos a nuestra fichero html.

<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js"></script>

<!-- TODO: Add SDKs for Firebase products that you want to use
     https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-analytics.js"></script>

<script>
  // Your web app's Firebase configuration
  var firebaseConfig = {
    apiKey: "xxxxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxxxxxxxx.firebaseapp.com",
    databaseURL: "https://xxxxxxxxxxxx.firebaseio.com",
    projectId: "xxxxxxxxxxxx",
    storageBucket: "xxxxxxxxxxxx.appspot.com",
    messagingSenderId: "xxxxxxxxxxxx",
    appId: "1:xxxxxxxxxxxx:web:xxxxxxxxxxxx",
    measurementId: "G-xxxxxxxxxxxx"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.analytics();
</script>

En el siguiente código vamos a iniciar la conexión a partir de la configuración que hemos obtenido ante desde firebase.

firebase.initializeApp(config);
var db = firebase.firestore();

Ya estaríamos conectado, para realizar una consulta de datos sería con la propiedad «collection»

db.collection("coches").get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
           console.log("Id",doc.id);
           console.log("Datos",doc.data());
        });
    });

Mostraremos por consola el «Id» y los «Datos» de nuestra tabla «coches»

Si queremos ordenar el listado por un campos, habría que añadir «orderBy».

db.collection("coches").orderBy("fechaPublicacion", "desc").get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
           console.log("Id",doc.id);
           console.log("Datos",doc.data());
        });
    });

Nos arrojara el listado de coches ordenado por «fechaPublicacion».

El código javascript (yo lo he incorporado en un fichero html) completo quedaría así:

<script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
        apiKey: "xxxxxxxxxxxxxxxxxxxx",
        authDomain: "xxxxxxxxxxxx.firebaseapp.com",
        databaseURL: "https://xxxxxxxxxxxx.firebaseio.com",
        projectId: "xxxxxxxxxxxx",
        storageBucket: "xxxxxxxxxxxx.appspot.com",
        messagingSenderId: "xxxxxxxxxxxx",
        appId: "1:xxxxxxxxxxxx:web:xxxxxxxxxxxx",
        measurementId: "G-xxxxxxxxxxxx"
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
    firebase.analytics();

    firebase.initializeApp(config);
    var db = firebase.firestore();

    db.collection("coches").orderBy("fechaPublicacion", "desc").get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            console.log("Id", doc.id);
            console.log("Datos", doc.data());
        });
    });

</script>

Si queremos hacer una consulta para filtrar los resultados sería añadiendo «where» :

db.collection("coches").where("diesel", "==", "si")
.get().then(function (querySnapshot) {
    querySnapshot.forEach(function (doc) {
           console.log("Id", doc.id);
           console.log("Datos", doc.data());
    });
});

Para recuperar un solo documento por su id:

 db.collection("coches").doc("5LMBbOG8vHWAEKb77wBv")
    .get().then(function (doc) {
            var coche = doc.data();
            console.log("Coche", coche);
    }).catch(function (error) {
            console.log("Error", error);
    });