error

SQL Server Management Studio se cierra al iniciar – Solución a SSMS

SQL Server Management Studio es una herramienta que sirve para conectarse y administrar un servidor de SQL o concretamente administrar SQL Server.

En ocasiones, al iniciar la herramienta de SQL Server Management la misma se cierra justo al iniciar, sin mostrar errores ni advertencias en ningún lugar.

Voy a explicar en este post cómo solucionar el error de cierre al inicio de SQL Server Management Studio.

Lo único que haremos será eliminar un archivo y unas claves de registro.

Continue reading…

Modificar gemfile para instalar gema de SQLite3 de otra manera

Solución a Cannot load such file — sqlite3/sqlite3_native (LoadError) en Ruby on Rails

Si al intentar ejecutar una aplicación de Ruby on rails en Windows aparece el siguiente error:

Cannot load such file — sqlite3/sqlite3_native (LoadError)

Hoy traigo una solución que funciona. No sé por qué aparece este error la mayoría de veces sobre Windows, ¿así quieren fomentar el uso de rails? por eso tanta gente prefiere otras cosas, en fin, veremos cómo arreglar este problema.

Continue reading…

Notificaciones en AngularJS con AngularUiNotification

Notificaciones en AngularJS con angular-ui-notification

AngularJS, si bien es un framework que ya no es recomendado hoy en día para realizar proyectos (si eres fan de AngularJS entonces puedes ver a angular.io), tiene un gran uso. Infiero que muchísimos sistemas están escritos con el framework superheroico de Google.

Notificaciones en AngularJS con AngularUiNotification

Notificaciones en AngularJS con AngularUiNotification

En este post se verá cómo mostrar notificaciones usando el framework de JavaScript llamado AngularJS y una librería llamada angular-ui-notification.

Continue reading…

Cannot change save handler when session is active

Introducción

Trabajando en un pequeño proyecto de PHP me topé con la siguiente advertencia: Warning: session_set_save_handler(): Cannot change save handler when session is active. Este mensaje me tuvo dando vueltas por todo internet sin encontrar una solución, pero probando algunas cosas di con ella y vengo a exponerla.

PHP permite implementar nuestro propio manejador de sesiones. En este blog ya hemos hecho alguno anteriormente, justo aquí: implementar session handler en PHP.

Pues  bien, vamos a la solución y explicación.

Explicación de Cannot change save handler when session is active

El mensaje lo dice todo. No se puede cambiar el manejador de sesiones mientras la sesión está activa. Esto tiene bastante sentido.

Es decir, no podemos hacer esto:

<?php
session_start();
session_set_save_handler(/*El handler aquí*/);
$_SESSION["foo"] = "bar";
echo $_SESSION["foo"];
?>

Ya que como vemos, estamos llamando a session_start y después estamos llamando a session_set_save_handler. Por lo que primero debemos llamar a session_set_save_handler y luego utilizar la sesión.

Pero el problema no es así de simple, ya que, ¿Qué pasa cuando leemos dos veces la sesión? por ejemplo, puede que tengamos dos métodos que leen la sesión, y que se ejecuten uno después del otro. La llamada de las sesiones sería así:

<?php

/*
Esto genera un error de que la sesión ya ha sido iniciada pero este no es el
problema ahora, eso se soluciona con session_status y bla bla
*/

#--Esto lo hace el primer método
session_set_save_handler(/*El handler*/);
session_start();
$_SESSION["foo"] = "bar";
#Hasta aquí todo bien

#--Esto lo hace el segundo método

/*
Justo aquí abajo está el error...
la sesión está siendo leída o escrita, porque la iniciamos allá arriba
pero estamos intentando registrar un handler, y por eso
se genera la advertencia, pues no se puede registrar un handler mientras
leemos o escribimos
*/
session_set_save_handler(/*El handler*/);
session_start();
$_SESSION["foo"] = "bar";
#Hasta aquí todo bien

?>

El huevo o la gallina

Y aquí entramos en un dilema. La solución más fácil sería ver si no hay datos de sesión, y si  no los hay, entoncesregistramos el handler. Algo así:

<?php
if(!isset($_SESSION["bla"])) session_set_save_handler(/*Handler*/);
?>

¿Pero cómo leemos datos de sesión de nuestro handler, si no lo hemos registrado? y recordemos que si lo registramos, generará un error. Pero si no lo registramos, no podremos comprobar si ya ha sido registrado.

Analogía del huevo y la gallina con Warning: session_set_save_handler(): Cannot change save handler when session is active

Analogía del huevo y la gallina con Warning: session_set_save_handler(): Cannot change save handler when session is active

Se parece al problema del huevo y la gallina. Ya que si no registramos el handler, estaremos leyendo datos de sesión del manejador propio de PHP, no del nuestro. Pero no podemos registrar el handler porque genera un error. Error que evitamos leyendo datos de la sesión con el handler registrado.

Solución a Cannot change save handler when session is active

La solución es sencilla. Ya que no podemos registrar nuestro handler porque eso genera un error, pero para omitir el error debemos leer datos de la sesión de nuestro handler, podemos mejor comprobar si está definido el arreglo superglobal $_SESSION.

Dicho arreglo superglobal estará indefinido si no hay datos de sesion (independientemente del handler), así que podemos comprobarlo para ver si deberíamos o no registrar el manejador. Así:

<?php
if (!isset($_SESSION)){
  session_set_save_handler(/*El handler aquí*/);
}

De esta manera, no importa cuántas veces se llame a la sesión, pues el handler será registrado sólo una vez.

Cuidado con la columna rowid autoincrementable de SQLite

Cuidado con la columna rowid autoincrementable de SQLite

Introducción

Internamente, SQLite (la base de datos que no necesita servidor) agrega una columna llamada rowid. Esto es una columna autoincrementable y por lo tanto no se repite.

Probablemente seamos perezosos y confiemos en ella, creyendo que todo irá bien.

Recientemente estuve trabajando en un proyecto con SQLite y descubrí algo muy importante que debemos saber al trabajar con el rowid implícito.

Explicación del error

Si no utilizas relaciones en tus tablas, puedes dejar de leer. Lo que hace esta característica es que no recuerda cuáles ids ya fueron utilizados.

Es decir, si tenemos 3 filas (con el id 1, 2 y 3 respectivamente) y eliminamos la tercer fila, sólo quedarán 2 (pero el id 3 ya había estado en uso).

Más tarde insertamos un nuevo registro, esperando que el id sea 4 (pues el 3, aunque no existe, ya fue utilizado), pero no es así, el id será 3.

Esto trae muchos problemas, pues si confiamos en que nunca se repetirá aunque se elimine, traerá resultados inesperados.

Un ejemplo que se me ocurre es tener 3 clientes. Luego hacer ventas que tengan una relación con clientes y que guarden el id de cliente.

Si eliminamos el tercer cliente, y luego creamos uno nuevo, parecerá que este nuevo cliente será el que ha hecho las ventas.

Rowid autoincrementable

Como lo dije hace un momento, si tenemos una tabla así:

CREATE TABLE mascotas(
  nombre TEXT NOT NULL
);

Automáticamente se agregará el rowid aunque no lo declaremos. Si no lo necesitamos, no hay problema.

Pero si necesitamos una columna autoincrementable hay que declararlo explícitamente como se ve abajo.

Solución

Hay que declarar implícitamente una columna de autoincremento, y también indicar que es una clave primaria.

Puede llamarse como deseemos pero en mi caso le pondré “rowid” para que mi app siga siendo compatible.

La tabla quedaría así:

CREATE TABLE mascotas(
  rowid INTEGER PRIMARY KEY AUTOINCREMENT,
  nombre TEXT NOT NULL
);

Con eso terminamos. Aquí dejo las referencias.

¿Bug en WordPress al poner título php: // input?

Introducción

Ya van 2 veces que me pasa esto, pero no entiendo la razón. Lo que pasa es muy raro: escribo php://input en el título, y al dar click en vista previa me sale el error 403. Bueno, de hecho me sale el 404 pero es porque no encontró el 403.

Descripción del problema

Lo he probado en 2 sitios (es decir, 2 instalaciones de WordPress) que tengo en el mismo servidor. No sé si sea mi servidor o WordPress, pero esto pasa:

Agregar entrada con título que contiene php://input

Agregar entrada con título que contiene php://input

Ahí pongo el título tal y como se ve. Al hacer click en Vista previa, esto se muestra:

Error al cargar vista previa

Error al cargar vista previa

Ni idea de lo que pueda ser, pero lo documento aquí por si alguien algún día sabe la razón de esto. Yo supongo que no debe haber una razón específica, ya que el título debería ser validado y “curado” pero al menos saldría una advertencia, y esto hace que no salga nada.

Por cierto, cuando lo pongo separado de las dos diagonales, no pasa nada. Es decir…

php://input => malo

php // input => bueno

Habilitar error log en CodeIgniter 3

Introducción

Para los desarrolladores que utilizamos AJAX o no queremos mostrar los errores en una app en producción, los logs son la herramienta principal para depurar y corregir errores.

Hoy mostraré cómo habilitar logs, o el archivo de errores en CodeIgniter.

Habilitar el log de errores

Lo único que tenemos que hacer es ir a application/config/config.php y cambiar el valor del arreglo $config en el índice log_threshold al valor 1.

Con esto estamos simplemente cambiado el umbral de errores.

El fragmento de código en cuestión es este:

Y ahí, un pequeño comentario nos da una pequeña introducción. Dice que si queremos deshabilitarlos, pongamos el valor en 0. Pero si deseamos habilitar los errores así como en cualquier aplicación, debemos ponerlo en 1.

En mi caso, al probar le puse un valor 4 y se loguearon muchas cosas:

Cuando en realidad sólo quería el error que aparece abajo. Así que mejor lo puse en nivel 1. Y el fragmento se ve como a continuación:

Ubicación de los archivos

Por cierto, los archivos de error aparecen en la carpeta application/logs y están nombrados de acuerdo al día. mes y año. Así, podemos analizarlos por fecha.

Aviso

Debemos asegurarnos de que en la carpeta application/logs se puedan crear archivos. Es decir, debe tener habilitada la escritura.

Conclusión

Así de fácil es habilitar el logueo de errores en CodeIgniter: un framework liviano de PHP que algunas personas y compañías todavía usan y usarán.

(429) Too Many Requests Laravel – Solución y explicación

Introducción

Cuando estamos consumiendo una api creada con Laravel, puede que nos aparezca el error que dice “(429) Too Many Requests“. Aquí explicaré por qué pasa y qué solución tenemos para ello.

Básicamente esto aparece porque estamos haciendo muchas peticiones en un corto periodo de tiempo; por ejemplo, hacer 100 peticiones en menos de un minuto.

Es una forma que tiene Laravel para protegernos. Ya que de esta forma bloqueamos el acceso a un usuario malicioso que haga miles de peticiones para que nuestro servidor caiga. Si pasa el límite, sólo se le responderá con el código http 429.

Continue reading…

Cuidado con las rutas de Laravel

Introducción

Las rutas de Laravel son una gran herramienta que nos permite construir una api rápidamente, y de forma fácil y eficaz. Simplemente tenemos que definir una ruta así:

Para después poder consumirla con una petición get a sitio.com/api/usuarios (por ejemplo). De esta manera nos evitamos parsear la ruta y muchas cosas que son laboriosas.

También podemos definir una ruta para que coincida con variables. Por ejemplo, la siguiente ruta muestra las ventas de algún año:

Podemos consumirla llamando a sitio.com/api/ventas/2017 y obtendríamos las ventas del año 2017 (en un caso teórico).

Conforme nuestras rutas crezcan, puede que olvidemos las rutas que hemos definido anteriormente y que incluso repitamos algunas de ellas.

Descripción del problema o error

Como se vio anteriormente, podemos obtener las ventas de un año con la siguiente ruta:

Y puede que después definamos una ruta para obtener las ventas canceladas, así:

Si ahora llamamos a sitio.com/api/ventas/2017 obtendremos las ventas del 2017, claro está. Y si quiero las ventas canceladas podría llamar a sitio.com/api/ventas/canceladas.

Pues aquí está el problema, ya que al llamar a sitio.com/api/ventas/canceladas Laravel pensará que estamos consultando las ventas por año, y que queremos las ventas en donde el año sea “canceladas” cosa que no tiene sentido. Lo que en realidad queremos son las ventas canceladas.

Esto podría traernos muchos errores, ya que no sabríamos por qué al llamar a sitio.com/api/ventas/canceladas no nos está devolviendo nada.

Solución

Podemos hacer dos cosas: renombrar nuestras rutas o delimitarlas con una expresión regular.

Renombrando rutas

Una solución que no me gusta mucho pero que funciona es renombrar nuestras rutas. Por ejemplo, podemos cambiar a que las ventas por año sean así:

Y ahora al llamar a ventas canceladas las rutas no se confundirán. Ya que para las ventas canceladas se llamará a sitio.com/api/ventas/canceladas y para las ventas por año se llamará a sitio.com/api/ventas/anio/2017 (agregamos anio antes de la variable).

De esta manera ya no chocarán. A mí se me hace una solución no tan práctica, pero funciona perfectamente y no tiene nada de malo.

Restringiendo rutas con expresión regular

Otra solución que me gusta más es hacer que la ruta coincida sólo si ésta coincide a su vez con una expresión regular. Es decir, podemos usar el método where de las rutas, para indicar que queremos que coincida sólo si es un número.

La ruta de las ventas por año quedaría así:

Simplemente estamos indicando que coincida sólo si la variable año es un número de 4 dígitos.

Así que al llamar a sitio.com/api/ventas/2017 obtendremos las ventas del 2017, ya que 2017 es un año de 4 dígitos.

Al llamar a sitio.com/api/ventas/canceladas la ruta no coincidirá, ya que “canceladas” no es un año, por lo que Laravel buscará otra ruta para ver si coincide antes de lanzar un error. Y como encontrará la ruta de las ventas canceladas, caerá ahí y obtendremos correctamente lo que queremos.

Usar las expresiones regulares también nos ayuda a mejorar un poco nuestra aplicación, y a delimitar datos para evitar errores.

Referencias

Aquí dejo algunos enlaces que pueden ser de ayuda para entender mejor esto

Documentación oficial de las rutas de Laravel

Expresión regular para un año de 4 dígitos

Probar expresiones regulares online

Aprende más sobre Laravel aquí.