miércoles, 25 de junio de 2025

Programación Reactiva con Streams en PHP: Beyond el Bucle For

Programación Reactiva con Streams en PHP: Beyond el Bucle For

La programación reactiva ofrece una alternativa poderosa al procesamiento iterativo tradicional, especialmente cuando se trata de grandes conjuntos de datos o flujos continuos de información. En PHP, podemos simular conceptos de programación reactiva utilizando iteradores, generadores y, más recientemente, bibliotecas dedicadas. Este artículo explora cómo implementar streams en PHP para procesar datos de manera asíncrona y no bloqueante.


<?php

/**
 * Un Stream en PHP basado en generadores.
 */
class Stream
{
    private $generator;

    public function __construct(callable $generatorFunction)
    {
        $this->generator = $generatorFunction();
    }

    public function map(callable $transform): Stream
    {
        $generator = $this->generator;
        return new Stream(function () use ($generator, $transform) {
            foreach ($generator as $item) {
                yield $transform($item);
            }
        });
    }

    public function filter(callable $predicate): Stream
    {
        $generator = $this->generator;
        return new Stream(function () use ($generator, $predicate) {
            foreach ($generator as $item) {
                if ($predicate($item)) {
                    yield $item;
                }
            }
        });
    }

    public function toArray(): array
    {
        return iterator_to_array($this->generator);
    }
}

// Ejemplo de uso:
$data = [1, 2, 3, 4, 5, 6];

$stream = new Stream(function () use ($data) {
    foreach ($data as $item) {
        yield $item;
    }
});

$result = $stream
    ->filter(function ($item) {
        return $item % 2 == 0; // Filtra los números pares
    })
    ->map(function ($item) {
        return $item * 2; // Multiplica por 2
    })
    ->toArray();

print_r($result); // Output: Array ( [0] => 4 [1] => 8 [2] => 12 )

?>
    

Este ejemplo muestra una implementación básica de un Stream en PHP. La clave es el uso de generadores (yield) para producir valores de manera lazy. Las operaciones map y filter no ejecutan el procesamiento inmediatamente, sino que crean nuevas instancias de Stream que encapsulan la lógica de transformación y filtrado. Solo cuando se llama a toArray (o cualquier operación terminal), se recorre el stream y se aplican las transformaciones.

La ventaja de este enfoque es que permite construir pipelines de procesamiento de datos complejos sin necesidad de cargar todo el conjunto de datos en la memoria a la vez. Esto es especialmente útil para archivos grandes, conexiones de bases de datos, o feeds de eventos en tiempo real.


<?php

// Ejemplo con un generador que simula datos de una base de datos
function databaseDataGenerator(int $limit): Generator
{
    for ($i = 1; $i <= $limit; $i++) {
        // Simula la obtención de datos de una base de datos
        yield ['id' => $i, 'value' => rand(1, 100)];
    }
}

$stream = new Stream(function() {
    return databaseDataGenerator(100); // Simula 100 registros de la base de datos
});

$filteredAndProcessedData = $stream
    ->filter(function ($item) {
        return $item['value'] > 50;
    })
    ->map(function ($item) {
        return ['processed_id' => 'P-' . $item['id'], 'processed_value' => $item['value'] * 2];
    })
    ->toArray();

print_r($filteredAndProcessedData);

?>
    

En conclusión, la programación reactiva con streams en PHP, aunque no nativa en el sentido estricto, puede ser simulada eficientemente usando generadores. Este patrón permite procesar grandes cantidades de datos de forma lazy, mejorando el rendimiento y la eficiencia en el uso de la memoria en aplicaciones PHP complejas. Bibliotecas más avanzadas ofrecen operadores adicionales y mayor control sobre el flujo de datos, pero comprender los fundamentos con generadores proporciona una base sólida.

Implementación de Rate Limiting Distribuido con Redis y PHP

Implementación de Rate Limiting Distribuido con Redis y PHP

El rate limiting, o limitación de velocidad, es una técnica crucial para proteger APIs y servicios web contra abusos, ataques DDoS y el consumo excesivo de recursos. Implementar un rate limiter robusto y escalable requiere una solución distribuida, especialmente en entornos con múltiples servidores. Este artículo explora cómo implementar un rate limiter distribuido utilizando Redis y PHP.

Redis, una base de datos en memoria, ofrece las características necesarias para una implementación eficiente de rate limiting distribuido, incluyendo operaciones atómicas y un rendimiento extremadamente rápido. Utilizaremos listas de Redis para rastrear las solicitudes dentro de un período de tiempo específico para cada usuario o IP.


<?php

// Configuración de Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

/**
 * Aplica rate limiting a una clave específica (por ejemplo, IP o ID de usuario).
 *
 * @param string $key La clave a la que se aplicará el rate limiting.
 * @param int $limit El número máximo de solicitudes permitidas.
 * @param int $periodo El período de tiempo en segundos dentro del cual se aplica el límite.
 * @return bool True si la solicitud está permitida, False si se excede el límite.
 */
function aplicarRateLimit(string $key, int $limit, int $periodo): bool {
    global $redis;

    $claveRedis = "rate_limit:" . $key;
    $timestampActual = time();

    // Elimina las solicitudes antiguas de la lista
    $redis->zRemRangeByScore($claveRedis, 0, $timestampActual - $periodo);

    // Obtiene el número de solicitudes restantes
    $conteoSolicitudes = $redis->zCard($claveRedis);

    // Verifica si se ha excedido el límite
    if ($conteoSolicitudes >= $limit) {
        return false; // Límite excedido
    }

    // Agrega la solicitud actual a la lista
    $redis->zAdd($claveRedis, $timestampActual, $timestampActual);

    // Configura un tiempo de vida para la clave (opcional, para limpieza)
    $redis->expire($claveRedis, $periodo * 2);

    return true; // Solicitud permitida
}

// Ejemplo de uso: Limitar las solicitudes de una IP a 10 por minuto
$ipUsuario = $_SERVER['REMOTE_ADDR'];
$limite = 10;
$periodo = 60; // 60 segundos (1 minuto)

if (aplicarRateLimit($ipUsuario, $limite, $periodo)) {
    // Procesar la solicitud
    echo "Solicitud permitida.";
} else {
    // Rechazar la solicitud
    http_response_code(429); // Too Many Requests
    echo "Demasiadas solicitudes. Inténtalo de nuevo más tarde.";
}

$redis->close();

Este código utiliza sorted sets de Redis para almacenar las marcas de tiempo de las solicitudes. La función `zRemRangeByScore` elimina las solicitudes antiguas, `zCard` cuenta las solicitudes actuales y `zAdd` agrega una nueva solicitud. Al usar sorted sets, podemos eficientemente contar y eliminar solicitudes basándonos en su marca de tiempo. La función `aplicarRateLimit` devuelve `true` si la solicitud está permitida y `false` en caso contrario, lo que permite rechazar solicitudes y devolver un código de estado HTTP 429 (Too Many Requests).

Recuerda ajustar los parámetros de configuración de Redis (`host`, `port`) según tu entorno. Además, considera implementar un middleware o un interceptor en tu framework PHP para aplicar el rate limiting de forma centralizada.

Manejo Avanzado de Sesiones en PHP con Regeneración Segura

Manejo Avanzado de Sesiones en PHP con Regeneración Segura

El manejo de sesiones es crucial en el desarrollo de aplicaciones web seguras. Si bien PHP proporciona funciones incorporadas para gestionar sesiones, es vital implementar prácticas avanzadas para proteger contra ataques como el secuestro de sesión. Este artículo explora cómo implementar una regeneración segura del ID de sesión para mitigar este riesgo.


<?php

// Iniciar o reanudar la sesión
session_start();

/**
 * Función para regenerar el ID de sesión de forma segura.
 *
 *  Regenera el ID de sesión y actualiza la marca de tiempo de inactividad.
 *  Esto ayuda a prevenir el secuestro de sesión al dificultar la predicción del ID
 *  y al limitar la validez de las sesiones robadas.
 */
function regenerateSessionId(): void {
    // Regenerar el ID de sesión (elimina el antiguo y crea uno nuevo)
    session_regenerate_id(true);

    // Actualizar la marca de tiempo de la última actividad.
    $_SESSION['last_activity'] = time();
}

// Ejemplo de uso: regenerar el ID de sesión al iniciar sesión un usuario.
if (isset($_POST['username']) && isset($_POST['password'])) {
    // Simulación de validación de usuario (¡no uses esto en producción!)
    if ($_POST['username'] === 'usuario' && $_POST['password'] === 'password') {
        $_SESSION['authenticated'] = true;
        regenerateSessionId(); // Regenerar el ID al iniciar sesión.
        echo "<p>Inicio de sesión exitoso. Nuevo ID de sesión: " . session_id() . "</p>";
    } else {
        echo "<p>Credenciales inválidas.</p>";
    }
}

// Ejemplo: Mostrar el ID de sesión actual
echo "<p>ID de sesión actual: " . session_id() . "</p>";

?>
    

La función `regenerateSessionId()` utiliza `session_regenerate_id(true)`. El parámetro `true` asegura que el ID de sesión antiguo se elimine, ofreciendo mayor seguridad. Es crucial llamar a esta función después de cualquier cambio significativo en los privilegios del usuario, como iniciar sesión, cambiar roles, o realizar acciones sensibles.


<?php

// Ejemplo de uso con tiempo de inactividad

session_start();

$inactive_timeout = 600; // 10 minutos de inactividad

if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $inactive_timeout)) {
    // Última actividad fue hace mucho tiempo, destruir la sesión.
    session_unset();     // Eliminar todas las variables de sesión
    session_destroy();   // Destruir la sesión
    header("Location: login.php"); // Redirigir a la página de inicio de sesión
    exit();
}

$_SESSION['last_activity'] = time(); // Actualizar la última actividad

?>
    

Además de la regeneración del ID, es esencial implementar un tiempo de inactividad para las sesiones. El código anterior muestra cómo verificar si ha pasado un tiempo determinado (por ejemplo, 10 minutos) desde la última actividad del usuario. Si el tiempo de inactividad se excede, la sesión se destruye, requiriendo que el usuario vuelva a iniciar sesión. Esta combinación de técnicas mejora significativamente la seguridad de las sesiones en tu aplicación PHP.

jueves, 2 de julio de 2015

Sacar número aleatorio entre 2 números php

Para sacar un número aleatorio entre 2 valores php utilizaremos la funcion RAND():



Esta línea cogerá un numero aleatorio entre 5 y 15 inclusive.

Crear ventana modal con jquery

Cargamos las librerías jquery y bootstrap.

1- Para crear una ventana modal lo primero que tenemos que hacer es declarar el enlace, donde en href colocaremos el id de la ventana moda:


2- Creamos la ventana modal que vamos a cargar:


Como se observa el id de la ventana modal es el mismo que el del href del enlace.

Crear tooltip en jquery

Hoy os enseñaremos como crear un tooltip en jquery:

Añadimos este javascript:


Una vez agregado ya podemos utilizarlo en cualquier sitio:

lunes, 29 de junio de 2015

Comprobar que checkbox esta seleccionado en jquery

Para comprobar si un checkbox esta checkeado en jquery hacemos lo siguiente:

Cuando pulsemos el boton editar comprobara si el checkbox llamado idservicio esta tickeado. Si esta tickeado devolvera verdadero y se ejecutara el form asociado y si no devolvera un alert y el formulario no se enviará.