Instalar entorno LAMP (Apache, MySQL, PHP) en Ubuntu

Si eres Desarrollador Web, es necesario contar con un entorno LAMP local para nuestros proyectos.

Instalar Apache, MySQL y PHP en Ubuntu es algo muy sencillo, trivial para muchos, pero desconocido por algunos. Aquí las instrucciones.

Usando la Terminal

Para mi, la forma más sencilla:

$ sudo apt-get install lamp-server^

Y si, es muy importante el símbolo “^” al final, pegado a “lamp-server“, ya que le indica a apt-get que realmente se instalará un meta paquete, o sea, una tarea (task) que incluye varios paquetes.

Usando la interfaz gráfica

Si estás usando Ubuntu 10.10, malas noticias, a los chicos de Canonical se les olvidó incluir la opción “Marcar Paquetes por Tarea” en Synaptic (bug documentado).

Si usas alguna versión de Ubuntu previa a la 10.10, ve al menú principal Sistema » Administración » Gestor de paquetes Synaptic, y al abrirse la ventana, selecciona en su menú Editar » Marcar Paquetes por Tarea. Asomará el siguiente cuadro de diálogo:

Ubuntu LAMP

Sólo hay que seleccionar LAMP Server y dar click en el botón Aceptar.

Notas Finales

Durante el proceso de instalación (en cualquiera de las dos formas mencionadas anteriormente), se te solicitará ingreses (y confirmes) la contraseña para el usuario root de MySQL. Todo lo demás es automático.

Yo prefiero usar la terminal, ¿y tú qué método de instalación elegiste?

Aumentar el Tamaño Máximo al Cargar Archivos con PHP y Apache

Una restricción lógica, pero molesta a veces, es el límite máximo en tamaño cuando deseamos cargar algún archivo a nuestro servidor web. Lo anterior se hace más notable si estamos desarrollando una aplicación web donde los usuarios requieran subir archivos (ya sea imágenes, documentos, paquetes comprimidos, etc) y éstos son más grandes que el límite estándar, el cual normalmente es de 2 MB.

Otro escenario: Si administras algún sitio basado en WordPress, Drupal o Joomla, y quieres usar sus herramientas propias para subir archivos grandes, el resultado será un mensaje de error.

Ok, ¡basta de ejemplos! ¿cómo lo solucionamos? Hay varias maneras.

Solución 1: Modificar php.ini global

La mejor solución de todas (desgraciadamente no todos pueden implementarla): modificar el archivo principal de configuración de PHP. Si tenemos un servidor local, o hemos contratado un servidor dedicado, es casi un hecho que podemos modificar el php.ini global, pero si tenemos un servidor compartido (sumamente comunes en la web), esta solución normalmente no es posible (algunos web hostings si lo permiten).

Dependiendo de tu distro, debemos editar el archivo php.ini con alguno de los siguientes comandos:

En ArchLinux:

$ sudo vim /etc/php/php.ini

En Ubuntu y Debian:

$ sudo vim /etc/php5/apache2/php.ini

En Fedora y CentOS:

$ sudo vim /etc/php.ini

Si no te sientes a gusto con vim, puedes usar nano, gedit, o el editor que prefieras.

Dentro de php.ini, localiza el texto upload_max_filesize y asígnale un valor superior al que ya tiene, por ejemplo:

upload_max_filesize = 10M

También te recomiendo aumentar los valores de post_max_size(tamaño máximo de carga por envío, debe ser igual o mayor al especificado en upload_max_filesize), e incluso el de max_execution_time (tiempo máximo en segundos que el servidor esperará al script para que termine su ejecución, en este caso, la carga de archivos). Por ejemplo:

upload_max_filesize = 10M
post_max_size = 20M
max_execution_time = 120

Guarda el archivo, y sal del editor. Para que los cambios aplicados funcionen, basta con reiniciar Apache.

En ArchLinux:

$ sudo /etc/rc.d/httpd restart

En Debian y Ubuntu:

$ sudo /etc/init.d/apache2 restart

En Fedora y CentOS:

$ sudo /etc/init.d/httpd restart

Solución 2: Usar php.ini local

Básicamente es hacer lo mismo que la solución anterior, la diferencia es que no se modifica el php.ini global, si no que creamos un php.ini local. Este método tiene algunas limitantes:

  • Los efectos del php.ini local no son recursivos a los subdirectorios en donde se encuentre ubicado, así que no basta crearlo en el directorio raíz de nuestro servidor, si no que debemos especificar un php.ini en cada directorio donde queramos obtener el efecto deseado.
  • Puesto que cada php.ini local se toma en cuenta en vez del php.ini global, éstos deben incluir ciertas directivas de compatibilidad necesarias para el web hosting que tengas contratado, por lo que es necesario consultar a tu proveedor por dichas directivas.

Un ejemplo de php.ini local, con directivas de compatibilidad y las que nosotros necesitamos, sería:

zend_extension = /usr/local/ioncube/ioncube.so
register_globals = Off
magic_quotes_gpc = Off
session.save_path = /tmp
memory_limit = 200M
upload_max_filesize = 10M
post_max_size = 20M
max_execution_time = 120

Pero repito, es muy importante consultar la documentación de tu proveedor de hosting.

Solución 3: Usar .htaccess

Crea (o modifica, en caso de que ya exista) el archivo .htaccess en el directorio raíz de tu sitio, blog o aplicación web, o bien, en el directorio donde deseas que las directivas tengan efecto.

Agrega las siguientes líneas (modifica los valores según lo requieras):

php_value upload_max_filesize 10M
php_value post_max_size 20M
php_value max_execution_time 120

A diferencia de la solución anterior, aquí no hay limitantes: los efectos del .htaccess si son recursivos a los subdirectorios donde se encuentre ubicado, y basta con especificar las directivas que nos interesan.

Notas Finales

En algunos ejemplos mencionados, utilicé sudo, pues son comandos que deben ejecutarse con permisos administrativos. Si no tienes configurado tu usuario para utilizar sudo, entonces debes ejecutar dichos comandos como root.

¿Es mejor usar comillas simples que comillas dobles en PHP?

En CodeForest se dieron a la tarea de verificar si era mejor usar comillas simples (') que comillas dobles (") al usar echo en PHP. El resultado de las pruebas de velocidad y rendimiento arrojó el siguiente resultado:

Si se usa en cadenas de texto planas, su rendimiento es el mismo.

echo "Me llamo Gregorio";
echo 'Me llamo Gregorio';

Si se mezcla una cadena de texto plana con una variable, el rendimiento es superior al usar como separador una coma (tomar la cadena y la variable como parámetros); le sigue en rendimiento el uso de concatenación (con el operador “.“) y la de más pobre rendimiento (usa más memoria) es el uso de comillas dobles y la variable embebida dentro de la cadena de texto. En el orden mencionado:

echo 'Me llamo ' , $nombre;
echo 'Me llamo ' . $nombre;
echo "Me llamo $nombre";

El resultado es interesante, puesto que la gran mayoría de los programadores PHP usan la última forma, siendo la menos eficiente. Claro, algunos preferirán mayor claridad en el código fuente, que optimización al momento de ejecución. ¿Qué preferir? Depende de ti.

Adicionalmente, los invito a conocer el sitio The PHP Benchmark, donde se analizan detalles como el tratado en el presente post.

Mostrar como Tabla HTML los detalles de los campos de las tablas de una base de datos MySQL con PHP

Creo que es el título más largo que he usado en un post… “Mostrar como Tabla HTML los detalles de los campos de las tablas de una base de datos MySQL con PHP“… no encontré una mejor forma de resumirlo.

Hace poco tuve la necesidad de mostrar como tablas HTML los detalles de los campos (sus nombres, tipos, llaves, valores por defecto, etc) de las tablas de una base de datos MySQL en particular, utilizando PHP. Tomando la idea de David, la modifiqué y traduje según mis requerimientos (intentando dejar el script lo más general posible), y el resultado fué el siguiente código.

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<title>Detalles de las Tablas de una Base da Datos</title>
 
<style type="text/css">
body			{ font-family: Arial, Verdana, Sans; font-size: 14px; }
table.tabla-bd		{ border-right:1px solid #ccc; border-bottom:1px solid #ccc; }
table.tabla-bd th	{ background:#eee; padding:5px; border-left:1px solid #ccc; border-top:1px solid #ccc; }
table.tabla-bd td	{ padding:5px; border-left:1px solid #ccc; border-top:1px solid #ccc; }
</style>
 
</head>
<body>
 
<?php
# Datos de Conexión a la Base de datos
# (Hay que ajustarlos a tus necesidades particulares)
$servidor  = 'miservidor';
$usuario   = 'miusuario';
$password  = 'miclave';
$basedatos = 'mibasededatos';
 
# Establecer la conexión a la Base de Datos
$conexion = mysql_connect($servidor,$usuario,$password);
mysql_select_db($basedatos,$conexion);
 
# Consulta SQL que devuelve los nombres de las tablas de la Base de Datos
$tablas = mysql_query('SHOW TABLES',$conexion) or die('Imposible mostrar tablas');
 
 
while($tabla = mysql_fetch_row($tablas)) {
 
	$nombreTabla = $tabla[0];
	echo '<h3>Tabla: ',$nombreTabla,'</h3>';
 
	# Consulta SQL que devuelve los campos de cada tabla
	$campos = mysql_query('SHOW COLUMNS FROM '.$nombreTabla) or die('Imposible mostrar campos de '.$nombreTabla);
 
	# Muestra como tabla HTML los detalles de los campos de la tabla correspondiente
	if(mysql_num_rows($campos)) {
		echo '<table class="tabla-bd" cellpadding="0" cellspacing="0"><thead><tr><th>Campo</th><th>Tipo</th><th>Nulo</th><th>Llave</th><th>Defecto</th><th>Extra</th></tr></thead><tbody>';
		while($detalles = mysql_fetch_row($campos)) {
			echo '<tr>';
			foreach($detalles as $detalle=>$valor) {
				echo '<td>',$valor,'</td>';
			}
			echo '</tr>';
		}
		echo '</tbody></table><br />';
	}
}
 
#Cerrar la conexión a la Base de Datos
mysql_close($conexion);
?>
 
</body>
</html>

¿Simple no? También podrías reutilizar el código anterior, por ejemplo: Si tienes una clase que encapsule el manejo de tus bases de datos, podrías usar el script anterior como método, y así invocarlo con un simple $basedatos->mostrarTablas(); … bueno, es sólo una idea.

Validando un Email con PHP usando filter_var()

Desde la salida de PHP 5.2.0, la extensión de filtros fué habilitada por defecto, y rápidamente se convirtió en una favorita entre los programadores de PHP.

Sin embargo, el filtro para validar emails no era 100% efectivo, ya que no tomaba en cuenta algunos detalles; por ejemplo, filter_var('john@lennon', FILTER_VALIDATE_EMAIL) tomaba como válido el email, a pesar de carecer del “.com”.

¿Cómo corregir esto? En The Electric Box encontraron una solución bastante simple y concreta: usar las maravillosas expresiones regulares.

Usaremos una función que encapsule la validación de emails:

function validarEmail($email) {
  return filter_var($email, FILTER_VALIDATE_EMAIL) && preg_match('/@.+\./', $email);
}

Para probar su funcionamiento, aquí algunos ejemplos de uso:

echo (int) validarEmail('john@lennon');             // 0
echo (int) validarEmail('john@lennon.');            // 0
echo (int) validarEmail('john@lennon.com');         // 1
echo (int) validarEmail('john@lennon.com.');        // 0
echo (int) validarEmail('john@lennon@beatles.com'); // 0
echo (int) validarEmail('john#lennon.com');         // 0
echo (int) validarEmail('john@lennon.beatles.com'); // 1

En el ejemplo anterior se utilizó cast (int) para convertir a entero el booleano devuelto por la función, ergo, 0 = false = email inválido, 1 = true = email válido.

Sencillo, ¿verdad? ¡Comentarios bienvenidos!

Calculando una Fecha Relativa con PHP

A veces en nuestros desarrollos web, necesitamos mostrar alguna fecha al puro estilo de Twitter, o sea, “hace 5 minutos“, “ayer“, “la semana pasada“, etc., pero PHP no incluye una función que lo haga por nosotros; afortunadamente, podemos crear nuestra propia función.

Aquí nuestra propuesta:

function FechaRelativa($fechaAbsoluta)
{
    $dias       = intval((time() - $fechaAbsoluta) / 86400);
    $segundos   = intval((time() - $fechaAbsoluta));
 
    if($dias < 0) {
        return -1; //Error
    } elseif ($segundos==0) {
        $fecha = "En este momento";
    } elseif ($segundos > 0 && $segundos < 60) {
        $fecha = "Hace " . $segundos . " segundos";
    } elseif ($segundos >= 60 && $segundos <120 ) {
        $fecha = "Hace un minuto";
    } elseif ($segundos >= 120 && $segundos < 3600 ) {
        $fecha = "Hace " . intval($segundos/60) . " minutos";
    } elseif ($segundos >= 3600 && $segundos < 7200) {
        $fecha = "Hace una hora";
    } elseif ($segundos >= 7200 && $segundos < 86400) {
        $fecha = "Hace " . intval($segundos/3600) . " horas";
    } elseif ($dias==1) {
        $fecha = "Ayer";
    } elseif ($dias >= 2 && $dias <= 6) {
        $fecha =  "Hace " . $dias . " días";
    } elseif ($dias >= 7 && $dias < 14) {
        $fecha= "La semana pasada";
    } elseif ($dias >= 14 && $dias <= 365) {
        $fecha =  "Hace " . intval($dias / 7) . " semanas";
    } else {
        $fecha = date("d-m-Y", $fechaAbsoluta);
    }
 
    return $fecha;
}
 
?>

La función FechaRelativa() acepta como parámetro una fecha absoluta en formato timestamp, y devuelve una cadena de texto, que representa la fecha relativa de dicho parámetro.

El código de FechaRelativa() está inspirado en la idea de los amigos de Code Diesel.

Comparativa de Versiones LAMP entre CentOS, Debian y Ubuntu Server

Probando diferentes distribuciones de Linux para montar un Servidor para Producción, me dió curiosidad conocer qué versiones de Kernel, Apache, MySQL y PHP son las que traen por defecto las últimas versiones de CentOS, Debian y Ubuntu Server.

¿Por qué esas distros? Luego de investigar un poco, son de las tres más recomendadas dentro de las gratuitas (por eso no estoy tomando en cuenta a Red Hat Enterprise Linux 5 y SUSE Linux Enterprise 11).

¿Qué versiones comparé? CentOS 5.5, Debian 5.0 y Ubuntu Server 10.04 (las últimas versiones disponibles al día de hoy, 28 de Mayo de 2010).

Luego de instalar desde cero cada distro, usando sólo paquetes estables recomendados de cada una, aquí el resultado obtenido:

  CentOS 5.5 Debian 5.0 Ubuntu 10.04 G.A.
Kernel 2.6.18 2.6.26 2.6.32 2.6.33
Apache 2.2.3 2.2.9 2.2.14 2.2.15
MySQL 5.0.77 5.0.51 5.1.41 5.1.47
PHP 5.1.6 5.2.6 5.3.2 5.3.2

En la última columna podemos observar la versión “Generally Available“, en otras palabras, la última versión oficial estable de cada paquete.

Es obvio que el número de versión de cada paquete no es un factor determinante para elegir entre una distribución u otra, pero dependiendo de nuestras necesidades específicas, si nos puede orientar para tomar una mejor decisión.

Y por si te lo estás preguntando, en mi caso muy particular, elegí Debian 5.0 para montar mi servidor de producción.

¿Cuál es tu distro favorita para servidores?

Instalar y Configurar PHP y MySQL en Cherokee Web Server

Cherokee Logo¿Ya instalaron Cherokee Web Server? Entonces seguro deseas que funcione con PHP y MySQL… ¡es muy sencillo! Sólo hay que seguir los pasos siguientes para Ubuntu.

  1. Si aún no lo haces, instala Cherokee Web Server.
  2. Si ya tienes instalado Apache, hay que eliminarlo para evitar conflictos.
  3. sudo update-rc.d -f apache remove

  4. Instala MySQL y PHP (si aún no los tienes instalados) usando el comando
  5. sudo apt-get install mysql-server mysql-client php5-cgi php5-mysql

  6. Por último, en el panel de administración de Cherokee, debemor entrar a la opción vServers, y ahí seleccionar el servidor default, y a la derecha seleccionar la ficha Comportamiento, y ahí dar click al botón Manejo de Reglas. Entonces, damos click al botón con el símbolo “+” para agregar una nueva regla, donde aparecerá una “ventana” donde debemos seleccionar la opción Lenguajes, y ahí seleccionamos PHP, para entonces darle click al botón Añadir.
  7. Cherokee PHP

  8. Por último, te sugerimos reiniciar el sistema para que todos los cambios sean aplicados.

Si te das cuenta, no hay que hacer nada para que Cherokee reconozca a MySQL. Por otro lado, el proceso mencionado es para Ubuntu; para otras distribuciones recomiendo leer la documentación oficial de Cherokee.

¡A probar la velocidad de Cherokee Web Server!

Invocando Objetos como si fueran Funciones en PHP

Interesante nueva funcionalidad la que trae PHP 5.3. Si ya estás usando esta versión de PHP, sigue leyendo. Existe el método __invoke que permite invocar (valga la redundancia) a un objeto como si fuera una función. Aquí un ejemplo:

class Mensaje {
    public function __invoke($texto) {
        return "¡Saludos $texto!";
    }
}
 
$saludo = new Mensaje;
echo $saludo('Gregorio'); // "¡Saludos Gregorio!"

Como detalle adicional, es interesante saber que esta forma es 25% más rápida que si hiciéramos una llamada a un método del objeto; por este simple hecho, vale la pena tomar en cuenta a __invoke.

Gracias a Sentido Web por el dato.

NetBeans IDE 6.7 Liberado

Hace algunos días fué liberada la nueva versión de un favorito de los desarrolladores, NetBeans IDE 6.7. Para quien no lo conozca, se trata de un entorno integrado de desarrollo (IDE) con características muy poderosas que lo hacen uno de los mejores en su clase. Pueden dar click sobre la imagen para verla completa.

NetBeans IDE 6.7

En esta versión, se destaca la integración con el Proyecto Kenai, un entorno de desarrollo colaborativo para el hospedaje de proyectos. A pesar de poder utilizar prácticamente cualquier lenguaje de programación, NetBeans se enfoca a Java, PHP, Ruby, JavaScript, Groovy y C/C++.

En lo particular, me agradó la integración con las APIs de servicios web, tales como Amazon S3, Delicious, Facebook, Flickr, Google (AdSense, Maps, etc), Twitter y Yahoo, entre otros.

Muchos desarrolladores toman por de facto a Eclipse como su entorno de desarrollo, pero siempre es bueno conocer otras alternativas (NetBeans, como Eclipse, es de código abierto, gratuito y multiplataforma), y comparar sus características; los invito a descargar NetBeans IDE 6.7, se encuentra disponible para Windows, MacOS X, Linux y Solaris.

Enlace: Descargar NetBeans IDE 6.7.