PHPExcel: Error al abrir un archivo creado con la función php://output

Estoy utilizando la libreria PHPExcel para crear archivos Excel 2007 desde PHP al vuelo., pero al momento de descargar el archivo utilizando algo como lo siguiente:

header(‘Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet’);
header(‘Content-Disposition: attachment;filename=”pruebas.xlsx”‘);
header(‘Cache-Control: max-age=0′);

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, ‘Excel2007′);
$objWriter->save(‘php://output’);

Y al abrir el excel me aparece un error como el siguiente:

Excel no puede abrir el archivo ‘pruebas.xlsx’ porque el formato o la extensión de éste no son válidos. Compruebe que el archivo no se ha dañado y que la extensión del mismo coincide con el formato del archivo.

Pero el detalle esta en que si se genera para guardar el excel en disco duro, si se abre correctamente, entonceees!., el problema esta en la generación al vuelo que este enviando algo extraño.

La solución esta en el encoding de los archivos PHP, estos deben de estar en modo UTF-8 sin BOM (ANSI as UTF-8), para ver que tipo de codificación tenemos, instalamos el notepad++, despues en la parte inferior derecha aparecerá el encoding y pues verificar que diga ANSI as UTF-8, para convertir solo ingresar al menú Codificación.

Y listo!.., ya podemos crear nuestro archivo Excel., también no olviden verificar que no se mande nada de nada de texto (ni un espacio en blanco., nadaaa!)

SQL Server: No regresa el texto completo en las celdas con valores tipo texto, modificar php.ini

Siguiendo con el tema del truncado de caracteres en SQL desde nuestra aplicación de PHP del post anterior, resulta que la solución también se puede hacer con el comando SQL.

SET TEXTSIZE NUMERO_CARACTERES_A_OBTENER

Pero igual si queremos algo más permanente, solo es cosa de modificar nuestro archivo PHP.ini, las lineas donde tengamos:

; Valid range 0 – 2147483647. Default = 4096.
;mssql.textlimit = 4096

; Valid range 0 – 2147483647. Default = 4096.
;mssql.textsize = 4096

Por lo general están comentadas estas lineas, solo es cosa de descomentarlas y poner el valor que deseemos, reiniciamos apache y listo :)

PHP: Convertir fecha de Twitter del formato RFC 2822 a uno de MySQL

Pues he estado probando la API de twitter y el campo created_at tiene la fecha en formato RFC 2822, osea en español algo así: Sun, 14 Aug 2005 16:13:03 +0000, el problema esta al guardar la información en la base de datos MySQL, ya que solo acepta formato “YYYY-MM-DD HH:MM:SS” entonces, ocupamos modificar esta información.

la solución esta en utilizar 2 funciones de PHP: strtotime y date

strtotime lo que hace es convertir una descripción de fecha/hora textual en Inglés a una fecha Unix y con comando date le damos el formato que deseemos.

Teniendo algo así.

date(‘Y-m-d H:i:s’,strtotime($json->created_at))

Archivo CSV marca error de formato SYLK

He estado trabajando con la librería php-csv-utils para crear archivos CSV desde PHP de forma más facil., y despues de crear el script y querer abrir el archivo.CSV con Microsoft Office Excel me aparece el siguiente mensaje de error:

Se ha detectado que “archivo.CSV” es un archivo SYLK, pero no se puede cargar. Puede que el archivo contenga errores o que no tenga formato de archivo SYLK. Haga clic en Aceptar para intentar abrirlo con otro formato

Y pues no se abre el archivo.., investigando sobre la solución a este error me encuentro que cuanto en la linea 1, aparece el texto ID (asi con mayusculas), es cuando aparece el error., la solución es que excel no detecte que los 2 primeros caracteres digan ID, ya sea pasarlo todo a minusculas ( id ), o la primera mayuscula y la demas minuscula ( Id )

Aquí la explicación oficial de la ayuda de Microsoft para el error SYLK y si quieren saber más sobre el formato Symbolic Link (SYLK) pues en wikipedia.

JpGraph Error 25128 Error en la función imageantialias de la libreria PHP GD

Estaba probando la librería JpGraph en un flamante Ubuntu 11.04, pero el problema es que la versión de PHP es la más nueva 5.3.3 y muchas funciones ya fueron depreciadas o por el tipo de instalación no están disponibles, como es el caso de la función imageantialias y pues nos lanza el error 25128

Lo que se debe hacer de forma rápida sin andar compilando el PHP-GD desde las sources, es comentar la linea de gd_image.inc.php

JpGraphError::RaiseL(25128);//(‘The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.’)

Y listo! ya funciona otra vez la librería, sin antialias claro, pero funciona :)

mcrypt: Error al cargar el modulo php_mcrypt en windows

Estoy utilizando Ushahidi en un servidor apache-php5 en windows, con AppServ, el problema esta que me dice que requiere la libreria php_mcrypt para funcionar, y pues entro a php.ini, busco la linea donde dice: extension=php_mcrypt.dll y descomento la linea, reinicio el servicio con apache_servicefix.bat dentro de la carpeta c:/AppServ/Apache2.2/ pero el problema sigue.

Revisando el log de apache veo el siguiente error:

PHP Warning: PHP Startup: Unable to load dynamic library ‘C:/AppServ\\php5\\ext\\php_mcrypt.dll’ – No se puede encontrar el m\xf3dulo especificado.\r\n in Unknown on line 0

La solución esta en copiar el archivo libmcrypt.dll que esta dentro de c:/appserv/php5/libmcrypt.dll a c:/AppServ/Apache2.2/bin/ reiniciar el servicio y listo!.., ya tenemos correctamente instalada la libreria MCrypt de PHP

Apache: 403 Forbidden con Codeigniter

Siguiendo con el error 403 Forbidden en Apache con Codeigniter pues busqué y busqué la solución, ya que la que habia investigado antes pues era temporal, y despues de navegar por X número de páginas zaaas, vuelve a salir el error 403.

La solución sigue estando en la configuración de Apache2.0 y el módulo rewrite, primero modificamos el archivo en /etc/apache2/sites-enabled/000-default (u otro parecido)

< Directory />
Options FollowSymLinks SymLinksIfOwnerMatch
AllowOverride FileInfo
< /Directory>

Y despues en el .htaccess, o lo pueden poner en el otro archivo la siguiente info:

< IfModule mod_mime.c>
AddType text/html;charset=UTF-8 .html
< /IfModule>

< IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#’system’ can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]

#When your application folder isn’t in the system folder
#This snippet prevents user access to the application folder
#Submitted by: Fabdrol
#Rename ‘application’ to your applications folder name.
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]

#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn’t true it sends the
#request to index.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/kml|/robots\.txt|/favicon\.ico)

RewriteRule ^(.*)$ /index.php/$1 [L]
< /IfModule>

< IfModule !mod_rewrite.c>
# If we don’t have mod_rewrite installed, all 404′s
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin

ErrorDocument 404 /index.php
< /IfModule>

Donde dice UTF8 es para que todas las páginas HTML las mande con ese encoding, y la parte que creo es importante es donde se filtra el js, css, pero bueno!, ya con eso funciona bien el codeigniter y sin errores 403 forbidden.

application/javascript (NS_ERROR_DOM_BAD_URI)

Si estas utilizando llamadas Ajax desde tu página web a dominios externos y te aparece el error NS_ERROR_DOM_BAD_URI en la extensión HttpFox de Firefox la solución es solicitar la página mediante JSON, si usas JQuery seria en teoría algo así:

$.getJSON(“http://dominioExterno.com/pagina”,function(result){

});

Pero nooooo! el error sigue apareciendo, entonces la solución correcta sería agregar un parametro X con valor = ?., en este caso le llamamos jsoncallback=? en español quedaría algo así:

$.getJSON(“http://dominioExterno.com/pagina?jsoncallback=?”,function(result){

});

Ahora ocupas moverle al servidor algunos parametrillos para que te regrese correctamente el JSON, si usas PHP puedes poner este código:

function generate_jsonp($data) {
if (preg_match(‘/\W/’, $_GET['jsoncallback'])) {
// if $_GET['jsoncallback'] contains a non-word character,
// this could be an XSS attack.
header(‘HTTP/1.1 400 Bad Request’);
exit();
}
header(‘Content-type: application/json; charset=utf-8′);
print sprintf(‘%s(%s);’, $_GET['jsoncallback'], json_encode($data));
}

Con esto evitas ataques XSS y te regresa tu JSON en una función tal y como te la mande getJSON, solo es cosa de enviar un arreglo a la función generate_jsonp

Y listo!.., ya debe de jalar la solicitud externa.

Aca algo de documentación para usar JSONP de forma segura: http://www.metaltoad.com/blog/using-jsonp-safely

PHP: la función imagefilter no es reconocida en PHP5

Estaba probando la creación de mapas de calor (heat map) con PHP y en mi maquina local todo funciona correcto para al pasarla al servidor saaz, error de PHP.

Fatal error: Call to undefined function imagefilter()

revisando la documentación de la función imagefilter dice que viene en la librería GD y PHP5, los 2 programas ya los tenia instalados, pero aún así no reconocía la función, e investigando dice que se ocupa instalar la libreria PHP5-GD Bundled (embedida o empaquetada), ya que la versión original fue desarrollada por Boutell.

Ahora al grano! a instalar la nueva librería, para eso la vamos a compilar todo a mano, jejeje:

apt-get update
apt-get install build-essential debhelper fakeroot
cd /usr/src
apt-get source php5
apt-get build-dep php5
cd php5-5.2.4

Recuerden cambiar la versión del PHP descargada, despues a modificar el archivo debian/rules

nano ./debian/rules

Buscamos la línea que diga:

–with-gd=shared,/usr –enable-gd-native-ttf \

Y la cambiamos por esta:

–with-gd=shared –enable-gd-native-ttf \

Ahora viene la parte tardadaaaaaa!!! a compilar todo,

dpkg-buildpackage -rfakeroot
cd ..
apt-get remove php5-gd
dpkg -i php5-gd_5.2.4-2ubuntu5.14_i386.deb

Reiniciamos apache y listo! la librería php5-gd debe de quedar OK!..

/etc/init.d/apache2 restart

Aca una imagen de como quedo el mapa de calor:

Codeigniter: Modificar LIMIT para el driver MSSQL

Después de encontrar la solución para que funcione el LIMIT de MySQL en Microsoft SQL Server ahora sigue el turno de modificar el código de Codeigniter para así tener algo transparente para nuestras consultas SQL.

Lo primero que se debe de hacer es modificar la librería de carga del Codeigniter, ( $this->load-> )
Vamos a trabajar en la carpeta: /system/application/libraries/ y creamos un archivo llamado: MY_Loader.php con el siguiente código:

< ?php
class MY_Loader extends CI_Loader{
/
* Constructor, calls parent constructor.
*/
function MY_Loader()
{
parent::CI_Loader();
}

/
* Database Loader
*
* @access public
* @param string the DB credentials
* @param bool whether to return the DB object
* @param bool whether to enable active record (this allows us to override the config setting)
* @return object
*/
function database($params = '', $return = FALSE, $active_record = FALSE)
{
// Do we even need to load the database class?
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == FALSE)
{
return FALSE;
}

require_once(BASEPATH.'database/DB'.EXT);

// Load the DB class
$db =& DB($params, $active_record);

$my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.’_driver’;
$my_driver_file = APPPATH.’libraries/’.$my_driver.EXT;

if (file_exists($my_driver_file))
{
require_once($my_driver_file);
$db =& new $my_driver(get_object_vars($db));
}

if ($return === TRUE)
{
return $db;
}
// Grab the super object
$CI =& get_instance();

// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$CI->db = ”;
$CI->db = $db;
// Assign the DB object to any existing models
$this->_ci_assign_to_models();
}

}

La idea de este archivo es extender la funcionalidad de carga de los drivers para la base de datos, despues en la misma carpeta de libraries creamos un archivo llamado: MY_DB_mssql_driver.php ya que estamos usando el driver mssql para nuestra conexión SQL Server

< ?php

class MY_DB_mssql_driver extends CI_DB_mssql_driver {

function __construct($params){
parent::__construct($params);
log_message('debug', 'Extended DB driver class instantiated!');
}

function _limit($sql, $limit, $offset){
if($offset == 0){
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
}else{
$OrderBy = "ORDER BY ";
if (count($this->ar_orderby) > 0){
$OrderBy .= implode(‘, ‘, $this->ar_orderby);

if ($this->ar_order !== FALSE)
{
$OrderBy .= ($this->ar_order == ‘desc’) ? ‘ DESC’ : ‘ ASC’;
}
}else{
$OrderBy .= “(SELECT 1)”;
}

$sql = preg_replace(‘/(\\’. $OrderBy .’\n?)/i’,”, $sql);
$sql = preg_replace(‘/(^\SELECT (DISTINCT)?)/i’,’\\1 ROW_NUMBER() OVER (‘.$OrderBy.’) AS rownum, ‘, $sql);
return “SELECT * \nFROM (\n” . $sql . “) AS A \nWHERE A.rownum BETWEEN (” .($offset + 1) . “) AND (“.($offset + $limit).”)”;
}
}

Y listo! con esto nuestra consulta LIMIT será transparente y se usará como siempre: $this->db->limit(2,10);

Aca les dejo las fuentes de esta información: