Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas
Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas

lunes, 10 de junio de 2024

7 razones para no usar Laravel en tu proyecto de PHP

En más de 40 años de experiencia como programador y director de proyectos de programación, he aprendido que cada requerimiento tiene mejores oportunidades de ser exitoso, dependiendo de la tecnología implementada para su realización. Y es por ello que he usado casi todo tipo de lenguajes, plataformas de desarrollo (IDE) y frameworks de lenguaje para tratar de ahorrar tiempo. En esta gran vastedad de existos y fracasos, he conocido un Framework que es relativamente popular entre algunos tipos de desarrolladores (generalmente con pocos años de experiencia), que recomiendan Laravel para cualquier tipo de proyecto. Pero realmente, Laravel no es el principe azul que muchos tienen en su cuento de hadas.

Laravel es un marco PHP popular conocido por su sintaxis elegante, funciones fáciles de desarrollar y su ecosistema sólido. Si bien Laravel es ampliamente utilizado por desarrolladores y empresas de diversos tamaños, incluidas muchas grandes empresas, puede haber varias razones por las que algunas grandes empresas pueden optar por no utilizar Laravel, aquí menciono sólo las mías, las que más dolor han causado en mis proyectos:

  1. Sistemas heredados: las grandes empresas suelen tener sistemas y aplicaciones existentes creados con diferentes tecnologías. Migrar a un nuevo marco como Laravel puede requerir mucho tiempo, recursos y esfuerzo, lo que puede ser un impedimento.
  2. Pila de tecnología: algunas empresas pueden haber estandarizado una pila o marco de tecnología diferente que se alinea con su infraestructura, experiencia o requisitos técnicos específicos existentes.
  3. Soluciones empresariales: las grandes empresas pueden tener requisitos complejos como escalabilidad, seguridad, cumplimiento e integración con sistemas heredados. Algunas empresas pueden preferir soluciones o marcos empresariales que ofrezcan características específicas que satisfagan estas necesidades.
  4. Soporte y mantenimiento: las empresas pueden considerar factores como el soporte a largo plazo, el mantenimiento y el respaldo de la comunidad al seleccionar una pila de tecnología. Si bien Laravel tiene una comunidad grande y activa, algunas empresas pueden preferir marcos con opciones de soporte comercial. Por otro lado, Laravel depende mucho de librerías y recursos de terceros, lo que puede generar momentos de crisis críticas al momento de hacer alguna actualización.
  5. Rendimiento y escalabilidad: si bien Laravel es conocido por sus funciones y productividad fáciles de usar para los desarrolladores, algunas empresas pueden tener aplicaciones críticas para el rendimiento en las que priorizan marcos conocidos por sus características de rendimiento y escalabilidad.
  6. Personalización y control: las grandes empresas pueden tener requisitos únicos que requieren un alto grado de personalización y control sobre el marco. Algunas empresas pueden optar por marcos más flexibles o de bajo nivel para satisfacer estas necesidades.
  7. Preocupaciones por la dependencia de un proveedor: las empresas pueden desconfiar de la dependencia de un proveedor y preferir marcos de código abierto que brinden flexibilidad y libertad para cambiar de tecnología si es necesario.
  8. Falta de independencia entre desarrollo y diseño: tal vez uno de los mayores problemas que enfrenta Laravel, es que todos los diseñadores dependen fuertemente del acompañamiento de los desarrolladores para actualizar sus diseños. Cosa que en otros Frameworks es muy fácil de sobrellevar.


Es importante tener en cuenta que las opciones de tecnología pueden variar según factores como los requisitos del proyecto, la experiencia del equipo, el presupuesto, el cronograma y los casos de uso específicos. Si bien es posible que algunas grandes empresas no utilicen Laravel por los motivos mencionados anteriormente, muchas otras organizaciones, incluidas grandes empresas, han adoptado Laravel con éxito para sus proyectos. La popularidad de Laravel y su comunidad activa indican que sigue siendo una opción viable para una amplia gama de proyectos de desarrollo web.

sábado, 11 de mayo de 2024

Calcular edad con la fecha de nacimiento en PHP

 En este tutorial, aprenderemos cómo calcular la edad a partir de la fecha de nacimiento en PHP.

Daré dos ejemplos de Cómo calcular la edad.

Ejemplo 1


    $dob='1993-07-01';
    $year = (date('Y') - date('Y',strtotime($dob)));
    echo $year;

Ejemplo 2

 
    $dob = new DateTime('1993-07-01');
    $today   = new DateTime('today');
    $year = $dob->diff($today)->y;
    $month = $dob->diff($today)->m;
    $day = $dob->diff($today)->d;
    echo "Age is"." ".$year."years"." ",$month."months"." ".$day."days";

martes, 26 de enero de 2021

5 Errores comunes programando en PHP y cómo prevenirlos

 Ahora que los desarrolladores pueden rastrear los problemas exactos que causan cuellos de botella en el rendimiento en aplicaciones PHP, veamos cinco errores comunes que cometen los desarrolladores al crear aplicaciones PHP y cómo pueden resolverlos.

Error 1: Hacer demasiadas consultas a la base de datos

PHP se encuentra con el mismo tipo de restricciones que los desarrolladores tendrían con otros lenguajes, como demasiadas consultas de bases de datos. Los desarrolladores no son expertos en bases de datos. La mayoría no conocen todos los matices de la base de datos que utilizan. A menudo, no están usando su capa de acceso a la base de datos de manera óptima, por lo que terminan haciendo demasiadas consultas a la base de datos o generando consultas a la base de datos que no usan índices.

Las bases de datos también funcionan de manera diferente bajo diferentes tipos de carga. Una base de datos que se ejecuta en una computadora portátil con decenas de megabytes de memoria se comporta de manera diferente a una base de datos de producción con un gigabyte, ya que se utilizan diferentes estrategias para seleccionar qué datos mirar. Las consultas que funcionaron en la máquina local de un desarrollador o en el entorno de ensayo pueden funcionar de manera diferente en producción.

Las mitigaciones para un rendimiento deficiente de las consultas de la base de datos son agregar consultas en caché y ajustar. El almacenamiento en caché ayuda a reducir la cantidad de consultas enviadas a la base de datos cuando el resultado ya se conoce o se accede con frecuencia. Por ejemplo, el artículo "más reciente" de un sitio de noticias cambia con menos frecuencia de la que se lee. Al almacenar en caché los resultados, los desarrolladores pueden mejorar el rendimiento leyendo los resultados del caché en lugar de la base de datos. Ajustar las consultas de la base de datos generalmente implica agregar índices adicionales en los datos que se usan con frecuencia en condiciones o combinaciones. También puede implicar el almacenamiento de datos de formas que requieran menos combinaciones para acceder.

Error 2: Cargar demasiados archivos


Con otros lenguajes de programación, las aplicaciones se inician y luego mantienen el código y los datos asociados en la memoria. Con PHP, sin embargo, no existe un estado de aplicación persistente: los archivos se recargan con cada solicitud. Cuando los desarrolladores no tienen en cuenta esto, pueden encontrarse con el problema de cargar demasiados archivos, lo que consume los recursos del sistema y ralentiza el rendimiento.

Los desarrolladores pueden resolver este problema activando el almacenamiento en caché del código de operación (código de operación). Como muchos lenguajes, PHP procesa el código fuente en códigos de operación, que luego se ejecutan en el tiempo de ejecución de PHP. La conversión de código PHP a códigos de operación ocurre en cada solicitud, ya que PHP no tiene un estado compartido. Si bien analizar el código fuente y generar códigos de operación es relativamente barato, los costos se acumulan a medida que una aplicación maneja más tráfico. Al habilitar el almacenamiento en caché del código de operación, el paso de análisis del código fuente se puede omitir, lo que produce ganancias de rendimiento medibles.

Error 3: Configuración incorrecta del servidor web

A diferencia de otros lenguajes de programación en los que el servidor web es parte del lenguaje, PHP se ejecuta dentro de un servidor web. Apache HTTP Server y Nginx son los dos más utilizados. El servidor web es otra capa que los desarrolladores de PHP deben supervisar. Desde elegir un modelo de proceso en Apache hasta ajustar PHP-FPM (Fast Process Manager) cuando se usa Nginx, existen algunas opciones de ajuste para usar.

Por ejemplo, los desarrolladores deberán configurar la cantidad de procesos de trabajo que se crearán y la frecuencia con la que se reciclarán. Si no tienen suficientes trabajadores (procesos en ejecución) disponibles, sus usuarios tendrán que hacer cola y esperar a que un trabajador esté libre. Si tienen demasiados trabajadores, podrían quedarse sin memoria durante un momento de mucha actividad. Los desarrolladores pueden utilizar la cantidad de memoria que normalmente utiliza una aplicación y los recursos disponibles en sus servidores como guía para elegir la cantidad de trabajadores.

Error 4: Malas prácticas de seguridad

PHP permite a los desarrolladores combinar una variedad de paradigmas de programación y cambiar entre código HTML y PHP con fluidez. Sin rigor, esto puede resultar rápidamente en un código desordenado que es difícil de mantener. Esta flexibilidad es una de las razones por las que PHP es un lenguaje excelente para principiantes, pero puede convertirse fácilmente en una debilidad que puede exponer las aplicaciones a problemas de seguridad como cross-site scripting (XSS) e inyección SQL (SQLi).

Los desarrolladores pueden mitigar estos riesgos mediante el uso de bibliotecas, herramientas y frameworks maduros. El uso de una biblioteca de plantillas como Twig ayuda a evitar el scripting entre sitios al codificar automáticamente en HTML todas las variables que se muestran en las plantillas. El uso de un mapeador relacional de objetos (ORM) o una biblioteca de abstracción de bases de datos puede evitar la inyección de SQL mediante el uso de declaraciones preparadas.

Error 5: No usar tipos estrictos y sugerencias de tipo

PHP tiene un sistema de tipos indulgente. Históricamente, PHP ha favorecido los tipos de coerción sobre la creación de errores. Esto puede llevar a trampas como dividir números por palabras y obtener resultados "útiles", pero también crear errores en tiempo de ejecución. Para ayudar a prevenir este tipo de errores, los desarrolladores deben habilitar "strict_types" y usar herramientas como Psalm y PHPStan como parte de su proceso de desarrollo. Estas herramientas analizan el código de forma estática y, al observar qué tipos de datos se utilizan en su aplicación, pueden señalar problemas potenciales antes de que se conviertan en problemas reales que afecten a los usuarios.

domingo, 27 de diciembre de 2020

for loop PHP continue to next item

 

<?php
$stack = array('first', 'second', 'third', 'fourth', 'fifth');

foreach($stack as $v){
    if($v == 'second') {
      continue;
    }
    echo $v.'<br>';
}
/*
first
third
fourth
fifth
 */
?> 

jueves, 26 de octubre de 2017

Anti-DDoS PHP Script (Prevenir ataques DDoS en PHP)

Las soluciones contra un ataque DDoS son más bien del lado de la configuración del servidor y el firewall que tenemos allí instalado.

No obstante, es posible a nivel de código tener un pequeño control, que si no evita el ataque completamente, al menos lo puede mitigar en una gran medida. Manos a la obra...

miércoles, 20 de septiembre de 2017

Cómo redimensionar imagenes en PHP

Hay varias alternativas ya disponibles en el medio.  Antes de poner en funcionamiento el que yo propongo, pueden probar algunos de los que ya existen en el medio.

Código de la función para hacer la redimensión:

  public function redimensionar_imagen($nombreimg, $rutaimg, $xmax, $ymax){  
        $ext = explode(".", $nombreimg);  
        $ext = $ext[count($ext)-1]; 

    if($ext == "jpg" || $ext == "jpeg")  
        $imagen = imagecreatefromjpeg($rutaimg);  
    elseif($ext == "png")  
        $imagen = imagecreatefrompng($rutaimg);  
    elseif($ext == "gif")  
        $imagen = imagecreatefromgif($rutaimg);  

    $x = imagesx($imagen);  
    $y = imagesy($imagen);  

    if($x <= $xmax && $y <= $ymax){
        //return "<center>Esta imagen ya esta optimizada para los maximos que deseas.<center>";
        return $imagen;  
    }

    if($x >= $y) {  
        $nuevax = $xmax;  
        $nuevay = $nuevax * $y / $x;  
    }  
    else {  
        $nuevay = $ymax;  
        $nuevax = $x / $y * $nuevay;  
    }  

    $img2 = imagecreatetruecolor($nuevax, $nuevay);  
    imagecopyresized($img2, $imagen, 0, 0, 0, 0, floor($nuevax), floor($nuevay), $x, $y);  
    //return "<center>La imagen se ha optimizado correctamente.</center>";
    return $img2;   
}

Y para llamar la función:

$nombre='imagen1';
$Path='img/section/immagen.jpg';
$alto=450;
$ancho=450;
$imagen_optimizada = $f->redimensionar_imagen($nombre, $Path, $alto, $ancho);

Sólo es llamar la función y pasarle los parámetros de Nombre, ruta física del archivo en el servidor, alto y ancho deseados al final.

jueves, 7 de abril de 2016

[Corregido] Call to a member function getPicklistValues() on a non-object in /crm/modules/Users/models/Record.php on line 494

Acabo de encontrarme con este mensaje de error luego de una migración de VTiger de 5.4 a 6.1.

En el foro de VTiger no han dado con una solución satisfactoria, y por algún motivo no tengo privilegios para postear la solución en dicho foro.

Bueno, aquí con la solución.

El problema lo podemos resolver directamente en el archivo ubicado en la ruta:
modules/Users/models/Record.php

Inicialmente, aparece esta código al rededor de la línea 494:

//-----------------------------------------------------------------------------
$hour_format = $fieldModel['hour_format']->getPicklistValues();
$start_hour = $fieldModel['start_hour']->getPicklistValues();

        $defaultValues = array('00:00'=>'12:00 AM','01:00'=>'01:00 AM','02:00'=>'02:00 AM','03:00'=>'03:00 AM','04:00'=>'04:00 AM','05:00'=>'05:00 AM',
                    '06:00'=>'06:00 AM','07:00'=>'07:00 AM','08:00'=>'08:00 AM','09:00'=>'09:00 AM','10:00'=>'10:00 AM','11:00'=>'11:00 AM','12:00'=>'12:00 PM',
                    '13:00'=>'01:00 PM','14:00'=>'02:00 PM','15:00'=>'03:00 PM','16:00'=>'04:00 PM','17:00'=>'05:00 PM','18:00'=>'06:00 PM','19:00'=>'07:00 PM',
                    '20:00'=>'08:00 PM','21:00'=>'09:00 PM','22:00'=>'10:00 PM','23:00'=>'11:00 PM');
//-----------------------------------------------------------------------------

Por algún motivo luego de la migración, no toma el listado por defecto de los Picklist para el listado de los horarios, pero si incluye los valores por defecto una línea más abajo.

Parece algo poco lógico, que hayan colocado los valores por defecto luego, yo simplemente le di el orden que me pareció más acertado.  Por lo tanto lo dejé de la siguiente manera:

//-----------------------------------------------------------------------------
        $defaultValues = array('00:00'=>'12:00 AM','01:00'=>'01:00 AM','02:00'=>'02:00 AM','03:00'=>'03:00 AM','04:00'=>'04:00 AM','05:00'=>'05:00 AM',
                    '06:00'=>'06:00 AM','07:00'=>'07:00 AM','08:00'=>'08:00 AM','09:00'=>'09:00 AM','10:00'=>'10:00 AM','11:00'=>'11:00 AM','12:00'=>'12:00 PM',
                    '13:00'=>'01:00 PM','14:00'=>'02:00 PM','15:00'=>'03:00 PM','16:00'=>'04:00 PM','17:00'=>'05:00 PM','18:00'=>'06:00 PM','19:00'=>'07:00 PM',
                    '20:00'=>'08:00 PM','21:00'=>'09:00 PM','22:00'=>'10:00 PM','23:00'=>'11:00 PM');

$hour_format = $defaultValues;
$start_hour = $defaultValues;
//-----------------------------------------------------------------------------

Y tema solucionado.

jueves, 25 de septiembre de 2014

Crear archivos descargables en CVS con PHP

CSV (valores separados por comas) es el formato más ampliamente soportado para la transferencia de datos tabulares entre aplicaciones. La capacidad de exportar datos en formato CSV es una característica útil para muchos programas, y se está convirtiendo cada vez más común en las aplicaciones web. Esta vez explicaré cómo usar PHP para crear archivos CSV, y cómo asegurarse de que el navegador del visitante ofrece para descargar el archivo en lugar de mostrarla.

1. El código


En el siguiente código se supone que los datos que se exportan provienen de una base de datos MySQL, pero puede ser fácilmente modificado para que funcione con otras fuentes de datos, y por lo tanto sirve como un modelo general:

// Encabezados que determinan la descarga del archivo y el nombre del archivo
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=datos_descargados.csv');

// Un punto para referir la descarga
$output = fopen('php://output', 'w');

// Los encabezados del archivo
fputcsv($output, array('Column 1', 'Column 2', 'Column 3'));

// Los datos
mysql_connect('localhost', 'username', 'password');
mysql_select_db('database');
$rows = mysql_query('SELECT field1,field2,field3 FROM table');

// loop en los registros, descargandolos
while ($row = mysql_fetch_assoc($rows)) fputcsv($output, $row);

La cadena 'datos_descargados.csv' en la línea 3 es el nombre que el navegador le sugerirá para el archivo descargado. El literal de matriz en la línea 9 contiene los títulos de las columnas; esta línea se debe omitir por completo si usted no desea incluir encabezados de columna. Las cadenas en líneas de 12 a 14 deben cambiar a los parámetros de conexión correspondientes y cadena de consulta de la base de datos. En una aplicación real de los parámetros de conexión de base de datos deben ser definidos como constantes en un archivo de configuración independiente.

2. ¿Cómo funciona?


El código tiene que decirle al navegador que se está produciendo un archivo CSV y que el archivo debe ser ofrecido para su descarga, en lugar de mostrarlo en el navegador. Línea 2 produce un encabezado HTTP decirle al navegador que el tipo MIME del contenido es text / csv, el tipo oficial MIME para los archivos CSV.

Línea 3 produce un encabezado 'Content-Disposition'. El encabezado Content-Disposition se define en el RFC 2183 y fue diseñado para ser utilizado en los correos electrónicos, pero también fue adoptado por los navegadores web. En navegadores web el valor 'apego' indica al navegador que ofrecerá el archivo para su descarga con el nombre sugerido - el archivo podría de otro modo se mostrará en la ventana del navegador como si fuera texto normal.

PHP 5.1 introdujo la función fputcsv, que da salida a una serie de datos a un puntero de archivo como valores separados por comas. Debido fputcsv sólo puede escribir en el archivo punteros, la línea 6 se abre la secuencia de salida como si fuera un archivo. Línea 9 entonces emite títulos de las columnas, mientras que la línea 17 bucles más de las filas de datos y les da salida.

jueves, 24 de abril de 2014

Error con date_default_timezone_set() en PHP

El Error:

date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin*' for 'CEST/2.0/DST' instead.

*...o cualquier otro sitio de este hermoso planeta.

Se nos ha presentado este error una vez montado el proyecto en el servidor, y puede ser por varias causas:
  • Nos han cambiado la versión de PHP.  Es decir, han actualizado la versión de PHP a una superior a 5.1.
  • No hemos incluido la linea de configuración de fecha en el servidor en nuestro código.  Esto es necesario si no se maneja en el php.ini
  • No hemos incluido la validación de la fecha y zona en nuestro php.ini
  • El servidor se enloqueció de la noche a la mañana.

Para darle solución a este detalle, primero que todo, supongamos que no se trata de la última causa.  Entonces demos solución en el código de nuestro archivo de PHP.


Muy al comienzo, antes de hacer uso de cualquier función date(). Debemos indicarle al servidor cuál es nuestra zona horaria con la siguiente instrucción:

Solución en el código:

<?php
date_default_timezone_set("America/Bogota"); //Configuramos el timezone
echo date_default_timezone_get(); // Vemos qué ha quedado configurado
//...de aqui en adelante el resto de nuestro código
?> 

Solución en el archivo php.ini:
[Date]
; Defines the default timezone used by the date functions
date.timezone = America/Chicago

No importa si el servidor se encuentra físicamente en otro país, la coniguración que aquí indicamos va a determinar los resultados de las funciones de fecha y tiempo en nuestra aplicación.

Aquí les dejo el listado de opciones que he podido encontrar buscando en la red:
  • Africa/Abidjan
  • Africa/Accra
  • Africa/Addis_Ababa
  • Africa/Algiers
  • Africa/Asmara
  • Africa/Asmera
  • Africa/Bamako
  • Africa/Bangui
  • Africa/Banjul
  • Africa/Bissau
  • Africa/Blantyre
  • Africa/Brazzaville
  • Africa/Bujumbura
  • Africa/Cairo
  • Africa/Casablanca
  • Africa/Ceuta
  • Africa/Conakry
  • Africa/Dakar
  • Africa/Dar_es_Salaam
  • Africa/Djibouti
  • Africa/Douala
  • Africa/El_Aaiun
  • Africa/Freetown
  • Africa/Gaborone
  • Africa/Harare
  • Africa/Johannesburg
  • Africa/Kampala
  • Africa/Khartoum
  • Africa/Kigali
  • Africa/Kinshasa
  • Africa/Lagos
  • Africa/Libreville
  • Africa/Lome
  • Africa/Luanda
  • Africa/Lubumbashi
  • Africa/Lusaka
  • Africa/Malabo
  • Africa/Maputo
  • Africa/Maseru
  • Africa/Mbabane
  • Africa/Mogadishu
  • Africa/Monrovia
  • Africa/Nairobi
  • Africa/Ndjamena
  • Africa/Niamey
  • Africa/Nouakchott
  • Africa/Ouagadougou
  • Africa/Porto-Novo
  • Africa/Sao_Tome
  • Africa/Timbuktu
  • Africa/Tripoli
  • Africa/Tunis
  • Africa/Windhoek
  • America/Adak
  • America/Anchorage
  • America/Anguilla
  • America/Antigua
  • America/Araguaina
  • America/Argentina/Buenos_Aires
  • America/Argentina/Catamarca
  • America/Argentina/ComodRivadavia
  • America/Argentina/Cordoba
  • America/Argentina/Jujuy
  • America/Argentina/La_Rioja
  • America/Argentina/Mendoza
  • America/Argentina/Rio_Gallegos
  • America/Argentina/San_Juan
  • America/Argentina/Tucuman
  • America/Argentina/Ushuaia
  • America/Aruba
  • America/Asuncion
  • America/Atikokan
  • America/Atka
  • America/Bahia
  • America/Barbados
  • America/Belem
  • America/Belize
  • America/Blanc-Sablon
  • America/Boa_Vista
  • America/Bogota
  • America/Boise
  • America/Buenos_Aires
  • America/Cambridge_Bay
  • America/Campo_Grande
  • America/Cancun
  • America/Caracas
  • America/Catamarca
  • America/Cayenne
  • America/Cayman
  • America/Chicago
  • America/Chihuahua
  • America/Coral_Harbour
  • America/Cordoba
  • America/Costa_Rica
  • America/Cuiaba
  • America/Curacao
  • America/Danmarkshavn
  • America/Dawson
  • America/Dawson_Creek
  • America/Denver
  • America/Detroit
  • America/Dominica
  • America/Edmonton
  • America/Eirunepe
  • America/El_Salvador
  • America/Ensenada
  • America/Fort_Wayne
  • America/Fortaleza
  • America/Glace_Bay
  • America/Godthab
  • America/Goose_Bay
  • America/Grand_Turk
  • America/Grenada
  • America/Guadeloupe
  • America/Guatemala
  • America/Guayaquil
  • America/Guyana
  • America/Halifax
  • America/Havana
  • America/Hermosillo
  • America/Indiana/Indianapolis
  • America/Indiana/Knox
  • America/Indiana/Marengo
  • America/Indiana/Petersburg
  • America/Indiana/Vevay
  • America/Indiana/Vincennes
  • America/Indiana/Winamac
  • America/Indianapolis
  • America/Inuvik
  • America/Iqaluit
  • America/Jamaica
  • America/Jujuy
  • America/Juneau
  • America/Kentucky/Louisville
  • America/Kentucky/Monticello
  • America/Knox_IN
  • America/La_Paz
  • America/Lima
  • America/Los_Angeles
  • America/Louisville
  • America/Maceio
  • America/Managua
  • America/Manaus
  • America/Martinique
  • America/Mazatlan
  • America/Mendoza
  • America/Menominee
  • America/Merida
  • America/Mexico_City
  • America/Miquelon
  • America/Moncton
  • America/Monterrey
  • America/Montevideo
  • America/Montreal
  • America/Montserrat
  • America/Nassau
  • America/New_York
  • America/Nipigon
  • America/Nome
  • America/Noronha
  • America/North_Dakota/Center
  • America/North_Dakota/New_Salem
  • America/Panama
  • America/Pangnirtung
  • America/Paramaribo
  • America/Phoenix
  • America/Port-au-Prince
  • America/Port_of_Spain
  • America/Porto_Acre
  • America/Porto_Velho
  • America/Puerto_Rico
  • America/Rainy_River
  • America/Rankin_Inlet
  • America/Recife
  • America/Regina
  • America/Resolute
  • America/Rio_Branco
  • America/Rosario
  • America/Santiago
  • America/Santo_Domingo
  • America/Sao_Paulo
  • America/Scoresbysund
  • America/Shiprock
  • America/St_Johns
  • America/St_Kitts
  • America/St_Lucia
  • America/St_Thomas
  • America/St_Vincent
  • America/Swift_Current
  • America/Tegucigalpa
  • America/Thule
  • America/Thunder_Bay
  • America/Tijuana
  • America/Toronto
  • America/Tortola
  • America/Vancouver
  • America/Virgin
  • America/Whitehorse
  • America/Winnipeg
  • America/Yakutat
  • America/Yellowknife
  • Antarctica/Casey
  • Antarctica/Davis
  • Antarctica/DumontDUrville
  • Antarctica/Mawson
  • Antarctica/McMurdo
  • Antarctica/Palmer
  • Antarctica/Rothera
  • Antarctica/South_Pole
  • Antarctica/Syowa
  • Antarctica/Vostok
  • Arctic/Longyearbyen
  • Asia/Aden
  • Asia/Almaty
  • Asia/Amman
  • Asia/Anadyr
  • Asia/Aqtau
  • Asia/Aqtobe
  • Asia/Ashgabat
  • Asia/Ashkhabad
  • Asia/Baghdad
  • Asia/Bahrain
  • Asia/Baku
  • Asia/Bangkok
  • Asia/Beirut
  • Asia/Bishkek
  • Asia/Brunei
  • Asia/Calcutta
  • Asia/Choibalsan
  • Asia/Chongqing
  • Asia/Chungking
  • Asia/Colombo
  • Asia/Dacca
  • Asia/Damascus
  • Asia/Dhaka
  • Asia/Dili
  • Asia/Dubai
  • Asia/Dushanbe
  • Asia/Gaza
  • Asia/Harbin
  • Asia/Hong_Kong
  • Asia/Hovd
  • Asia/Irkutsk
  • Asia/Istanbul
  • Asia/Jakarta
  • Asia/Jayapura
  • Asia/Jerusalem
  • Asia/Kabul
  • Asia/Kamchatka
  • Asia/Karachi
  • Asia/Kashgar
  • Asia/Katmandu
  • Asia/Krasnoyarsk
  • Asia/Kuala_Lumpur
  • Asia/Kuching
  • Asia/Kuwait
  • Asia/Macao
  • Asia/Macau
  • Asia/Magadan
  • Asia/Makassar
  • Asia/Manila
  • Asia/Muscat
  • Asia/Nicosia
  • Asia/Novosibirsk
  • Asia/Omsk
  • Asia/Oral
  • Asia/Phnom_Penh
  • Asia/Pontianak
  • Asia/Pyongyang
  • Asia/Qatar
  • Asia/Qyzylorda
  • Asia/Rangoon
  • Asia/Riyadh
  • Asia/Riyadh87
  • Asia/Riyadh88
  • Asia/Riyadh89
  • Asia/Saigon
  • Asia/Sakhalin
  • Asia/Samarkand
  • Asia/Seoul
  • Asia/Shanghai
  • Asia/Singapore
  • Asia/Taipei
  • Asia/Tashkent
  • Asia/Tbilisi
  • Asia/Tehran
  • Asia/Tel_Aviv
  • Asia/Thimbu
  • Asia/Thimphu
  • Asia/Tokyo
  • Asia/Ujung_Pandang
  • Asia/Ulaanbaatar
  • Asia/Ulan_Bator
  • Asia/Urumqi
  • Asia/Vientiane
  • Asia/Vladivostok
  • Asia/Yakutsk
  • Asia/Yekaterinburg
  • Asia/Yerevan
  • Atlantic/Azores
  • Atlantic/Bermuda
  • Atlantic/Canary
  • Atlantic/Cape_Verde
  • Atlantic/Faeroe
  • Atlantic/Faroe
  • Atlantic/Jan_Mayen
  • Atlantic/Madeira
  • Atlantic/Reykjavik
  • Atlantic/South_Georgia
  • Atlantic/St_Helena
  • Atlantic/Stanley
  • Australia/ACT
  • Australia/Adelaide
  • Australia/Brisbane
  • Australia/Broken_Hill
  • Australia/Canberra
  • Australia/Currie
  • Australia/Darwin
  • Australia/Eucla
  • Australia/Hobart
  • Australia/LHI
  • Australia/Lindeman
  • Australia/Lord_Howe
  • Australia/Melbourne
  • Australia/NSW
  • Australia/North
  • Australia/Perth
  • Australia/Queensland
  • Australia/South
  • Australia/Sydney
  • Australia/Tasmania
  • Australia/Victoria
  • Australia/West
  • Australia/Yancowinna
  • Brazil/Acre
  • Brazil/DeNoronha
  • Brazil/East
  • Brazil/West
  • CET
  • CST6CDT
  • Canada/Atlantic
  • Canada/Central
  • Canada/East-Saskatchewan
  • Canada/Eastern
  • Canada/Mountain
  • Canada/Newfoundland
  • Canada/Pacific
  • Canada/Saskatchewan
  • Canada/Yukon
  • Chile/Continental
  • Chile/EasterIsland
  • Cuba
  • EET
  • EST
  • EST5EDT
  • Egypt
  • Eire
  • Etc/GMT
  • Etc/GMT+0
  • Etc/GMT+1
  • Etc/GMT+10
  • Etc/GMT+11
  • Etc/GMT+12
  • Etc/GMT+2
  • Etc/GMT+3
  • Etc/GMT+4
  • Etc/GMT+5
  • Etc/GMT+6
  • Etc/GMT+7
  • Etc/GMT+8
  • Etc/GMT+9
  • Etc/GMT-0
  • Etc/GMT-1
  • Etc/GMT-10
  • Etc/GMT-11
  • Etc/GMT-12
  • Etc/GMT-13
  • Etc/GMT-14
  • Etc/GMT-2
  • Etc/GMT-3
  • Etc/GMT-4
  • Etc/GMT-5
  • Etc/GMT-6
  • Etc/GMT-7
  • Etc/GMT-8
  • Etc/GMT-9
  • Etc/GMT0
  • Etc/Greenwich
  • Etc/UCT
  • Etc/UTC
  • Etc/Universal
  • Etc/Zulu
  • Europe/Amsterdam
  • Europe/Andorra
  • Europe/Athens
  • Europe/Belfast
  • Europe/Belgrade
  • Europe/Berlin
  • Europe/Bratislava
  • Europe/Brussels
  • Europe/Bucharest
  • Europe/Budapest
  • Europe/Chisinau
  • Europe/Copenhagen
  • Europe/Dublin
  • Europe/Gibraltar
  • Europe/Guernsey
  • Europe/Helsinki
  • Europe/Isle_of_Man
  • Europe/Istanbul
  • Europe/Jersey
  • Europe/Kaliningrad
  • Europe/Kiev
  • Europe/Lisbon
  • Europe/Ljubljana
  • Europe/London
  • Europe/Luxembourg
  • Europe/Madrid
  • Europe/Malta
  • Europe/Mariehamn
  • Europe/Minsk
  • Europe/Monaco
  • Europe/Moscow
  • Europe/Nicosia
  • Europe/Oslo
  • Europe/Paris
  • Europe/Podgorica
  • Europe/Prague
  • Europe/Riga
  • Europe/Rome
  • Europe/Samara
  • Europe/San_Marino
  • Europe/Sarajevo
  • Europe/Simferopol
  • Europe/Skopje
  • Europe/Sofia
  • Europe/Stockholm
  • Europe/Tallinn
  • Europe/Tirane
  • Europe/Tiraspol
  • Europe/Uzhgorod
  • Europe/Vaduz
  • Europe/Vatican
  • Europe/Vienna
  • Europe/Vilnius
  • Europe/Volgograd
  • Europe/Warsaw
  • Europe/Zagreb
  • Europe/Zaporozhye
  • Europe/Zurich
  • Factory
  • GB
  • GB-Eire
  • GMT
  • GMT+0
  • GMT-0
  • GMT0
  • Greenwich
  • HST
  • Hongkong
  • Iceland
  • Indian/Antananarivo
  • Indian/Chagos
  • Indian/Christmas
  • Indian/Cocos
  • Indian/Comoro
  • Indian/Kerguelen
  • Indian/Mahe
  • Indian/Maldives
  • Indian/Mauritius
  • Indian/Mayotte
  • Indian/Reunion
  • Iran
  • Israel
  • Jamaica
  • Japan
  • Kwajalein
  • Libya
  • MET
  • MST
  • MST7MDT
  • Mexico/BajaNorte
  • Mexico/BajaSur
  • Mexico/General
  • Mideast/Riyadh87
  • Mideast/Riyadh88
  • Mideast/Riyadh89
  • NZ
  • NZ-CHAT
  • Navajo
  • PRC
  • PST8PDT
  • Pacific/Apia
  • Pacific/Auckland
  • Pacific/Chatham
  • Pacific/Easter
  • Pacific/Efate
  • Pacific/Enderbury
  • Pacific/Fakaofo
  • Pacific/Fiji
  • Pacific/Funafuti
  • Pacific/Galapagos
  • Pacific/Gambier
  • Pacific/Guadalcanal
  • Pacific/Guam
  • Pacific/Honolulu
  • Pacific/Johnston
  • Pacific/Kiritimati
  • Pacific/Kosrae
  • Pacific/Kwajalein
  • Pacific/Majuro
  • Pacific/Marquesas
  • Pacific/Midway
  • Pacific/Nauru
  • Pacific/Niue
  • Pacific/Norfolk
  • Pacific/Noumea
  • Pacific/Pago_Pago
  • Pacific/Palau
  • Pacific/Pitcairn
  • Pacific/Ponape
  • Pacific/Port_Moresby
  • Pacific/Rarotonga
  • Pacific/Saipan
  • Pacific/Samoa
  • Pacific/Tahiti
  • Pacific/Tarawa
  • Pacific/Tongatapu
  • Pacific/Truk
  • Pacific/Wake
  • Pacific/Wallis
  • Pacific/Yap
  • Poland
  • Portugal
  • ROC
  • ROK
  • Singapore
  • Turkey
  • UCT
  • US/Alaska
  • US/Aleutian
  • US/Arizona
  • US/Central
  • US/East-Indiana
  • US/Eastern
  • US/Hawaii
  • US/Indiana-Starke
  • US/Michigan
  • US/Mountain
  • US/Pacific
  • US/Pacific-New
  • US/Samoa
  • UTC
  • Universal
  • W-SU
  • WET
  • Zulu

miércoles, 19 de junio de 2013

Warning: Cannot modify header information - headers already sent by...

Situación:

Aparece este error en nuestro servidor de PHP:


Warning:  Cannot modify header information - headers already sent
 by (output started at 
/home/dominio/public_html/includes/functions/incrustaciones.php:496)
 in /home/dominio/public_html/general.php on line 108

Entendiendo el Problema:

En PHP podemos incrustar codigo para funciones recurrentes, esto lo hacemos con los siguientes comandos: include_once('archivodefunciones.php'), require('archivodefunciones.php').

Estos archivos incrustados solo deben contener PHP, y debemos asegurarnos que tanto al comienzo como al final se usen los TAG de código para determinar el contenido del archivo.  Estos tag son <?php al comienzo y ?> al final, entonces una estructura de un archivo incrustado debe ser:

Al comienzo:




Y al final:



Causas del problema:

El error se genera cuando hay contenido luego del cierre del archivo incrustado.  Es decir, el mensaje de eeror nos indica que debemos revisar el archivo incrustaciones.php (segun nuestro ejemplo), y debemos mirar al final del documento.  En pocas palabras encontraremos el archivo con el siguiente final:



Solución:

Hay dos maneras de solucionar el problema:
  1. Quitando el contenido restante luego del Tag de cierre de código.
  2. Quitando el Tag de cierre de código, indicando que el código de PHP no se ha terminado.
 

jueves, 27 de diciembre de 2012

Crear un XML desde un Array en PHP

Hace poco me encontré con la necesidad de generar archivos XML desde PHP. Lo interesante del tema es que el XML debe generarse en el servidor desde algunos parámetros, por eso era necesario incluir un encabezado para que el cliente lo identificara como tal.

Por lo tanto esto se compone de cuatro partes:

1) El encabezado en PHP:

<?php
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');

header('Content-type: text/xml');
?>


2) El array puede ser en cualquier complejidad. Aqui algunos ejemplos:

<?php
$array 
= array(
    
"foo" => "bar",
    
"bar" => "foo",
);
// a partir de PHP 5.4 

$array = [
    
"foo" => "bar",
    
"bar" => "foo",
];
?>

3) La invocación se hace por una función en donde se le pasa el array, indicandole cuál es el nodo del XML en el que se va a encapsular el resto de los datos:

echo arrayToXml($array,'datos');


4) La función que hace el trabajo es la siguiente:

function arrayToXml($array,$lastkey='root')
{
    $buffer.="<".$lastkey.">";
    if (!is_array($array))
    {$buffer.=$array;}
    else
    {
        foreach($array as $key=>$value)
        {
            if (is_array($value))
            {
                if ( is_numeric(key($value)))
                {
                    foreach($value as $bkey=>$bvalue)
                    {
                        $buffer.=arrayToXml($bvalue,$key);
                    }
                }
                else
                {
                    $buffer.=arrayToXml($value,$key);
                }
            }
            else
            {
                    $buffer.=arrayToXml($value,$key);
            }
        }
    }
    $buffer.="</".$lastkey.">";
    return $buffer;
}






5) El resultado que obtenemos es un archivo en XML con la siguiente estructura:

<datos>
   <foo>bar</foo>
   <bar>foo</bar>
</datos>

lunes, 30 de abril de 2012

Configuraciones universales o parámetros universales

Algunas veces nos encontramos con aplicaciones que requieren configuraciones, y estas, muchas veces, se hacen en un archivo de configuración. Pero luego, nos vamos dando cuenta que el archivo de configuraciones es tan grande, o que hay que darle acceso a varios colaboradores que implica que tengamos muchos detalles de seguridad que contemplar.

Indiferentemente a la tecnología, se puede construir un sistema de configuraciones que sea gestionable a nivel de base de datos y hacer una pantalla administrativa para sus diferentes valores.

¿Qué se puede guardar en un sistema de configuraciones?

Casi de todo: Traducciones, parámetros de configuración, plantillas de html, hojas de estilos css, llaves de acceso a APIs, definición de permisos, etc.

El esquema de la base de datos es la siguiente:

En donde:
  • config_id: Es un autonumérico, llave principal.
  • config_area: Nuestro proyecto puede tener varias áreas, aquí se pueden categorizar las diferentes configuraciones por cada uno de los módulos (usuarios, clientes, chat, agenda, facturas, etc)
  • config_texto: Es necesario que le pongamos un texto indicando de qué se trata la configuración.
  • config_parametro: Este es realmente el parámetro que será llamado desde el código, para poder hacer uso de su valor. Personalmente, acostumbro hacerlo memotécnico para poderlo leer o capturar fácilmente desde el código, por ejemplo: val_chat_permitir_salas_privadas, val_usuario_long_max_login, val_usuario_email_requerido, val_lang_en_register, etc
  • config_valor: Este es el valor que haremos uso en el aplicativo, el que mostraremos, o nos permitirá tener completamente configurado nuestro entorno. Sin importar el tipo de base de datos, es recomendable que sea de gran tamaño el archivo, para que su contenido pueda ser amplio.  en algunos proyectos, incluso aquí ingreso hasta la apariencia completa de la plantilla html del sitio.
Crear la tabla en SQLServer (2000, 2005, 2008)

CREATE TABLE [configuracion]( [config_id] [int] IDENTITY(1,1) NOT NULL, [config_area] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_texto] [varchar](1500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_parametro] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_valor] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL, CONSTRAINT [PK_configuracion] PRIMARY KEY CLUSTERED ( [config_id] ASC ) ) END

Crear la tabla en MySQL
CREATE TABLE IF NOT EXISTS `configuracion` ( `config_id` int(11) NOT NULL AUTO_INCREMENT, `config_area` varchar(50) DEFAULT NULL, `config_texto` varchar(1500) DEFAULT NULL, `config_parametro` varchar(50) DEFAULT NULL, `config_valor` text, PRIMARY KEY (`config_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Opcional a esto, se puede construir un administrador para estos datos, o se pueden gestionar todas las configuraciones a nivel de base de datos... eso ya depende del alcance que se le quiera dar al sistema de configuraciones universales.

Una sola función para invocar los valores
En VB.NET

Imports System.Data.SqlClient

    Function LN_obtener_configuracion(ByVal parametro As String) As String
        ' por defecto la respuesta de resultado es una cadena en blanco
        Dim rta As String = ""
        'se conecta a la base de datos
        Dim MyConnection As New SqlClient.SqlConnection("Data Source=server_name;Initial Catalog=my_db;Integrated Security=True")
        Dim MyCommand As SqlDataAdapter
        'hace la consulta en la base de datos
        MyCommand = New SqlDataAdapter("Select config_valor from configuracion where config_parametro='" & parametro.ToString() & "'", MyConnection)
        Dim DS As New DataSet
        Try
            MyCommand.Fill(DS, "res")
        Catch ex As Exception
            'aqui se controla cualquier error
        End Try
        'cierra las conexiones
        MyCommand.Dispose()
        MyConnection.Dispose()
        'extrae el valor, solo si hay algun contenido y existe el parámetro
        If DS.Tables("res").Rows.Count > 0 Then
            'Leemos la primera aparición de este valor en la BD, se supone que solo hay un registro con este parámetro
            rta = DS.Tables("res").Rows(0)("config_valor").ToString()
        End If
        'retorna el valor
        Return rta.ToString()
    End Function

En C#.NET
public string LN_obtener_configuracion(string parametro)
{
 // por defecto la respuesta de resultado es una cadena en blanco
 string rta = "";

 //se conecta a la base de datos
 System.Data.SqlClient.SqlConnection MyConnection = new System.Data.SqlClient.SqlConnection("Data Source=server_name;Initial Catalog=my_db;Integrated Security=True");
 SqlDataAdapter MyCommand = default(SqlDataAdapter);

 //hace la consulta en la base de datos
 MyCommand = new SqlDataAdapter("Select config_valor from configuracion where config_parametro='" + parametro.ToString() + "'", MyConnection);
 DataSet DS = new DataSet();
 try {
  MyCommand.Fill(DS, "res");
 } catch (Exception ex) {
  //aqui se controla cualquier error
 }

 //cierra las conexiones
 MyCommand.Dispose();
 MyConnection.Dispose();

 //extrae el valor, solo si hay algun contenido y existe el parámetro
 if (DS.Tables["res"].Rows.Count > 0) {
  //Leemos la primera aparición de este valor en la BD, se supone que solo hay un registro con este parámetro
  rta = DS.Tables["res"].Rows[0]["config_valor"].ToString();
 }
 //retorna el valor
 return rta.ToString();
}

En PHP
function LN_obtener_configuracion($parametro)
{
 $rta = "";
 $con = mysql_connect("localhost","peter","abc123");
 if (!$con) {
   die('Could not connect: ' . mysql_error());
 }
 
 mysql_select_db("my_db", $con);
 $result = mysql_query("Select config_valor from configuracion where config_parametro='" . $parametro . "'");
 while($row = mysql_fetch_array($result)) {
   $rta = $row['config_valor'];
 }
 
 mysql_close($con);
    return $rta;
}

Para su utilización simplemente ponemos en nuestro código:
VB.NET:
Dim txt_mensajebienvenida As String = LN_obtener_configuracion("val_lang_en_hello").ToString()

C#.NET:
string txt_mensajebienvenida = LN_obtener_configuracion("val_lang_en_hello").ToString();

PHP:
$txt_mensajebienvenida = LN_obtener_configuracion('val_lang_en_hello');

Y de esta manera la variable txt_mensajebienvenida tendrá a partir de este momento el valor que le hayamos puesto al parámetro de val_lang_en_hello en la base de datos.


7 razones para no usar Laravel en tu proyecto de PHP

En más de 40 años de experiencia como programador y director de proyectos de programación, he aprendido que cada requerimiento tiene mejores...