Autor: Danny Rios Tolosa

  • PHP asíncrono: cómo manejar miles de solicitudes simultáneas

    PHP asíncrono: cómo manejar miles de solicitudes simultáneas

    En los primeros años de la web, PHP se ejecutaba en un ciclo relativamente simple: recibía una petición, ejecutaba el script de principio a fin y devolvía una respuesta. Este modelo síncrono es fácil de entender, pero limita la capacidad de una aplicación para aprovechar al máximo la CPU y los recursos de red. Si tu aplicación necesita esperar a que una consulta a la base de datos termine o a que un API externo responda, el intérprete queda bloqueado hasta que la operación finaliza. Cuando el tráfico crece, estos tiempos de espera se multiplican y el servidor no puede gestionar más peticiones.

    Para superar estas limitaciones, la comunidad PHP ha desarrollado librerías y extensiones que introducen concurrencia y paralelismo, permitiendo hacer múltiples trabajos a la vez. Esta guía explora cómo funcionan estas técnicas, qué herramientas están disponibles y cómo aplicarlas para que PHP maneje miles de solicitudes simultáneas.

    Concurrencia vs. paralelismo

    Es habitual confundir estos términos, pero se refieren a conceptos diferentes. Concurrencia implica que un programa puede avanzar en varias tareas intercalando su ejecución; por ejemplo, mientras espera la respuesta de una consulta puede procesar otra petición. Paralelismo, en cambio, significa ejecutar dos o más tareas al mismo tiempo en diferentes núcleos de CPU o procesos. Como explica un artículo de la comunidad Dev.to, la mayoría de las aplicaciones PHP tradicionales son secuenciales y no aprovechan ninguna de estas dos capacidades.

    Fibers: el soporte nativo para flujos cooperativos

    A partir de PHP 8.1 se introdujo la API de Fibers, pequeñas unidades de ejecución cooperativa similares a las corutinas de otros lenguajes. Las fibers permiten pausar y reanudar funciones sin bloquear la ejecución global. Sin embargo, los autores de la RFC advierten que no están pensadas para usarse directamente en las aplicaciones: su propósito es servir como base sobre la que librerías y frameworks construyan event loops y APIs asíncronas. En otras palabras, las fibers son ladrillos sobre los que se construyen herramientas de alto nivel.

    HTTP asíncrono con Guzzle

    Una de las primeras necesidades al trabajar de forma concurrente es realizar varias peticiones HTTP en paralelo. La librería Guzzle proporciona una interfaz sencilla para ello. Sus métodos getAsync, postAsync y similares devuelven objetos Promise conformes a la especificación Promises/A+, lo que permite encadenar llamadas o esperar a que varias se resuelvan a la vez. Por ejemplo, podemos enviar múltiples solicitudes a distintas APIs y usar Promise\\all() para esperar todas las respuestas antes de continuar con el procesamiento.

    AMPHP: concurrencia basada en fibers

    AMPHP es un conjunto de librerías que facilitan la concurrencia en PHP y, desde la versión 3, se basa internamente en fibers. Ofrece alternativas no bloqueantes a muchas funciones habituales, como el manejo de archivos, consultas MySQL o conexión con Redis, sin necesidad de instalar extensiones externas. Esto lo hace ideal para entornos donde no se puede instalar software adicional.

    AMPHP utiliza la función async() para lanzar operaciones que devuelven objetos Future: representaciones del resultado futuro de una operación asíncrona. Estas futures se pueden esperar con combinadores como await(), awaitAll(), awaitFirst() o awaitAny(), que permiten esperar a una, varias o todas las operaciones según convenga. Gracias a estas utilidades, se puede escribir código de inserción de datos, consultas a bases de datos y llamadas a APIs de forma concurrente con una sintaxis legible.

    ReactPHP: programación orientada a eventos

    Otra alternativa popular es ReactPHP, que proporciona un bucle de eventos de bajo nivel y utilidades para trabajar con flujos, resoluciones DNS, clientes y servidores HTTP, y otros componentes asíncronos. Su enfoque modular permite instalar sólo los paquetes necesarios, como un cliente HTTP asíncrono o un servidor HTTP.

    ReactPHP es especialmente últil para crear servidores web que gestionen muchas conexiones simultáneas sin bloquearse. Con su paquete react/http es posible crear un HttpServer que responda inmediatamente a las peticiones GET y diferir respuestas en otros casos, simulando operaciones como consultas a servicios externos o bases de datos. Al ser event‑driven, el servidor puede seguir atendiendo nuevas peticiones mientras espera que se resuelvan tareas pendientes.

    Otras opciones: Swoole y extensiones de sistema

    Además de las librerías mencionadas, existen extensiones como Swoole, que se compilan como módulos para PHP y proporcionan corrutinas, canales y servidores HTTP de alto rendimiento. Swoole transforma PHP en un servidor persistente con su propio gestor de eventos y tiene un rendimiento cercano a servidores escritos en C. Sin embargo, requiere instalar un módulo en el servidor y cambiar la forma de desplegar la aplicación.

    Otra posibilidad es recurrir a extensiones estándar como pcntl para crear procesos hijos o a la interfaz de subprocesos pthreads (en desuso), aunque estas opciones se centran más en paralelismo a nivel de procesos que en I/O asíncrona.

    Consejos para aplicaciones reales

    • Evalúa la complejidad: La programación asíncrona añade capas de abstracción. Antes de adoptarla, analiza si el cuello de botella de tu aplicación es realmente la espera de I/O o la CPU.
    • Combina técnicas: A veces basta con hacer peticiones concurrentes con Guzzle, y en otras conviene usar un bucle de eventos como AMPHP o ReactPHP. Incluso puedes delegar tareas pesadas a queues o workers que se ejecutan en segundo plano.
    • Mide y prueba: Utiliza herramientas de profiling y pruebas de carga para verificar que el uso de librerías asíncronas mejora el rendimiento. No todas las aplicaciones se benefician de la misma forma.

    Conclusión

    Aunque PHP nació como un lenguaje secuencial y bloqueante, hoy en día es posible gestionar miles de solicitudes de forma eficiente gracias a las fibras, promesas y bucles de eventos. Librerías como Guzzle, AMPHP y ReactPHP abstraen la complejidad de trabajar con promises y futures, y permiten escribir código asíncrono legible y mantenible. Elegir la herramienta adecuada y comprender las diferencias entre concurrencia y paralelismo te ayudará a escalar tus aplicaciones y sacar todo el partido al entorno donde se ejecutan.

  • Guía completa de operadores en PHP

    Guía completa de operadores en PHP

    LosLos operadores son los ladrillos con los que construimos expresiones en cualquier lenguaje de programación. En PHP no son la excepción: permiten sumar o restar valores, comparar variables, concatenar cadenas o incluso ejecutar comandos del sistema. Conocer cada tipo de operador y sus matices te ayudará a escribir código más claro y eficiente.

    1. Operadores aritméticos operadores son los ladrillos con los que construimos expresiones en cualquier lenguaje de programación. En PHP no son la excepción: permiten sumar o restar valores, comparar variables, concatenar cadenas o incluso ejecutar comandos del sistema. Conocer cada tipo de operador y sus matices te ayudará a escribir código más claro y eficiente.

    1. Operadores aritméticos

    Los operadores aritméticos se utilizan para realizar operaciones matemáticas sobre valores numéricos:

    • Suma (+) y resta (-): 3 + 2 devuelve 5, 7 - 4 devuelve 3.
    • Multiplicación (*) y división (/): 6 * 4 devuelve 24, 8 / 2 devuelve 4. Ten en cuenta que la división con enteros en PHP 8 devuelve un flotante (7/2 produce 3.5).
    • Módulo (%): devuelve el resto de una división. 10 % 3 devuelve 1.
    • Exponenciación (**): eleva un número a una potencia. 2 ** 3 devuelve 8. $a = 10;
      $b = 3;
      $mod = $a % $b; // $mod contiene 1
      $potencia = 2 ** 5; // 32

    2. Operadores de asignación

    Además del operador de asignación simple (=), PHP ofrece operadores compuestos que combinan asignación con una operación aritmética o de cadena:

    • +=, -=, *=, /=, %= y **=: incrementan o decrementan la variable. Por ejemplo: $x = 5;
      $x += 3; // ahora $x es 8
      $x *= 2; // ahora $x es 16
    • .=, operador de concatenación: agrega una cadena al final de otra: $mensaje = «Hola»;
      $mensaje .= » mundo»; // $mensaje es «Hola mundo»

    3. Operadores de comparación

    Comparan dos valores y devuelven un resultado booleano (“true” o “false”). Algunos de los más usados son:

    • Igualdad == y desigualdad !=: comparan solo el valor, no el tipo. «5» == 5 es true.
    • Identidad === y no identidad !==: comparan valor y tipo. «5» === 5 es false porque uno es cadena y el otro entero.
    • Mayor que > y menor que <, así como >= y <= para mayor o igual y menor o igual.
    • Nave espacial (&lt;=>): devuelve -1 si el primer operando es menor, 0 si son iguales o 1 si es mayor. Es útil para ordenar: $resultado = 3 <=> 5; // -1 porque 3 es menor que 5

    4. Operadores de incremento y decremento

    PHP soporta tanto incrementos y decrementos pre como post:

    • ++$var / $var++: incrementan la variable en 1. La versión prefija incrementa antes de devolver el valor; la posfija devuelve el valor antiguo y luego incrementa.
    • --$var / $var--: decrementan de manera similar. $a = 5;
      $b = $a++; // $b es 5 y luego $a pasa a 6
      $c = ++$a; // $a pasa a 7 y $c también es 7

    5. Operadores lógicos

    Son esenciales para controlar el flujo de los programas. Operan sobre valores booleanos:

    • AND (&amp;&amp; y and): devuelven true si ambos operandos son verdaderos. La versión de baja prioridad (and) se evalúa después de las asignaciones.
    • OR (|| y or): devuelven true si al menos uno de los operandos es verdadero. Al igual que and, or tiene menor prioridad.
    • XOR (xor): devuelve true si exactamente uno de los operandos es verdadero.
    • NOT (!): niega un valor booleano. $esMayor = ($edad >= 18) && $tieneDocumento;
      $esGratis = ($usuario == «admin») || ($usuario == «editor»);

    6. Operadores de cadena

    La concatenación se realiza con el punto (.). Para unir varias cadenas de manera eficiente, también puede usarse .=, como vimos en los operadores de asignación.

    $nombre = "Juan";
    $apellido = "Pérez";
    $completo = $nombre . " " . $apellido; // "Juan Pérez"
    

    7. Operadores de arrays

    Estos operadores trabajan sobre arrays:

    • Unión (+): combina dos arrays, pero los elementos de la derecha no reemplazan a los de la izquierda si comparten claves.
    • Igualdad (==): devuelve true si tienen las mismas parejas clave/valor, sin importar el orden.
    • Identidad (===): devuelve true si tienen las mismas parejas clave/valor en el mismo orden y del mismo tipo.
    • Desigualdad (!= o &lt;>) y no identidad (!==). $a = [«color» => «rojo», «valor» => 2];
      $b = [«color» => «rojo», «valor» => 2, «extra» => 4];
      $c = $a + $b; // $c tiene las claves de $a y añade la clave «extra» de $b

    8. Operadores ternarios y de coalescencia nula

    El operador ternario es una forma abreviada de una estructura condicional if:

    $edad = 20;
    $mensaje = ($edad >= 18) ? "Eres mayor de edad" : "Eres menor de edad";
    

    Desde PHP 7 existe una versión abreviada: ??, denominada operador de coalescencia nula. Devuelve el operando de la izquierda si existe y no es null; de lo contrario, devuelve el de la derecha. Es especialmente útil al trabajar con arrays o valores opcionales:

    $nombre = $_GET["nombre"] ?? "Invitado";
    

    9. Operador de control de errores y ejecución de comandos

    • Control de errores (@): suprime cualquier mensaje de error generado por la expresión. Debe usarse con cautela, ya que puede ocultar problemas serios. @$resultado = 1 / 0; // no muestra el warning de división por cero
    • **Ejecutar comandos del sistema (`)**: los backticks permiten ejecutar un comando de la línea de comandos. Por motivos de seguridad, es preferible utilizar funciones comoshell_exec()oproc_open()` y siempre validar la entrada del usuario. $fecha = date; // asigna la salida del comando ‘date’

    10. Operadores bit a bit

    Trabajan sobre la representación binaria de enteros y son útiles en algoritmos de bajo nivel, como manipulación de permisos o flags:

    • AND (&amp;): establece un bit a 1 sólo si ambos bits correspondientes son 1.
    • OR (|): establece un bit a 1 si alguno de los bits correspondientes es 1.
    • XOR (^): establece un bit a 1 si sólo uno de los bits es 1.
    • NOT (~): invierte cada bit.
    • Desplazamiento a la izquierda (&lt;&lt;) y a la derecha (>>): mueven los bits de un número. $permisoLectura = 0b0100;
      $permisoEscritura = 0b0010;
      $permisos = $permisoLectura | $permisoEscritura; // 0b0110
      $tieneLectura = ($permisos & 0b0100) !== 0; // true

    11. Precedencia y asociatividad

    Cuando combinas varios operadores, PHP necesita saber cuál evaluar primero. La precedencia determina la prioridad (por ejemplo, la multiplicación se evalúa antes que la suma) y la asociatividad define el orden en caso de igualdad de precedencia (izquierda a derecha o derecha a izquierda). Para evitar confusiones y mejorar la legibilidad, utiliza paréntesis.

    $resultado = 3 + 4 * 2; // es 11 porque * tiene mayor prioridad que +
    $resultado = (3 + 4) * 2; // es 14
    

    Conclusión

    PHP ofrece un abanico de operadores que van desde tareas básicas como sumar o concatenar hasta operaciones de bajo nivel con bits y ejecución de comandos. Dominar su sintaxis y entender su precedencia te permitirá escribir código más expresivo y menos propenso a errores. Siempre que tengas dudas sobre cómo se evaluará una expresión compleja, recurre a los paréntesis para dejar claro el orden de las operaciones.

  • Trucos avanzados de Eloquent que impulsan el rendimiento de tu aplicación Laravel

    Trucos avanzados de Eloquent que impulsan el rendimiento de tu aplicación Laravel

    Trucos avanzados de Eloquent que impulsan el rendimiento de tu aplicación Laravel

    Eloquent es uno de los puntos fuertes de Laravel: facilita la interacción con bases de datos a través de un ORM expresivo. Sin embargo, esta comodidad tiene un coste. Es muy fácil escribir consultas que realizan demasiadas operaciones o generan una avalancha de solicitudes a la base de datos. En esta entrada exploraremos técnicas avanzadas para exprimir todo el potencial de Eloquent sin sacrificar el rendimiento. Todas las recomendaciones están pensadas para desarrolladores hispanohablantes y se basan en prácticas contrastadas en proyectos reales.

    1. Usa eager loading para evitar el problema N + 1

    La carga diferida hace que las relaciones se consulten únicamente cuando accedes a ellas. Si recorres una colección de modelos y en cada iteración accedes a la relación ($book-&gt;author), se ejecuta una consulta adicional por cada registro. Este patrón se conoce como problema N + 1: una consulta inicial más una por cada relación. En proyectos con cientos de filas esto se traduce en cientos de consultas innecesarias y tiempos de respuesta elevados.

    La solución es eager loading, que realiza las consultas de las relaciones en bloque. Eloquent lo permite con el método with():

    // Sin eager loading: genera N+1 consultas
    $books = Book::all();
    foreach ($books as $book) {
        echo $book->author->name;
    }
    
    // Con eager loading: solo 2 consultas
    $books = Book::with('author')->get();
    foreach ($books as $book) {
        echo $book->author->name;
    }
    

    Además de cargar relaciones, puedes aprovechar withCount() y withSum() para obtener datos agregados (conteos, sumas, promedios) sin cargar todos los registros. Esto evita ejecutar métodos como $author-&gt;books()-&gt;count() dentro de bucles, que vuelven a consultar la base de datos.

    2. Recupera solo las columnas que necesitas

    Por defecto, Eloquent::all() selecciona todas las columnas (SELECT *). Si tu tabla contiene columnas grandes (texto, JSON, blobs), estás transportando datos que no usas. Para reducir el tráfico y acelerar las consultas puedes limitar las columnas con select() o addSelect():

    // Solo necesitamos id y nombre
    $users = User::select('id', 'name')->get();
    
    // O bien añadir columnas a una consulta ya existente
    $posts = Post::where('published', true)->addSelect(['id', 'title'])->get();
    

    Otra ventaja de especificar columnas es que le indicas al optimizador de consultas qué índices puede utilizar, lo que mejora aún más el rendimiento.

    3. Divide grandes cantidades de datos con chunk() o cursor()

    Cuando procesas tablas con miles o millones de registros, cargar todos los modelos en memoria puede agotar la RAM y ralentizar el servidor. Eloquent ofrece dos métodos para trabajar con grandes conjuntos de datos de manera eficiente:

    • chunk() recupera registros en lotes. Por ejemplo, Model::chunk(100, function ($items) { … }); ejecuta la consulta en bloques de 100 filas y libera la memoria después de cada bloque.
    • cursor() devuelve una colección perezosa que itera sobre los registros sin cargarlos todos a la vez. Es especialmente útil cuando necesitas recorrer una tabla completa.

    Ambas técnicas mantienen la huella de memoria baja y permiten a tu aplicación procesar datos masivos de forma segura.

    4. Define query scopes para reutilizar lógica compleja

    Los scopes encapsulan condiciones de consulta repetitivas en métodos reutilizables. Declarando un scope dentro del modelo (public function scopeActive($query) { … }) puedes componer consultas legibles y consistentes. Según el artículo de DEV Community, utilizar scopes mantiene el código organizado y reduce errores al escribir condiciones complejas.

    Por ejemplo:

    // En el modelo User
    public function scopeActive(Builder $query): Builder
    {
        return $query->where('active', true);
    }
    
    // Uso
    $activeUsers = User::active()->orderBy('created_at', 'desc')->paginate(20);
    

    También puedes crear scopes dinámicos (o “global scopes”) para filtrar automáticamente por empresa, idioma, etc. Los scopes ayudan a evitar duplicar lógica y facilitan los ajustes posteriores.

    5. Implementa caché para consultas intensivas

    Cuando ejecutas consultas que no cambian con frecuencia (por ejemplo, contar productos o calcular sumas), puedes almacenar sus resultados en caché. El propio artículo de DEV Community destaca la importancia de la caché para mejorar la velocidad en aplicaciones Laravel. Laravel ofrece varias formas de hacerlo:

    use Illuminate\\Support\\Facades\\Cache;
    
    // Caché de 60 minutos para el total de posts publicados
    $count = Cache::remember('posts.count', 60 * 60, function () {
        return Post::where('published', true)->count();
    });
    

    También puedes emplear rememberForever() para almacenar datos de forma indefinida hasta que los invalides manualmente. Si tus consultas dependen de parámetros (por ejemplo, usuario_id), incluye esos parámetros en la clave de caché para evitar colisiones.

    6. Aprovecha soft deletes y observadores

    El uso del trait SoftDeletes te permite eliminar registros sin perderlos físicamente. Esta funcionalidad es útil para auditoría y recuperación de datos, y se activa añadiendo use SoftDeletes; en el modelo y creando una columna deleted_at. El artículo de DEV Community recuerda que los “soft deletes” son una forma de mejorar la seguridad de tus datos.

    Los observadores (observers) permiten asociar lógica a eventos del modelo (crear, actualizar, eliminar). Por ejemplo, puedes enviar notificaciones, registrar cambios o sincronizar datos con otros sistemas cuando se cree un registro. Encapsular estas acciones en observadores mantiene los controladores limpios y hace que la aplicación sea más modular.

    7. Usa paginación adecuada: paginate(), simplePaginate() y cursorPaginate()

    Mostrar tablas enormes sin paginar dispara el uso de memoria y ralentiza la interfaz. Laravel ofrece varias opciones:

    • paginate() genera una consulta que incluye el recuento total de registros. Es la opción habitual para mostrar números de página y resultados de pocos miles de filas.
    • simplePaginate() evita el conteo total, lo que reduce el número de consultas. Ideal para listas largas donde no necesitas saber cuántas páginas hay.
    • cursorPaginate() utiliza un cursor basado en claves ordenadas, eliminando la necesidad de contar registros y mejorando la eficiencia en bases de datos grandes. Requiere ordenar por un campo único (por ejemplo, id).

    Seleccionar el tipo de paginación correcto reducirá el tiempo de respuesta y optimizará el rendimiento de las consultas.

    8. Considera consultas complejas con Query Builder o SQL bruto

    Aunque Eloquent hace que el código sea más legible, a veces es mejor escribir consultas manualmente. El Query Builder de Laravel permite construir consultas SQL complejas de forma programática y admite operaciones como joins, subconsultas y cláusulas específicas del motor de base de datos. Para operaciones masivas (bulk updates, inserts) o informes complejos, usar SQL bruto (DB::select(...)) puede ser más eficiente.

    Conclusión

    Eloquent es una herramienta poderosa, pero como cualquier abstracción, puede generar cuellos de botella si no se usa correctamente. La clave está en entender cómo funciona bajo el capó y aplicar estrategias como eager loading, limitar columnas, procesar datos en lotes, reutilizar scopes, cachear resultados, usar soft deletes y paginar correctamente. Adoptar estas prácticas mejorará la escalabilidad de tus aplicaciones Laravel y hará que tus consultas sean más rápidas y predecibles.

  • Buenas prácticas modernas para Laravel en 2025

    Buenas prácticas modernas para Laravel en 2025

    Laravel sigue siendo uno de los frameworks PHP más populares y su ecosistema evoluciona constantemente. Para mantener una base de código limpia y sostenible en 2025 conviene adoptar las siguientes prácticas:

    1. Mantén tu proyecto actualizado: usa siempre la última versión estable de Laravel (actualmente la 12.x) y actualiza las dependencias con composer update. Esto aporta mejoras de rendimiento y parches de seguridad.
    2. Escribe pruebas automatizadas: una suite de tests evita que los errores críticos lleguen a producción y proporciona confianza al refactorizar. Considera usar PHPUnit y Pest para las pruebas unitarias y de integración.
    3. Respeta la estructura estándar: el árbol de directorios de Laravel está pensado para que los equipos colaboren fácilmente. Almacena controladores en app/Http/Controllers, modelos en app/Models y vistas en resources/views.
    4. Usa FormRequest para la validación: crea clases que extienden FormRequest para encapsular las reglas y mensajes de validación, de manera que los controladores se mantengan limpios.
    5. Emplea controladores de acción única y middleware: define un único método __invoke() por controlador cuando solo exista una acción, e implementa middleware personalizados para evitar duplicar código en rutas.
    6. Encapsula la lógica de negocio: extrae el código complejo a service classes o actions para mejorar la legibilidad y reutilización.
    7. Aprovecha los helper functions y colecciones: los métodos de la clase Collection (como map, filter o reduce) permiten escribir código expresivo y conciso.
    8. Optimiza el rendimiento: actualiza a PHP 8.2 para aprovechar el compilador JIT, usa Laravel Octane para servir peticiones de forma concurre ntecache:remember y php artisan config:cachey aplicarememberyestrategias de cacheo (como a base de datos.

    Adoptar estas prácticas te permitirá escribir código mantenible, seguro y rápido, reduciendo a la vez la deuda técnica.

  • Novedades en Firebase Studio y herramientas open-source para SaaS

    Novedades en Firebase Studio y herramientas open-source para SaaS

    Firebase Studio ha renovado su suite con mejoras que facilitan la creación de aplicaciones basadas en IA y la integración con el ecosistema de Google.

    • Plantillas optimizadas por IA para frameworks como Flutter, Angular, React y Next.js, que generan estructuras de código a partir de descripciones en lenguaje natural y se integran con Material Design.
    • Integración directa con servicios de Firebase (FireStore, Auth, Storage y Hosting) para que los proyectos ya estén conectados desde el inicio.
    • Sistema de bifurcación de proyectos que permite clonar un workspace y experimentar sin afectar el código principal.
    • Mejores prompts y plantillas personalizadas, con soporte para retroalimentación de las respuestas.
    • Carga de proyectos de hasta 100 MB, ideal para trabajar con librerías pesadas.

    Además existen alternativas open‑source que te permiten montar servicios SaaS sin depender de proveedores cerrados:

    • Supabase: plataforma de base de datos Postgres con API en tiempo real, autenticación integrada y almacenamiento de archivos.
    • PocketBase: backend ligero en un solo binario con base de datos, autenticación y notificaciones en tiempo real.
    • Dokku: PaaS auto‑gestionado para desplegar aplicaciones mediante Git y añadir complementos como bases de datos o certificados SSL.
    • Airbyte: plataforma de integración de datos con una biblioteca de conectores para mover información entre servicios.
    • Appwrite: backend auto‑alojado que ofrece base de datos, funciones serverless, autenticación y almacenamiento.
    • Ory Kratos: sistema de gestión de identidad con autenticación sin contraseñas y MFA.
    • Otras herramientas como Plane, Coolify, n8n, LLMWare, Trieve, Affine, Hanko, Taubyte y Plausible cubren necesidades como gestión de proyectos, despliegue de contenedores, automatización de flujos, bases de datos vectoriales y analítica privada.

    Estas herramientas demuestran que es posible construir aplicaciones completas con tecnología abierta, combinando el poder de Firebase Studio para acelerar el front‑end con un backend flexible y controlado.

  • Avances en Yii 3: HTTP Runner 3.2 y Middleware 1.1

    Avances en Yii 3: HTTP Runner 3.2 y Middleware 1.1

    La versión 3.2 de HTTP Runner en Yii 3 incorpora mejoras importantes. Ahora el núcleo de Yii puede obtener la respuesta de la aplicación sin enviarla directamente al cliente gracias al nuevo método HttpApplicationRunner::runAndGetResponse(), lo que facilita pruebas y composición de aplicaciones. El constructor del corredor acepta parámetros opcionales para inyectar un emisor (Emitter) y habilitar o deshabilitar middlewares específicos como RemoveBodyByStatus, ContentLength y HeadRequest, permitiendo una configuración más granular. También se refactorizó RequestFactory para utilizar propiedades de sólo lectura, y se solucionó un fallo que eliminaba la cabecera Content‑Length cuando ya estaba definida.

    La biblioteca Middleware de Yii llega a la versión 1.1 con una limpieza profunda y novedades. Este lanzamiento sube la versión mínima de PHP a 8.1 y actualiza los paquetes dependientes (router 4, session 3, cookie 1.2.3). Algunas middlewares como CorsAllowAll, ForceSecureConnection, HttpCache y TagRequest quedan obsoletas. Se añadió compatibilidad con la interfaz ClockInterface del estándar PSR‑20 para que el middleware Locale pueda obtener la hora actual. Además, se marcaron parámetros como anulables para mejorar la flexibilidad al inyectar servicios.

  • Yii Dummy Provider 1.1: proveedor ficticio para pruebas y bases de datos

    Yii Dummy Provider 1.1: proveedor ficticio para pruebas y bases de datos

    Yii Dummy Provider 1.1 es una herramienta pensada para quienes necesitan ejecutar pruebas de sus aplicaciones sin depender de un motor de bases de datos real. La versión 1.1 publicada el 7 de julio de 2025 introduce un paquete virtual llamado yiisoft/db implementation que proporciona una implementación ficticia de la interfaz de base de datos; esto permite simular consultas e inserciones de forma sencilla.

    Al usar este proveedor dummy, los desarrolladores pueden crear y validar modelos, formular consultas o probar lógicas de negocio sin tener que levantar un servidor MySQL, PostgreSQL u otro servicio. La iniciativa busca unificar las dependencias de las distintas bibliotecas del ecosistema Yii para que todas puedan referenciar este paquete virtual en lugar de incluir un motor concreto, facilitando así el diseño de pruebas y la portabilidad.

  • Yii Validator 2.4 y 2.5: mejoras en mensajes y nuevas utilidades

    Yii Validator 2.4 y 2.5: mejoras en mensajes y nuevas utilidades

    La biblioteca de validación de Yii 3 sigue evolucionando. En la versión 2.4 se mejoraron los mensajes de error y se refinó la API para ofrecer una experiencia de desarrollo más coherente. Las mejoras incluyen una mejor estructuración de los resultados de validación y mensajes más claros para el usuario.

    La versión 2.5 introduce el método Result::getPropertyErrorMessagesByPath(), que permite obtener los mensajes de error de una propiedad siguiendo un camino específico dentro de un modelo complejo. Esto facilita el acceso a los problemas de validación de campos anidados. Junto con otras pequeñas mejoras y correcciones, estas actualizaciones hacen que la validación en Yii sea más potente y fácil de usar.

  • PHP 8.5 en camino: principales novedades

    PHP 8.5 en camino: principales novedades

    PHP 8.5 estará disponible el 20 de noviembre de 2025 y actualmente se encuentra en fase alfa. Esta versión añade varias características pensadas para hacer la vida más cómoda a los desarrolladores y mejorar la experiencia del lenguaje.

    Entre las novedades destacadas están las funciones array_first() y array_last(), que permiten obtener directamente el primer y el último valor de un array sin tener que escribir código extra. También se introduce el operador de tubería (|>), que facilita encadenar llamadas de funciones de manera más limpia y legible.

    Otra incorporación son las funciones get_exception_handler() y get_error_handler(), útiles para recuperar los manejadores de excepciones y errores en tiempo de ejecución. A nivel de red, PHP 8.5 añade curl_multi_get_handles(), que devuelve las conexiones asociadas a un manejador múltiple de cURL, y define la constante PHP_BUILD_DATE para conocer la fecha de compilación de la binaria.

    En materia de internacionalización, se suma la función locale_is_right_to_left() (y su método OOP equivalente) para detectar si un idioma se escribe de derecha a izquierda, y se incorpora la clase Intl\IntlListFormatter para dar formato a listas de forma amigable. Para la CLI, un nuevo parámetro php –ini=diff muestra únicamente las directivas de configuración que difieren de los valores por defecto.

    Todas estas novedades hacen de PHP 8.5 una versión especialmente interesante, pese a que todavía está en desarrollo. Se esperan más cambios antes del lanzamiento definitivo, pero el avance ya apunta a un lenguaje más expresivo y cómodo.

  • Agregar certificados de seguridad auto-firmados en Windows – Linux – Mac

    Agregar certificados de seguridad auto-firmados en Windows – Linux – Mac

    En casi todos los proyectos que se desarrollan actualmente, se habla en cualquier medida, de la seguridad y si es un proyecto web o con operación sobre internet, se escuchara en alguna medida el uso de certificados de seguridad; pero para la generación de estos se requiere por lo menos de un domino único y conexión a internet.

    Teniendo en cuenta este panorama, me encuentro en un proyecto donde se requiere tener conexión con un docker registry para poder cargar y descargar imagenes docker, este servidor estará desconectado de internet y no tendrá dominio registrado.

    Al hacer la conexión de las maquinas que descargan imágenes, este obliga a que la conexión se haga por medio de HTTPS , por lo cual es requerido crear un certificado auto-firmado, pero para que esto sirva, se debe descargar e instalar este en cada maquina que se quiera conectar, lo cual voy a explicar a continuación.

    Instacion en Windows

    Para agregar el certificado debe ejecutar el siguiente comando

    certutil -addstore -f "ROOT" new-root-certificate.crt
    

    Donde new-root-certificate.crt es el nombre de archivo del certificado

    Para desinstalar el certificado, debe ejecutar el siguiente comando

    certutil -delstore "ROOT" serial-number-hex
    

    Donde serial-number-hex, es el identificador del certificado a desinstalar

    Instalacion en MacOS

    Para agregar el certificado de a macos ejecute el siguiente comando

    sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/new-root-certificate.crt
    

    Para remover el certificado del sistema, ejecute el siguiente comando

    sudo security delete-certificate -c "&lt;nombre del certificado a remover>"
    

    Linux(Ubuntu, Debian)

    Para agregar el certificado a linux, debe seguir los siguientes pasos

    sudo cp foo.crt /usr/local/share/ca-certificates/foo.crt
    sudo update-ca-certificates
    

    Teniendo en cuenta que el nombre del archivo foo.crt debe cambiarse a como se llame su certificado

    Para remover el certificado debe ejecutar el siguiente comando

    sudo rm /usr/local/share/ca-certificates/foo.crt
    sudo update-ca-certificates --fresh
    

    Teniendo en cuenta que el nombre del archivo foo.crt debe cambiarse a como se llame su certificado

    Espero que esta breve explicación les sea de ayuda.

  • Paths de wordpress que puedes necesitar

    Paths de wordpress que puedes necesitar

    Estas son algunos de los paths de wordpress que puedes necesitar para realizar desarrollos de temas o plugins para WordPress.

    plugins_url(): Retorna el path de instalación de los plugins.

    get_theme_root(): Retorna el path raíz de instalación de los temas (theme).

    get_template_directory_uri(): Retorna la URL donde están guardados los archivos del tema (theme) actual.

    admin_url(): Retorna la dirección de las páginas administrativas de WordPress.

    content_url(): Indica donde se encuentra el directorio wp-content.

    site_url() y home_url(): Retorna la dirección del sitio.

    includes_url(): Retorna el path de los archivos de INCLUDE de WordPress.

    wp_upload_dir(): Retorna el path del directorio donde se almacenan los archivos subidos por el usuario.




     

  • Instalacion del wifi usb TL-WN725N en el raspberry pi

    Instalacion del wifi usb TL-WN725N en el raspberry pi

    Si ustedes como nosotros se han encontrado con el problema de querer conectar a la red la raspberry pi, pero de forma inalambrica y tienen disponible una wifi usb TP-LINK TL-WN725N, aqui les comentaremos los pasos necesarios para instalarla con exito.

    Nota

    Para poder seguir los pasos del siguiente tutorial deber saber hacer una conexion por medio de ssh o estar trabajando en el bash del raspberry pi

    Pasos de instalación en el raspberry

    Paso 1

    lo primero que debemos hacer es actualizar el firmware del raspberry pi

    rpi-update
    

    En caso que el comando anterior nos llegue a dar un error, es porque no tenemos instalado el paquete y debemos que instalarlo asi

    sudo apt-get install rpi-update
    

    con esto ya tendrán el comando rpi-update listo para actualizar el raspberry pi

    Paso 2

    Ahora debemos actualizar los paquetes del sistema operativo del raspberry pi, esto se hace por medio de los siguientes comandos (tenga en cuenta que cada linea es un comando que debe ejecutar)

    sudo apt-get update
    sudo apt-get upgrade
    sudo reboot
    

    la explicación de estos comandos es la siguiente, el primero actualiza las lista de paquetes identificando asi cuales son los paquetes obsoletos y que deben ser actualizados, el segundo comando se usa para actualizar aquellos paquetes identificados como desactulizados en el comando anterior y el ultimo comando ejecuta un reinicio para que la actualización tenga efecto en todos los componentes actualizados.

    Paso 3

    antes de instalar el controlador necesitamos saber una información para poder saber cual es el archivo que vamos a descargar.

    uname -a
    

    el resultado sera algo como esto

    Linux termometro 3.12.33+ #722 PREEMPT Sat Nov 22 12:03:51 GMT 2014 armv6l GNU/Linux
    

    de esta información debemos de tener en cuenta lo siguiente 3.12.33+ #722 pues con esta información debemos seleccionar de la lista la url de descarga del controlador

    Paso 4

    ahora vamos al siguiente link+ para poder conocer cual es fragmento de url de descarga, de acuerdo con la informacion anterior (3.12.33+ #722)

    Raspberry usb wifi

    Con la informacion que esta subrayada, completamos la url quedando asi
    https://dl.dropboxusercontent.com/u/80256631/8188eu-20141107.tar.gz, de esta url la informacion que siempre varia es la que se encuentra despues de ultimo slash, esta url la necesitamos para el completar el primer comando del paso 5.

    Paso 5

    ahora si vamos a descargar e instalar el controlador

    wget https://dl.dropboxusercontent.com/u/80256631/8188eu-20141107.tar.gz
    tar -zxvf 8188eu-20141107.tar.gz
    sudo install -p -m 644 8188eu.ko /lib/modules/3.12.33+/kernel/drivers/net/wireless
    sudo insmod /lib/modules/3.12.33+/kernel/drivers/net/wireless/8188eu.ko
    sudo depmod -a
    sudo reboot
    

    En el caso de los comandos 3 y 4 es necesario cambiar 3.12.33+ por el valor que nos dio el comando del paso 3

    Paso 6

    Teniendo esto y después del reinicio que se genero en el ultimo comando del paso anterior, procedemos a hacer la conexion wifi, pues ya la debe haber reconocido.

    Para hacer la conexion wifi se debe modificar el archivo del sistema /etc/wpa_supplicant/wpa_supplicant.conf agregandole lo siguiente

    network={
    ssid="nombre de la red"
    psk="password de la red"
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=TKIP
    auth_alg=OPEN
    }
    

    Paso 7

    Este ultimo paso es opcional, aunque a veces muy necesario.

    En ocasiones la conexion wifi que acabamos de configurar entra en reposo cuando no esta transmitiendo, el problema surge cuando se quiere volver a conectar con el raspberry, pues la conexion wifi no responde, para solucionar este problema debemos de hacer lo siguiente.

    debemos crear el archivo /etc/modprobe.d/8188eu.conf con el siguiente comando

    sudo nano /etc/modprobe.d/8188eu.conf
    

    Este comando abrirá el editor nano, el cual nos va a permitir en el nuevo archivo ingresar la siguiente información.

    options 8188eu rtw_power_mgnt=0 rtw_enusbss=0
    

    Con esta linea dentro del archivo oprimimos CTRL+o y CTRL+X para guardar y cerrar respectivamente, y por ultimo un reinicio mas al raspberry y desconectar el cable de red para que use la conexion wifi.

  • Jquery Tips (Metodos)

    Jquery Tips (Metodos)

    Después de aprender a seleccionar con jQuery los elementos del documento html por medio de los selectores anteriormente comentados, es importante saber qué hacer con estos, por lo cual vamos a ver cómo aplicar métodos a un elemento seleccionado.

    Ejemplos de aplicación de métodos con jQuery

    
    // Aplica propiedad CSS al elemento seleccionado
    $(&amp;quot;. className&amp;quot;). css(&amp;quot; border&amp;quot;, &amp;quot;1px solid red&amp;quot;); 
    
    // Aplica CSS de un elemento usando un objeto
    $(&amp;quot;. className&amp;quot;). css({&amp;quot; border&amp;quot;: &amp;quot;1px solid red&amp;quot;}); 
    
    // Aplica dos CSS a los objetos seleccionados
    // (notese que este ejemplo usa una notación de objeto para el caso de las propiedades que
    // se desean establecer por medio del método CSS de jquery, por esta razon se
    // puede usar para aplicar mas de una propiedad)
    $(&amp;quot;. className&amp;quot;). css({ &amp;quot;color&amp;quot;: &amp;quot;red&amp;quot;, &amp;quot;font-weight&amp;quot;: &amp;quot;bold&amp;quot; });
    
    // Esconde la segunda fila de la tabla
    $(&amp;quot; table tr:nth-child( 2)&amp;quot;). hide(); 
    
    // Convierte la lista &amp;lt; ul id = &amp;quot;list&amp;quot; &amp;gt; en una lista ordenable
    $(&amp;quot; ul# list&amp;quot;). sortable(); 
    
    // Selecciona todos  los elementos y los filtra usando el metodo &amp;quot;is&amp;quot;
    $(&amp;quot;*&amp;quot;). is(&amp;quot; p&amp;quot;); 
    
    // El metodo &amp;quot;is&amp;quot; es usado con la variable &amp;quot;this&amp;quot; dentro de los callback para poder indetificar su tipo
    $(this). is(&amp;quot;div&amp;quot;); 
    
    // Selecciona un elemento y con el metodo &amp;quot;parent&amp;quot; selecciona el elemento padre
    $(&amp;quot;p#short&amp;quot;). parent();
    
    // Selecciona todos los inputs si estos tienen como padre el elemento &amp;quot;form&amp;quot;Â
    $(&amp;quot; input&amp;quot;). parent(). is(&amp;quot; form&amp;quot;); 
    
    // Selecciona y aplica el estilo CSS, limpia la cola, hace una nueva seleccion y aplica nuevo CSS, en otras palabras los elementos 
    
    quedan con fuente de color azul y los elementos quedan con fuente de color rojo
    $(&amp;quot; p&amp;quot;). css(&amp;quot; color&amp;quot;, &amp;quot;blue&amp;quot;). end(). add(&amp;quot; b&amp;quot;). css(&amp;quot; color&amp;quot;, &amp;quot;red&amp;quot;); 
    
    // si se hace sin el metodo &amp;quot;end&amp;quot; entre los elementos ambos quedan con fuente de color rojo.
    $(&amp;quot; p&amp;quot;). css(&amp;quot; color&amp;quot;, &amp;quot;blue&amp;quot;). add(&amp;quot; b&amp;quot;). css(&amp;quot; color&amp;quot;, &amp;quot;red&amp;quot;);
    
    
  • Jquery tips (Selectores)

    Jquery tips (Selectores)

    JQuery es sin duda el framework javascript mas popular en la web, por esto en ocasiones es importante tener a la mano información que aunque es básica, nos ayudara a resolver varios problemas.

    Empecemos con lo basico

    $(" div");
    

    Es lo mismo que

    jQuery(" div");
    

    selectores

    // Selector por tag
    $("body"); 
    
    // Selector por id del elemento 
    $("# id"); 
    
    // Selector por clase del elemento 
    $(".className"); 
    
    // Selector usando pseudo-selector CSS :nth-child 
    $(" div:nth-child( 2)"); 
    
    // Selector de todos los elementos del documento html 
    $("*"); 
    
    // Selector de todos los elementos párrafo
    $("p"); 
    
    // Selector para párrafos spans y divs 
    $("p, span, div"); 
    
    // selector de párrafo con id 
    $(" p# short");
    
    // selector de div con clase
    $(" div.option"); 
    
    // Selector con elemento y pseudo-selector :first o :last
    $(" p:first"); 
    $(" p:last"); 
    
    
    // Selector con elemento y pseudo-selector nth-child (nos permite seleccionar cualquier posición de una lista de elementos )
    $(" p:nth-child( 1)"); // primero
    $(" p:nth-child( 2)"); // segundo
    $(" p:nth-child( 3)"); // tercero
    
    // Selector con elemento y pseudo-selector nth-child con palabras clave even o odd
    // even para seleccionar todos los pares 
    // odd para seleccionar los impares
    $(" p:nth-child( even)"); 
    $(" p:nth-child( odd)"); 
    
    // Selector con los paréntesis cuadrados para seleccionar cualquier elemento con un atributo llamado "xxx"
    $("[xxx]"); 
    
    // Selector para seleccionar todos los párrafos hijos pero solo después de cualquier elemento con clase "s"
    $(".s ~p"); 
    
    // Selector para los inputs de type definido ejemplo tipo "text"  
    $(" input[ type = text]");
    
    // Selector para todos los checkbox seleccionados usando el selector de atrubuto [] o el psudo-selector :checked, selector que tambein sirve para los radio buttons 
    $(" input:checked"); 
    
    // Selector poara seleccionar solo checkboxes 
    $(" input[ type = checkbox]: checked"); 
    
    // Selector para todos los elementos inputs contenidos en el elemento form
    $("form input"); 
    
    // Selector para todos los elementos a dentro de la tabla 
    $("table tr td a"); 
    

    Aqui terminan los tips de selectores.

  • Configurar camara web lifecam vx-500 en octopi

    Configurar camara web lifecam vx-500 en octopi

    Primero les hablo del gran proyecto que es OctoPrint y su adaptacion a raspberry pi llamado OctoPi

    OctoPrint es un software de control de Impresoras 3D que se ejecuta desde un navegador y permite controlar tu impresora 3D de forma remota a través de la red; este grandioso software es open source y recientemente ha sido apadrinado por la empresa española Bq.

    OctoPi mas que una adaptación, es un script que genera una imagen de raspbian modificado, esta es una imagen del sistema operativo linux para raspberry, este script deja listo el sistema para conectarlo a la impresora 3D y usarlo como Host para poder hacer las impresiones y el manejo de la impresora.

    Estos dos grandes proyectos los conocí por que hace un tiempo empece con la creación de mi impresora 3D y me vi en la necesidad de tener un host, el cual inicialmente era mi portatil, pero luego encontre en la red que se podia usar un raspberry pi, el cual ya tenia y empece a configurar, realmente por medio del proyecto OctoPi fue muy facil, pero fue muy complicado lograr hacer funcionar la camara web que tengo, esto para podr observar como va la impresion sin estar al lado de la impresora.

    Realmente creo que el problema que tube con la camara web es por lo vieja que es, por lo cual me toco investigar mucho en internet pero al final lo logre; aqui les cuento los comandos y procedimiento que realice para poder hacer funcionar mi camara lifecam vx-500 (Microsoft).

    Octopi crea un script para arrancar la camara web, este script esta ubicado en la direccion /home/pi/scripts/webcamDaemon, el archivo arranca con el sistema operativo, pero en mi caso la camara arrancaba pero no daba ninguna imagen, por lo cual procedi a comentariar los comandos internos del archivo, para poder ejecutarlos manualmente y asi saber cual era el problema.

    Sucede que por Octopi para hacer uso de la camara web usa otro proyecto open source llamado mjpg_streamer el cual usa por defecto el formato de procesamiento de imagen JPEG, el cual no es soportado por mi camara, asi que para saber cual era el formato use los siguientes comandos.

    Primero instale los siguiente

    sudo apt-get install subversion libv4l-dev libjpeg8-dev imagemagick fswebcam
    

    Esto instala una aplicación la cual nos va a dar información sobre la cámara web, luego de haber instalado, ejecutamos el siguiente comando:

    fswebcam --verbose
    

    Este comando nos dará la siguiente información

    --- Opening /dev/video0...
    Trying source module v4l2...
    /dev/video0 opened.
    src_v4l2_get_capability,87: /dev/video0 information:
    src_v4l2_get_capability,88: cap.driver: &amp;quot;uvcvideo&amp;quot;
    src_v4l2_get_capability,89: cap.card: &amp;quot;Microsoft LifeCam&amp;quot;
    src_v4l2_get_capability,90: cap.bus_info: &amp;quot;usb-bcm2708_usb-1.2&amp;quot;
    src_v4l2_get_capability,91: cap.capabilities=0x84000001
    src_v4l2_get_capability,92: - VIDEO_CAPTURE
    src_v4l2_get_capability,103: - STREAMING
    No input was specified, using the first.
    src_v4l2_set_input,181: /dev/video0: Input 0 information:
    src_v4l2_set_input,182: name = &amp;quot;Camera 1&amp;quot;
    src_v4l2_set_input,183: type = 00000002
    src_v4l2_set_input,185: - CAMERA
    src_v4l2_set_input,186: audioset = 00000000
    src_v4l2_set_input,187: tuner = 00000000
    src_v4l2_set_input,188: status = 00000000
    src_v4l2_set_pix_format,520: Device offers the following V4L2 pixel formats:
    src_v4l2_set_pix_format,533: 0: [0x56595559] 'YUYV' (YUV 4:2:2 (YUYV))
    Using palette YUYV
    Adjusting resolution from 384x288 to 352x288.
    src_v4l2_set_mmap,672: mmap information:
    src_v4l2_set_mmap,673: frames=4
    src_v4l2_set_mmap,722: 0 length=202752
    src_v4l2_set_mmap,722: 1 length=202752
    src_v4l2_set_mmap,722: 2 length=202752
    src_v4l2_set_mmap,722: 3 length=202752
    --- Capturing frame...
    Captured frame in 0.00 seconds.
    --- Processing captured image...
    There are unsaved changes to the image.
    

    En la linea 21 nos damos cuenta que nos indica que el formato de imagen que da la camara es YUYV (Using palette YUYV) por lo cual nos toca indicarle a mjpg_streamer que use este formato.

    Para poder indicarle al demonio de Octopi que use este formato tenemos que modificar el archivo sh /home/pi/scripts/webcamDaemon dejandolo asi

    #!/bin/bash
    
    MJPGSTREAMER_HOME=/home/pi/mjpg-streamer
    MJPGSTREAMER_INPUT_USB=&amp;quot;input_uvc.so -y&amp;quot;
    MJPGSTREAMER_INPUT_RASPICAM=&amp;quot;input_raspicam.so&amp;quot;
    
    # init configuration
    camera=&amp;quot;usb&amp;quot;
    camera_usb_options=&amp;quot;-r 640x480 -f 10&amp;quot;
    camera_raspi_options=&amp;quot;-fps 10&amp;quot;
    
    if [ -e &amp;quot;/boot/octopi.txt&amp;quot; ]; then
        source &amp;quot;/boot/octopi.txt&amp;quot;
    fi
    
    # runs MJPG Streamer, using the provided input plugin + configuration
    function runMjpgStreamer {
        input=$1
        pushd $MJPGSTREAMER_HOME
        echo Running ./mjpg_streamer -o &amp;quot;output_http.so -w ./www&amp;quot; -i &amp;quot;$input&amp;quot;
        LD_LIBRARY_PATH=. ./mjpg_streamer -o &amp;quot;output_http.so -w ./www&amp;quot; -i &amp;quot;$input&amp;quot;
        popd
    }
    
    # starts up the RasPiCam
    function startRaspi {
        logger &amp;quot;Starting Raspberry Pi camera&amp;quot;
        runMjpgStreamer &amp;quot;$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options&amp;quot;
    }
    
    # starts up the USB webcam
    function startUsb {
        logger &amp;quot;Starting USB webcam&amp;quot;
        runMjpgStreamer &amp;quot;$MJPGSTREAMER_INPUT_USB $camera_usb_options&amp;quot;
    }
    
    # we need this to prevent the later calls to vcgencmd from blocking
    # I have no idea why, but that's how it is...
    vcgencmd version
    
    # echo configuration
    echo camera: $camera
    echo usb options: $camera_usb_options
    echo raspi options: $camera_raspi_options
    
    # keep mjpg streamer running if some camera is attached
    while true; do
        if [ -e &amp;quot;/dev/video0&amp;quot; ] &amp;amp;&amp;amp; { [ &amp;quot;$camera&amp;quot; = &amp;quot;auto&amp;quot; ] || [ &amp;quot;$camera&amp;quot; = &amp;quot;usb&amp;quot; ] ; }; then
            startUsb
        elif [ &amp;quot;`vcgencmd get_camera`&amp;quot; = &amp;quot;supported=1 detected=1&amp;quot; ] &amp;amp;&amp;amp; { [ &amp;quot;$camera&amp;quot; = &amp;quot;auto&amp;quot; ] || [ &amp;quot;$camera&amp;quot; = &amp;quot;raspi&amp;quot; ] ; }; then
            startRaspi
        else
            echo &amp;quot;No camera detected, trying again in two minutes&amp;quot;
        fi
    
        sleep 120
    done
    

    El cambio que se realiza es en la linea numero 4 en donde se le pone un -y antes de las comillas finales.

    Con esto solo falta reiniciar y el raspberry pi y el octoprint ya estaran transmitiendo imagen en vivo.

    Espero que este articulo sea de ayuda.

  • Como instalar node js, npm y express en linux ubuntu/mint

    Como instalar node js, npm y express en linux ubuntu/mint

    Para instalar node js lanzaremos los siguientes comandos

    Este comando es para agregar un repositorio PPA

    sudo add-apt-repository ppa:chris-lea/node.js
    

    Los siguientes comandos actualizan el listado de los paquetes disponibles e instala el paquete de nodejs el cual tambien incluye a npm

    sudo apt-get update
    sudo apt-get install nodejs
    

    Ya con estos comandos instalados podemos comprobar las versiones de nodejs y npm

    $ node --version
    v0.10.29
    
    npm --version
    1.4.14
    

    por ultimo para instalar el express en linux ubuntu/mint

    sudo npm install -g express
    sudo npm install -g express-generator
    
  • URLs amigables para Yii Frameworks

    URLs amigables para Yii Frameworks

    para poder hacer esto el procedimiento es muy sencillo, pero como suele ocurrir en interner en ocaciones la informacion esta dispersa, por loo cual les traigo es tip de como configurar esto en unos simples pasos

    paso 1
    tener habilitado la extencion de mod_rewrite en apache

    paso 2
    crear el archivo .htaccess en la raiz del sitio con la siguiente información

    RewriteEngine on
    
    # if a directory or a file exists, use it directly
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    # otherwise forward it to index.php
    RewriteRule . index.php
    

    paso 3
    buscar en el archivo de configuracion del nuevo sitio (comunmente esta en protected/config/main.php) la linea donde este «urlManager» y descomentariar el bloque, el bloque debe quedar asi:

    		'urlManager'=>array(
    			'urlFormat'=>'path',
    			'showScriptName'=>false,
    			'rules'=>array(
    				'<controller:\w+>/<id:\d+>'=>'<controller>/view',
    				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
    				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
    			),
    		),
    
  • Cambiar Zona Horaria Linux

    Cambiar Zona Horaria Linux

    Hoy vengo con este corto y sencillo tip para poder cambiar la zona horaria del sistema operativo linux, la verdad es que siempre que necesito esta información termino buscando por muchos lugares, por lo cual para no tener que volver a hacer muchas búsquedas lo pongo aquí y lo comparto con ustedes para que cuando lo necesiten lo encuentren fácilmente.
    (más…)

  • Apuntes de GIT parte 1

    Apuntes de GIT parte 1

    apuntesgit

    En la empresa donde actualmente trabajo me toco manejar el versionado del código, es divertido, pero todo entra en una época de desastre cuando uno se da cuenta que toca hacerlo todo en consola, y peor cuando uno esta acostumbrado a trabajar en ambiente gráfico; continuando con mi tarea diaria me encontré que la documentación sobre git es muy amplia, pero en algunos casos es muy dispersa, en otros muy poco puntual, en otros muy básica (en extremo), así que decidí hacer mis apuntes los comandos que consideraba que en algún momento iba a necesitar. (más…)

  • Lección 3: Introducción a PHP

    Lección 3: Introducción a PHP

    En el mundo del desarrollo existen muchos lenguajes de programación los cuales son muy reconocidos como por ejemplo .NET, python, Ruby y otros tantos, pero en este caso vamos a habar de PHP uno de los lenguajes de mayor popularidad en la web y el lenguaje que es el centro de atención de este curso, hoy por fin, después de haber dado las expliaciones necesarias para poder montar el ambiente de desarrollo necesario para poder realizar nuestras practicas, comenzamos con los primeros pasos.

    Capítulo 1: Las etiquetas PHP

    PHP asi como otros lenguajes de script pueden ser incrustados dentro de una página e incluso ejecutarse en un archivo independiente, pero para que el servidor sepa que esa información se ha de interpretar, se ha de marcar o enmarcar entre unas marcas especificas las cuales nos indican que el texto contenido es php.
    (más…)

  • Lección 2: Crear un sitio web

    Lección 2: Crear un sitio web

    Capítulo 1: ¿Cómo funcionan las páginas PHP?

    PHP para que funcione necesita de su interprete o motor de scripting, el cual ejecuta el código escrito en este lenguaje antes de ser entregada una respuesta al servidor web para que este le muestre el resultado al cliente; la forma en la cual es interpretado es de la forma que todo lenguaje scripting, la ejecución se hace de forma secuencial.

    Capítulo 2: Crear un alias en Apache

    como ya lo habíamos dicho en la lección anterior, todos los ejemplos los vamos a hacer con el servidor WAMP. por lo cual vamos a usar el menu del servidor para crear el alias, pero primero que todo veamos que es un alias para el servidor del apache, Un alias sirve para poder tener una página web en una ubicación diferente del DocumentRoot, es decir, la ruta establecida por defecto para almacenar las páginas.
    (más…)

  • Curso De Php Lección 1: Instalación

    Curso De Php Lección 1: Instalación

    Capítulo 1: Introducción

    Como es de suponer al ingresar al mundo de un lenguaje de programación es importante conocer por lo menos el ambiente basico necesario para poder realizar los desarrollos que dia a dia iran siendo mas complejos dependiendo de la emotividad que tenga la persona que quiere profundizar en el mundo del desarrollo.

    Así como para poder compilar un programa en C o C++ necesita como minimo un compilador del lenguaje, y que para trabajar con .net es necesario el frameworks, asi mismo para poder ejecutar el programa o script de PHP es necesario tener unas aplicaciones basicas para poder probar lo que vamos haciendo en el curso.
    (más…)

  • Curso De Php

    Curso De Php

    la presente entrada es para dar a conocer el temario de un proyecto de curso de PHP que realizare con el fin de enseñarle a dos personas a programar en este lenguaje, el acceso sera totalmente libre para cualquier persona.

    A continuacion el temario, el cual he ido creando con lo temas de interes que creo que son importantes, y teniendo en cuenta algunos temarios encontrados en cursos que rondan por internet, el temario puede ser afectado agregando mas capítulos o lecciones con el fin de completar temas que no fueron tenidos en cuenta inicialmente.

    (más…)

  • Festivos de Colombia en PHP

    Festivos de Colombia en PHP

    Codigo Fuente

    Con la siguiente clase se genera un array con los calculos necesarios para calcular los festivos de colombia de acuerdo a la normativa actual del país.

    Los festivos se dividen en 4 tipos de festivos

    • Festivos fijos (son aquellos que no se mueven de la fecha sin importar que día de la semana son)
    • Festivos Emiliani (estos son los festivos que son corridos al lunes siguiente a ocurrir el verdadero día feriado, esto debido a la legislación colombiana)
    • Festivos calculados por el dia de pascuas
    • Festivos calculados por el dia de pascuas y corridos al lunes siguiente por la ley Emiliani

    La clase creada tiene un constructor al cual se le pasa el numero del año del cual se quiere saber las fechas festivas, las cuales se almacenan en un array de tres dimensiones donde la primer dimencion es el año, la segunda dimencion es el mes y la tercera dimencion es el dia.

    para calcular el dia de pascua se utiliza una funcion nativa de PHP llamada easter_date al cual se le pasa por argumento el año al cual dicha fecha.

     

    Adicional a esto tambien la clase tiene una funcion a la cual se le pasa por parametro un dia y un mes del año calculado, y esta nos dira si ese dia es festivo.

    Esta clase esta siendo usada en un proyecto que actualmente desarrolla iguazoft para un cliente muy especial.

    Espero la clase les sea de utilidad.

    Descarge aqui la clase