Deploy sencillo de Symfony 2 con GIT

Cuando tenemos lista nuestra aplicación Symfony 2, queremos una forma ágil de subirla a nuestro servidores sin que cada vez haya que hacer el proceso manualmente. Existen muchas maneras de hacerlo como por ejemplo:

  • Crearse un script bash que haga la subida con “scp” o “rsync”
  • Usar herramientas especificas como Capistrano (o Capifony para Symfony)
  • Usar bundles que ya te dan el trabajo medio hecho
  • Hacerlo mediante Git y los Hooks.

Yo os explicaré esta última, ya que como suelo trabajar con git, me es muy cómodo tener los Deploys integrados.

1 – Preparar el servidor

Lo primero de todo es preparar el servidor. Primero de todo dentro creamos una carpeta que alojara el git de nuestro proyecto, en mi caso lo tengo creado dentro del virtualhost, al lado de las carpetas httpdocs y logs. Y luego iniciaremos en la carpeta “deploy” un repositorio git “bare” (sin estructura de ficheros).

 

Selection_006

mkdir deploy
cd deploy
git init --bare

2 – Creamos el hook

Luego creamos un hook en el repositorio del tipo “post-receive”. Es un script que se ejecutará una vez ese repositorio reciba un “push”. Para ello simpemente creamos dentro de “deploy/hooks” un archivo llamado “post-receive”.

#!/bin/bash
read from to branch

if [[ $branch != *"master"* ]]
then
  echo "Received branch ${branch}, not deploying.";
  exit;
fi

DEPLOYDIR="/var/www/html/www.example.com/httpdocs"
GIT_WORK_TREE="${DEPLOYDIR}" git checkout -f
cd "${DEPLOYDIR}"
sh script_update.sh

Para que funcione le deberemos dar permisos de ejecución (chmod +x post-receive).

3 – Script de actualización

Si os fijáis en las lineas del hook, se hace una llamada a un script “script_update.sh”. Esto es opcional, pero seguramente queráis limpiar cache, hacer migración de datos, ejecutar algun comando o actualizar la base de datos. Os dejo un ejemplo que lo que podría ser:

#!/bin/sh
php composer.phar install
php app/console cache:clear --env=prod --no-warmup
php app/console doc:sc:up --force
php app/console assetic:dump
php app/console assets:install web

4 – Preparar para el “push”

Ahora solo tenemos que crear el repositorio remoto en nuestro git local (donde trabajamos con el proyecto). De manera que al hacer PUSH a ese repositorio, se suba el código.

Recordad que sería algo asi como: “git remote add deploy ssh://vuestro_servidor/var/www/../deploy”

5 – Conclusiones

Bueno la magia ya esta preparada, está será la secuencia, cuando queráis hacer un deploy a vuestro servidor:

  1. Con todo vuestro código commiteado hacéis PUSH en el remoto llamado “deploy”
  2. El código se subira al git del servidor
  3. Se ejecutará el hook que movera el contenido a vuestra carpeta de la aplicación
  4. Se ejecutará el script que limpiará la cache y demás tareas

¡Tachán ya tenéis una manera de actualizar vuestra web con un sólo comando!

¿Qué maneras usáis vosotros?

 

Leer Más

Problemas de cache de Symfony2 en Ubuntu

Su hubiera un ranking de los errores mas producidos en Symfony2 sin duda seria:

RuntimeException: Failed to write cache file

Este es el típico error de permisos de escritura de las carpetas app/logs y app/cache/ y esto se debe que en vez de hacerlo bien desde el principio le damos permisos “chmod -R 777” o alguna burrada así. A parte de los problemas claros de esto, simplemente nos volverà a fallar cuando hagamos un “cache:clear” o un “composer update” dado que el sistema siempre reescribirá esas carpetas y volveremos a perder los permisos.

Para solucionar eso simplemente hay que leer la guía de instalación basica de Symfony donde nos explica que para sistemas Ubuntu (en mi caso) necesitamos el siguiente código para configurar permisis de una vez por todas:

rm -rf app/cache/*
rm -rf app/logs/*
HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1`
sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs
sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs

 

Leer Más

Envío de emails con PHP, instalación de un SMTP

mandrill-snarl_2110219iEstaba yo migrando algunas webs que tengo de un servidor a otro: he pasado de un servidor compartido (el típico plan que te pueden ofrecer cualquier empresa de hosting) a un servidor dedicado (bastante pequeño) pero a mi me va de sobras, además éste esta en Francia (OVH), a diferencia del que tenia antes (DreamHost) en Estados Unidos, la verdad que la latencia se nota un pico.

Después de dejar montado todo el servidor con el stack LAMP básico, me tocaba configurar un servicio para envíar emails para luego usarlo en mis aplicaciones en PHP. Al principio me decante por  (más…)

Leer Más

Migrando de MySQL a Oracle para PHP (problemas!)

Bueno, hacía tiempo que no escribía por aquí, la verdad es que me cuesta mantener un ritmo constante, puesto que ahora que tengo un trabajo fijo (bien!?) a veces vuelvo a casa y lo último que me apetece es seguir escribiendo sobre programación, pero que os voy a contar ¿no?

En fin, volviendo al tema importante, hace unos días nos propusieron actualizar una aplicación hecha enteramente en PHP (nativo, sin ningún framework), para que soportase oracle. Bien la cosa no parecía difícil, porque esa aplicación, tenía una librería con las funciones de MySQL, por lo que sería tan fácil como duplicar esa librería y substituir las funciones por las de Oracle. Después de ver lo que había, decidimos usar la OCI8 de PHP (documentación).

Bien, este artículo no es para haceros un tutorial sobre como migrar de MySQL a Oracle, pero si que quería comentar algunos de los problemas que nos hemos ido encontrando, tanto a nivel de funciones en PHP como al migrar con SQL de una a la otra. Y ojo! Yo tuve que aprender Oracle a marchas forzadas, por lo que me considero un usuario de este gestor totalmente novato, seguramente los errores expuestos a continuación se pueden solventar de una manera quizá mas compleja y profesional, pero al menos os daré un punto de partida si estáis en los mismos problemas que yo.

Para empezar, la migración la hicimos “automaticamente” mediante SQL Developer (enlace) y estos fueron algunos de los problemas y consideraciones que nos encontramos:

1) los campos TEXT de MySQL pasan a ser objetos LOB de Oracle, por lo que a posteriori, será diferente tratarlos, ya que las consultas no nos devolverán una “string”, sino que te devuelven un objeto OCILOB (documentación), que para leerlo se tendrá que hacer algo así como:

//$cad sería el valor del campo de la base de datos tipo CLOB
$cad = (string)$blob->read($blob->size());	

(más…)

Leer Más

Creando nuestro Foro (Cuarta Parte): Los posts

Bueno, ahora la parte mas importante, tenemos que mostrar los posts, la idea es la misma que en los tutoriales anteriores. Primero de todo necesitaremos una “ruta” arriba de todo que nos indique el nombre del tema, así como la categoría de la que deriva, importante para que los usuarios no pierdan la pista de dónde están (obviamente serán links para volver atrás).

Pero vayamos por partes, primero de todo nueva función en el controller, que manejara los temas, al igual que lo hacía con las categorías:

function tema($id = 0)
{
	if((int)$id< =0)
	{
		echo "Error, no existe una tema con esta id.";	
	}
	else
	{
		$this->load->model("foros_model", "foros");	
		$this->load->model("usuarios_model", "usuarios");							
		
		$vars['query'] = $this->foros->getPosts($id);
		$this->load->view("header");
		$this->load->view("foros/tema", $vars);
		$this->load->view("footer");				
	}
}

Ahora pasaremos al view, que tiene bastante chicha:

< ?php
	echo '<h2><a href="index.php/foros/index">Foros</a> &raquo; <a href="index.php/foros/categoria/'.$this->foros->getPostsTemaParam((int)$this->uri->segment(3), "cat_id").'">'.$this->foros->getNombreCategoria($this->foros->getPostsTemaParam((int)$this->uri->segment(3), "cat_id")).'</a>: "'.$this->foros->getPostsTemaParam((int)$this->uri->segment(3), "titulo").'"';

	if($query->num_rows() > 0)
	{
		foreach($query->result() as $row)
		{
			echo '<h4>'.$this->usuarios->getName($row->usuario_id).' dice:</h4>';
			echo '<p>'.$row->cuerpo.'</p>';
		}
	}
	else
	{
		echo '<p>No hay ninguna tema creado</p>';	
	}
?>

La primera linea, que es muy larga es para lo que os comentaba al principio. Como véis hago uso repetidamente de una función que he creado en el model, que nos dará toda la información que queramos del tema (titulo, id, categoría a la que pertenece).

Como veis la función es muy simple, jugamos con los parámetros que nos pasan y hacemos que la función sea genérica para nuestros propósitos, así la podemos reutilizar sin necesidad de crear una función especifica para cada cosa.

function getPosts($tema_id = 0)
{
	$this->db->where("tema_id", $tema_id);
	$this->db->order_by("id", "ASC");
	$q = $this->db->get("forum_posts");	
	return $q;
}

function getPostsTemaParam($id, $param)
{
	$this->db->where("id", $id);
	$this->db->select($param);
	$q = $this->db->get("forum_temas");
	$r = $q->row_array();
	return $r[$param];
}

Y bueno el trabajo está casi listo, esto ya tiene pinta de foro (cutre y sin estilos, pero eso es lo de menos ahora mismo). Lo que haría falta tanto en temas como en posts es un botón que nos lleve a un formulario para poder crear nuevos temas y nuevos posts. Pero eso es muy sencillo y seguro que todos sabréis hacerlo me imagino, ya que simplemente se trata de insertar información a la base de datos. Esto ya lo hemos visto en un tutorial anterior: Gestor de noticias.

También comentar que para un foro, obviamente necesitáis un sistema de usuarios, así que echadle un vistazo al que ya hicimos hace tiempo: Sistema de Usuarios.

La cosa ha quedado algo así:

———-

Como quedó el foro

Leer Más

Creando nuestro Foro (Tercera parte): Los temas

Bueno, ahora ya teníamos el listado de categorías funcionando, así que profundizaremos un nivel mas, los temas. Para que nos entendamos veamos que profundidades tendremos en el foro:

Foro > Categorías > Temas > Posts

Empezando a programar me di cuenta que harían falta unos retoques en la base de datos, pues necesito una tabla para los “temas” que no había creado. Como el tutorial lo voy haciendo poco a poco a medida que lo hago, también me doy cuenta de errores y cosas que me olvido, y como ya os avisé, la base de datos siempre hay que adaptarla.

Veamos la nueva tabla “forum_temas”, de momento tendrá estos campos (y de paso una fila de ejemplo):

Tabla de los temas

Como suponéis, cat_id hará referencia a la id de la categoría.

Luego también necesitaremos unos cambios en la tabla “forum_posts”, pues añadiendo la anterior hay algunos campos que ya no necesitamos.

nueva tabla de posts

Hemos incorporado el tema_id, sustituyendo a padre, para que quede mas claro hacía donde es la referencia. También hemos quitado el titulo, porque ya lo lleva la tabla anterior.

Ahora ya pasamos a la programación en PHP y CodeIgniter.

(más…)

Leer Más

Creando nuestro Foro (Segunda parte): Las categorías

Bueno ha llegado el momento de ponerse a programar en CodeIgniter, pues ya tenemos las bases de datos creadas. Para empezar pondremos algunos valores en la base de datos, en la tabla de categorías, por ejemplo estas:

categorías en la base de datos

Os podéis fijar, tal y como os comenté en el post anterior como funciona el tema del “padre”, simplemente hace referencia a la ID a la cual pertenece. En este caso tenemos la categoría padre (definida por padre=0) “General” y sus hijos son “Noticias” y “Off-topic”, de todas maneras luego lo veréis mas claro.

Ahora necesitaremos las 3 partes fundamentales del modelo MVC que son: la vista, el controlador y el modelo, asi que lo vamos a crear.

  1. El controlador: controllers/foros.php
  2. El modelo: models/foros_models.php
  3. Las vistas irán dentro de la carpeta views/foros, y crearemos index.php

Una vez tenemos creados estos 3 archivos empezaremos a hilar un poco todo para empezar a mostrar las categorías. Empezaremos por el modelo, es el que nos ayudara a comunicarnos con la base de datos, el código será este de momento:
(más…)

Leer Más

Creando nuestro Foro (Primera parte): La base de datos

Bueno abro este nuevo taller, para crear un foro en CodeIgniter. Obviamente no será tan completo como aquellos que circulan por Internet (phpBB y sucedaneos), pero si será una sencilla base para que por un lado aprendáis a usar CodeIgniter y por otro lado podáis ampliarlo para adaptarlo a vuestro gusto.

Como siempre empezaremos poco a poco y con buena letra. Lo primero será crear las tablas necesarias para la base de datos. Mantendremos el asunto sencillo y empezaremos con la estructura mas básica de todas.

Vamos a las categorías que tendrá el foro, ahora mismo se me ocurren estos campos

  • id
  • nombre
  • padre

Simple y sencillo. Padre simplemente hará referencia de si es una categoría que dependa de otras o es una principal. Este es el código SQL:

CREATE TABLE IF NOT EXISTS `forum_cat` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nombre` varchar(100) NOT NULL,
  `padre` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Luego la tabla de posts quedaría con estos campos:

  • id
  • titulo
  • cuerpo
  • fecha
  • usuario_id
  • padre

Tampoco descarto que a mitad de la programación de este foro me de cuenta que falta algún campo, pues tened en cuenta que voy escribiendo esto a medida que lo voy a ir programando. Así quedaría el código SQL:

CREATE TABLE IF NOT EXISTS `forum_posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `titulo` varchar(100) NOT NULL,
  `cuerpo` text NOT NULL,
  `fecha` datetime NOT NULL,
  `usuario_id` int(11) NOT NULL,
  `padre` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Y bueno para empezar creo que es todo lo que nos hará falta. Si creéis que me puedo dejar algún campo básico para el funcionamiento, comentad o pasaros por el foro y lo discutimos ;)

El próximo post mas y mejor.

Leer Más

Formulario de contacto (Tercera parte): Enviando emails

Bueno esta es la ultima parte de este sencillo tutorial, seguimos con la creación de un formulario de contacto en CodeIgniter, basicamente lo que vamos a hacer ahora es utilizar la libreria Email Class.

Como tenemos las variables de “nombre, “email” y “texto” simplemente tendremos que introducirlas en las funciones correspondientes, algo así como:

< ?php 
if(!defined('BASEPATH')) 
	exit('No direct script access allowed');

class Contacto extends CI_Controller 
{
	function __construct()
	{
		parent::__construct();
	}

	function index()
	{

		$this->load->library('form_validation');
		
		$this->form_validation->set_rules('nombre', 'Nombre', 'trim|required|xss_clean');
		$this->form_validation->set_rules('email', 'Email', 'required|valid_email');	
		$this->form_validation->set_rules('texto', 'Texto', 'xss_clean');	

		if($this->form_validation->run())
		{
			//print_r($_POST);	
			
			$this->load->library('email');

			$this->email->from('webmaster@noquieroprogramar.com', 'Lagarto');
			$this->email->to($_POST['email']);
			
			$this->email->subject('Contacto de tu web');
			$this->email->message($_POST['nombre']. ", se ha puesto en contacto contigo y te ha dicho: ".$_POST['texto']);
			
			$this->email->send();
			
			echo $this->email->print_debugger();
		}
		else
		{
			$this->load->view('contacto');
		}		
	}
}
?>

Veréis como he dejado la función “debug” para que comprobéis que todo ha ido correctamente, obviamente esto no lo tendríais que incluir en vuestra aplicación sino un “redirect” hacía alguna página que ponga “Has enviado correctamente el formulario” o algo parecido.

Aquí la prueba:

Prueba del envío de email

A partir de aquí, lo podéis complicar como queráis, pero esta es la base mas simple para empezar a trabajar.

Para cualquier duda que tengáis sobre esto u otra cosa no olvidéis pasaros por el foro. (tenéis en enlace por la derecha y arriba de la web).

Leer Más

Formulario de contacto (Segunda Parte): Validación

Bueno siguiendo el taller/tutorial del otro dia, voy a proceder con la validación del formulario. Si recordáis, teníamos el formulario creado y usamos la función print_r para ver que recibíamos correctamente las variables. Hoy basicamente lo que haremos es comprobar que esas variables que recibimos son lo que nosotros queremos, es decir vamos a validar que el usuario ha introducido lo que nosotros buscamos.

  • Nombre: tiene que ser requerido para enviar el formulario
  • Email: tiene que ser requerido y ser un email valido.
  • Texto: opcional.

Para empezar, iremos a ver la guía en la documentación de CodeIgniter y veremos como se utiliza la librería: Form Validation. Siguiendo los sencillos pasos del principio tendremos este código en el controlador contacto.php:

(más…)

Leer Más