Cómo crear y usar funciones en Symfony 2.8

Como en toda aplicación compleja, en Symfony es posible crear y usar funciones personalizadas. La cuestión clave, además de escribirlas bien, es ubicarlas en las carpetas apropiadas y llamarlas del modo correcto. Distinguiremos dos casos:

  1.  Funciones a utilizar en un controlador.
  2. Funciones a utilizar en una plantilla TWIG.

Veamos estos casos a través de ejemplos.

Funciones a utilizar en un controlador

Desarrollaré este punto a partir de un ejemplo concreto. Tengo una «acción» en un controlador con el siguiente código:

$mi_numero= number_format($contrat['id'], 0, ',', '.');
$mi_fecha_firma=ConverterHelper::obtenermiFecha($contrat['fechaFirma']);
$mi_fecha_inicio=ConverterHelper::obtenermiFecha($contrat['fechaInicio']);
$mi_fecha_final=ConverterHelper::obtenermiFecha($contrat['fechaFinal']);
$mi_nombres=$contrat['docentes']['nombres']; //funciona
$mi_apellido=$contrat['docentes']['apellido']; //funciona
$mi_dni=$contrat['docentes']['dni']; //funciona
$mi_cuit=$contrat['docentes']['cuit'];
$mi_direccion=$contrat['docentes']['direccion'];
$mi_direccion=  str_replace('Piso:   Depto:   Barrio:', 'Barrio:',    $mi_direccion); //depuracion 1
$mi_direccion=  str_replace('Depto:   Barrio:', 'Barrio:', $mi_direccion); //depuracion 2
$mi_materia=$contrat['materias']['descripcion']; //funciona
$mi_carrera = $contrat['materias']['carreras']['descripcion'];
$mi_institucion = $contrat['materias']['carreras']['institucion']['nombre'];
$mi_monto= number_format($contrat['monto'], 2, ',', '.');
$mi_monto_letras= ConverterHelper::numtoletras($contrat['monto']);
$mi_monto_adicional= number_format($contrat['montoAdicional'], 2, ',', '.');
$mi_monto_adicional_letras= ConverterHelper::numtoletras($contrat['montoAdicional']);
$mi_garantia = $contrat['garantiaMinAlumnos'];
$mi_marca_imprimir= ($contrat['marcaImprimir']) ? 'Sí' : 'No' ;

En las líneas de código de arriba, tenemos varios ejemplos de llamado a funciones. Algunas como $mi_monto= number_format($contrat[‘monto’], 2, ‘,’, ‘.’); llaman a una función predefinida de PHP. Como muestra el ejemplo, necesito que un número $contrat[‘monto’], sea formateado con dos decimales, y el separador decimal sea la coma y el separador de miles el punto.
Luego tengo un ejemplo del llamado a una función personalizada: $mi_monto_letras= ConverterHelper::numtoletras($contrat[‘monto’]); Se trata del mismo monto anterior, que quiero expresar en letras, ya que la información que estoy procesando, será utilizada en un contrato comercial. A través de la expresión, llamo a una función que hace esta tarea, a la que le envío un número, y me devuelve el mismo número pero en letras. Es decir, si el número enviado a la función «numtoletras» es «1510» el texto devuelto por la función será: «un mil quinientos diez».
Observese la sintaxis: estoy llamando a una clase ConverterHelper y dentro de la clase, a una función llamada numtoletras a la que le paso el argumento $contrat[‘monto’]. Lo expresamos como ConverterHelper::numtoletras($contrat[‘monto’])
Para que esta función pueda operar hay que tomar varios recaudos. Paso a explicar:

Primero que nada, debemos definir en el archivo de controlador donde vayamos a usar la o las funciones, la ruta donde Symfony podrá encontrar esas funciones.En la imagen siguiente, tenemos las primeras líneas de código del archivo ContratosController.php

contratos_controller

Podemos observar en el recuadro rojo de arriba, que hay dos funciones declaradas con su ruta, que son las que se utilizan en distintas partes del archivo de controlador, ContratosController.php
Yo he creado una carpeta especial para las funciones personalizadas a utilizar en los diferentes controladores, que he llamado Helper y está dentro de la carpeta Controller del bundle, BackendBundle, como se muestra en la imagen siguiente:

helper

Vemos que dentro la carpeta Helper hay tres archivos PHP. Cada archivo puede conterner más de una función, pero por claridad conviene crear un archivo para cada función. En cada archivo PHP procedo a crear una clase y dentro de esa clase, pongo las funciones a utilizar. En el ejemplo que venimos desarrollando, tengo la clase ConverterHelper y dentro de la clase la función numtoletras

Podemos ver las primeras líneas de código del archivo ConverterHelper.php en la imagen siguiente:

converter

Funciones a utilizar en una plantilla TWIG

Con las funciones personalizadas a utilizar dentro de archivos Twig, la filosofía es similar a las funciones utilizadas en los controladores: mantener separadas las funciones, respecto de las plantillas de Twig donde son llamadas. Solo cambia en algo la sintaxis. Recordemos que en los archivos Twig, no podemos incorporar en forma directa código PHP, de modo que si necesitamos usar código PHP, debemos llamar a una función externa a la plantilla, para ejecutar ese código.

Primero que nada, debemos decirle a Symfony donde estarán las funciones de Twig. Esto lo hacemos en el archivos services.yml que se encuentra en la carpeta app\config donde definimos los parámetros que se muestran en la figura siguiente:

services

Veamos el uso de las funciones, desarrollando dos ejemplos muy sencillos.

Empecemos por el primero. He creado una función en Twig para formatear los títulos de una manera determinada y siempre igual para todas las plantillas. El llamado a la función, que la he denominado poner_h1, se muestra en la imagen siguiente donde tengo una plantilla Twig:

h1ejemplo

A esta función, le paso el contenido del título, en este caso «Nuevo Docente». La función se ejecuta en un archivo denominado AppExtension.php que está ubicado en la carpeta AppBundle\Twig\AppExtension tal como lo definimos en el archivo services.yml

A continuación el contenido del archivo con las dos funciones de ejemplo que mostraré.

namespace AppBundle\Twig;

class AppExtension extends \Twig_Extension
{

public function getFunctions()
{
return array(
new \Twig_SimpleFunction('poner_h1',  array($this, 'ponerh1')),
new \Twig_SimpleFunction('obtener_fecha',  array($this, 'obtenerFecha')),

);
}

public function ponerh1($mititulo)
{
$mititulo_formateado='
<table width="100%">
<tbody>
<tr>
<td align="center">
<h1>'.$mititulo.'</h1>
</td>
</tr>
<tr></tr>
</tbody>
</table>
';

return $mititulo_formateado;
}

public function obtenerFecha()
{
setlocale(LC_ALL, "es_ES");
$timestamp=time();
$format='l j  F Y H:i';
$trans = array(
'Monday' => 'Lunes,',
'Tuesday' => 'Martes,',
'Wednesday' => 'Miércoles,',
'Thursday' => 'Jueves,',
'Friday' => 'Viernes,',
'Saturday' => 'Sábado,',
'Sunday' => 'Domingo,',
'January' => ' de Enero de ',
'February' => ' de Febrero de ',
'March' => ' de Marzo de ',
'April' => ' de Abril de ',
'May' => ' de Mayo de ',
'June' => ' de Junio de ',
'July' => ' de Julio de ',
'August' => ' de Agosto de ',
'September' => ' de Septiembre de ',
'October' => ' de Octubre de ',
'November' => ' de Noviembre de ',
'December' => ' de Diciembre de ', );

return strtr(date($format,$timestamp),$trans);

}

}

Observemos que dentro la clase AppExtension tenemo dos «zonas» bien diferenciadas. Por un lado la función public function getFunctions() donde tengo listado el conjunto de las funciones de Twig que voy a utilizar. En este primer ejemplo, vemos que la línea de código donde se declara esta función es:
new \Twig_SimpleFunction(‘poner_h1’, array($this, ‘ponerh1’)),
aquí queda definido un nuevo nombre interno, para ejecutar la función: ‘ponerh1’ Esta es la función propiamente dicha, que se localiza más abajo en este mismo archivo. Allí podemos ver que la función, toma el texto que le pasa la plantilla de Twig, y lo formatea tal como se ve en la función. Devolviendo el texto formateado a la plantilla de Twig. Como quiero que Twig ejecute este valor como código HTML, agrego el parámetro raw ala llamada desde Twig. Rcuérdese que la función completa tal como es llamada desde la plantilla de Twig era: {{ poner_h1 (‘Nuevo Docente’) | raw}}

El segundo ejemplo, es una función PHP que me permite poner una fecha detallada en una plantilla Twig, de manera que se muestre el nombre del día, el nombre del mes y el año, junto con la hora, todo eso en español, tal como se ve en la imagen de más abajo. Entonces debo convertir la función que hace esta tarea en PHP pero que muestra los nombres en inglés y pasar esos nombres al español. La función se llama obtener_fecha() y no lleva ningún parámetro, ya que la propia función, toma la fecha y hora actual del sistema y la formatea del modo que se muestra aquí:

fecha

El código que va en la plantilla Twig es:

<div align="center">
<h3>Fecha de impresión: {{ obtener_fecha() }}</h3>
</div>

Y la función está en el archivo AppExtension.php
Y esto es todo. Creo como ejemplos básicos son claros y muestran como se usan y donde se escriben las distintas funciones personalizadas en Symfony 2.8.

Symfony 2.8: Cómo crear y procesar un formulario para múltiples registros de una misma entidad

Introdución

En numerosas ocasiones, surge la necesidad de editar múltiples registros de una misma entidad en un solo formulario. Este asunto tiene su dificultad, ya que Symfony2, está orientado a la idea de trabajar con un registro a la vez de cada entidad. O a lo sumo, con el registro de una entidad, y varios registros de otra entidad relacionada con la primera. Pero no se encuentran ejemplos de edición simultáneas de varios registros de una sola entidad.

El caso que desarrollaré, parte de una entidad llamada «Docentes» donde necesito editar varios registros a la vez, para hacer más ágil el trabajo. El campo a editar será uno solo, se llama «discrecional»  y es de tipo boolean. Los archivos involucrado del sistema Symfony2, son cuatro: docentes.yml, DocentesController.php, DocentesRepository.php y discrecional.html.twig

La ruta

Siempre en Symfony 2.8, debemos crear la ruta. Una de las opciones, que elijo yo, es usar el archivo de extensión yml que corresponda. En mi caso, la entidad sobre la que estoy trabajando se llama «Docentes», y el archivo que contiene todas las rutas relacionadas a esta entidad se llama docentes.yml. Allí procedo a definir la nueva ruta que llamaré «discrecional» y también queda definido el nombre y ubicación del controlador, como se muestra en la imagen siguiente:

form1

El Controlador

Una vez definida la ruta, el paso siguiente es crear el controlador, y aquí surgen varias novedades respecto a lo que conocemos, sobre como construir un formulario en Symfony2. Veamos primero el código y luego lo analizamos.

El archivo de controlador de la entidad «Docentes», se llama «DocentesController.php» y la función que maneja las acciones asociada al formulario que quiero construir, la llamé «discrecionalAction».

public function discrecionalAction(Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $defaultData= $em->getRepository('BackendBundle:Docentes')->buscarDocentesActivos2();

// construimos un  formulario "vacío" sin campos definido
            $form = $this->createFormBuilder($defaultData);

            $form = $form->getForm();

            $form->handleRequest($request);  

   // después del submit              

                if ($form->isSubmitted() && $form->isValid()) {

                $i=0;
                    foreach ($defaultData as $value) {
                         $data2= array('id' =>$request->request->get($defaultData[$i]['id']),
                      'discrecional' =>$request->request->get('D'.$defaultData[$i]['id'])); 

                        if (($request->request->get('D'.$defaultData[$i]['id'])== '0' and $defaultData[$i]['discrecional']=='0') or
                            ($request->request->get('D'.$defaultData[$i]['id'])== NULL and $defaultData[$i]['discrecional']=='1'))
                        {
                         $em->getRepository('BackendBundle:Docentes')->findDocenteFiltId2($data2);
                        }
                        $i=$i+1;
                    }

        return $this->redirectToRoute('docentes_discrecional');
                   }        

          return $this->render('docentes/discrecional.html.twig', array(
                     'docentes' =>$defaultData,
            'form' => $form->createView() ));
    }

Comentamos el código de más arriba. En primer lugar, tal como se muestra en las líneas de código 3 y 4, realizamos una consulta, para obtener el subconjunto de registros que nos interesa editar. Enseguida veremos como se compone esta consulta.

Una vez obtenido los registros que nos interesan, procedemos a construir el formulario. Esto se realiza en las líneas de código de 7 a 11. Lo más extraño, es que aquí no definimos ningún campo a mostrar en el formulario. Es como decirle a Symfony que construya un formulario «vacío». Esto es clave para que puedan editarse varios registros a la vez, ya que si pusiera aquí los campos que quiero visualizar y editar en el formulario, Symfony, solo permitiría aplicarlo a un registro por vez y no a varios registros simultáneamente, como es mi deseo. El trabajo de definir y mostrar los campos, queda reservado para la vista, es decir, el archivo discrecional.html.twig

Después del «submit», una vez que el controlador recibe la información del formulario, procedemos a procesar esa información y deberemos actualizar los registro de la entidad o tabla llamada Docentes. Observense con particular atención las líneas 18 a 26. Allí estamos iterando los datos recibidos del formulario, para actualizar cada registro. Es decir, debemos recorrer todos los registros recibidos del formulario, y actualizar la tabla Docentes con esos datos. Para realizar esa actualización, recurrimos a otra consulta, que será esta vez una consulta de actualización mediante el uso de la función UPDATE (ya lo explicaremos en detalle cuando tratemos las consultas contenidas en el repositorio). Para ganar velocidad y evitar una sobrecarga del servidor, selecciono los registros que realmente se han modificado en el formulario, y solo a esos registros, le aplico la consulta de actualización. Es decir, dentro del «foreach» hay un «if», y solo los registros que cumplen las condiciones, son actualizados.

De las líneas 33 a 35, procedemos a pasar los datos del array $defaultData a la vista que se mostrará a través del archivo dsicrecional.html.twig

La vista

En la vista, es donde hacemos explicíto los campos y registros a editar. Mostramos el código y después lo comentamos.

{% block body %}
{{ form_start(form) }}
{% for docente in docentes %}
Id: <input type="integer" name="{{ docente.id }}" required="required" style="width: 30px" value="{{ docente.id }}" readonly>
Apellido: <input type="text" name="{{ docente.apellido }}" required="required" style="width: 80px" value="{{ docente.apellido }}" readonly>
Nombres: <input type="text" name="{{ docente.nombres }}" required="required" style="width: 80px" value="{{ docente.nombres }}" readonly>
Discrecional: <input type="checkbox" name="D{{ docente.id }}" value="{{ docente.discrecional }}" >
{% endfor %}

<input type="submit" value="Grabar" />
{{ form_end(form) }}

{% endblock %}

Aquí vemos que con los datos recibidos del controlador, Symfony construye la vista del formulario. Vemos que aquí también hacemos una iteración, donde cada «vuelta» de esa iteración me construye un registro. En este caso, los tres primeros campos de cada registro son de solo lectura («readonly») ya que no quiero que se editen aquí. Están para identificar el registro. El único campo que me interesa editar es el campo boolean «discrecional». Preste atención a como está construido el nombre de cada campo de manera de tener un nombre único por cada registro y campo. Esto es fundamental para poder luego procesar la información que el formulario devuelve al controlador, una vez que el usuario hace un clic en el botón «Grabar» («submit»).

Las funciones del repositorio

 Dije antes que usabámos dos funciones ubicadas en el repositorio «DocentesRepository.php». La primer función, es una consulta que me devuelve un subconjunto de la entidad Docentes y lo llamé «buscarDocentesActivos2()», su código es :

 public function buscarDocentesActivos2()
    {
        
        $fields = array('d.id', 'd.apellido', 'd.nombres', 'd.discrecional');

    $query = $this->getEntityManager()->createQueryBuilder();
        $query
            ->select($fields)
            ->from('BackendBundle:Docentes', 'd')
           ->where('d.activo=true')
           ->orderBy('d.apellido, d.nombres');     

        $consulta = $query->getQuery()->getResult();
        
        return $consulta;
    }

Obsérvese que definimos un array $fields con los cuatro campos que me interesan (la entidad es más grande y tiene 17 campos). Luego devolvemos los resultados al controlador, y con esos datos se construirá el formulario.
La segunda función que está en el repositorio, se llama «findDocenteFiltId2($filtro)». Aquí está su código:

public function findDocenteFiltId2($filtro)
    {

     if (is_null($filtro['discrecional'])){ 
         $discrec= '0';
     };
     
     if ($filtro['discrecional']=='0'){ 
         $discrec= '1';
     };
     
     $em = $this->getEntityManager();

        $consulta = $em->createQuery('
            UPDATE BackendBundle:Docentes d
            SET d.discrecional = :disc
            WHERE d.id = :idver
        ');
            
       $consulta->setParameters(array(
      
        'idver' => $filtro['id'],
        'disc'  => $discrec,     
            ));
          return $consulta->getArrayResult();
     
    }   

Esta función, la usamos para actualizar nuestra tabla Docentes. Recibe del controlador, un array llamado $filtro, que contiene los datos de dos campos. El valor del campo «id» que nos perimitirá encontrar de manera inequívoca el registro que queremos actualizar (UPDATE). El otro campo es «discrecional» con su nuevo valor. A esta función solo llegan los registros que efectivamente se han modificado. La consulta permite cargar el nuevo valor de «discrecional» de acuerdo a lo recibido del controlador. Las líneas 4 a 10, transforman los datos del campo «discrecional» en un valor equivalente, para que puedan ser interpretados por la consulta.
La lógica de la actualización se muestra en la tabla siguiente. Hay cuatro casos posibles:

Condición del registro Valor antes del «submit» Valor después del «submit»
No hay cambios en «discrecional» Si está marcado, tiene el valor «1» Al no cambiar, sigue teniendo el valor «1»
No hay cambios en «discrecional» Si está desmarcado, tiene el valor «cero» Aunque su valor no cambie, después del «submit» el formulario le asigna el valor NULL en lugar de «cero»
Registro editado El valor antes del «submit» era «desmarcado» o sea «cero» El valor después del «submit» aunque ahora sea «marcado», no devuelve «1» sino de nuevo «cero»!
Registro editado El valor antes del «submit», era «marcado» o sea «1» El valor después del «submit» será NULL y no «cero»

Conociendo estos comportamientos de Symfony al procesar el formulario, hacemos un filtro en el controlador, donde mediante el «if» determinamos si estamos en el caso de la tercera o cuarta fila de la tabla de más arriba. En ese caso, el controlador, envía la información con los cambios, al repositorio, más especifícamente a la función «findDocenteFiltId2($filtro)», los datos del registro que debe actualizarse con UPDATE.

Symfony 2.8: Cómo agregar un campo a una tabla ya existente

Introducción

Suele ocurrir que después de crear una base de datos con sus tablas, nos demos cuenta que necesitamos modificar una de las tablas, para agregar un campo nuevo no previsto originalmente.
Hacer esto, requiere de varios pasos que paso a explicar.

Primer paso: Modificar la tabla

Yo utilizo phpAdmin y bases de datos MySQL. Ingresamos a phpMyAdmin, buscamos la tabla a modificar (en mi caso, se llama docentes). Vemos la estructura de la tabla docentes antes de su modificación en la fiura siguiente (la tabla es más grande que lo que muestra la imagen, ya que comprende 26 campos que no entran completos en la imagen):
campo1

A esta tabla, le voy a agregar un campo de tipo Boolean llamado discrecional.

 

Segundo paso: Modificar la entidad

Debemos modificar en el código, la entidad donde se define la tabla en Symfony 2.8. En mi caso, el archivo se llama Docentes.php y se ubica en la carpeta: src/BackendBundle/Entity
Procedemos a agregar el nuevo campo y sus métodos get y set al archivo Docentes.php, como muestran las dos figuras siguientes:

campo3

campo4
Dependiendo de como se haya creado la base de datos con sus tablas, quizás se haya creado un archivo de doctrine con extensión xml. En mi caso, se llama Docentes.orm.xml y se encuentra ubicado en la carpeta que muestra la figura siguiente:

campo5

Agregamos la nueva línea que suministra información del nuevo campo (destacado en recuadro rojo en la imagen siguiente):

campo6

Tercer paso: Modificar los formularios

Por supuesto, debemos incorporar estos datos a los archivos PHP que crean los formularios para dar de alta y modificar la entidad Docentes, agregando el campo nuevo.

En este caso, editamos el archivo DocentesType.php ubicado en: src/BackendBundle/Form  Agregamos la línea:  ->add(‘discrecional’)

 

Cuarto paso: Modificar las vistas

Debemos ahora introducir los cambios en los archivos Twig donde necesitamos que este campo aparezca. En mi caso son los siguientes formularios:

  • new.html.twig
  • edit.html.twig
  • show.html.twig

Quinto paso: Limpiar la cache

Siempre es conveniente, cuando hacemos modificaciones de este tipo, limpiar la cache de Symfony.

Desplegar un proyecto Symfony 1.4 en hosting compartido: El problema de las direcciones relativas

Un proyecto desarrollado con Symfony, debería desplegarse en un servidor dedicado o al menos en un VPS, si el tráfico del sitio lo amerita. Un servidor dedicado o un VPS nos permite además afinar la configuración para un mejor desempeño de Symfony.

Si por el contrario, tenemos un proyecto desarrollado con Symfony que no tendrá demasiado tráfico y no requiere ajustes especiales en la configuración del servidor, podemos alojarlo en un hosting compartido. Aunque son más lentos, tiene un costo mucho menor y necesitan de menos conocimientos de configuración del servidor. Yo he desarrollado con Symfony 1.4, una extranet que tiene cierta complejidad pero escaso tráfico. La he alojado en un servidor compartido sin ningún problema de funcionamiento.

Nuestros sistemas desarrollados con Symfony 1.4 y alojados en nuestro localhost, tienen como carpeta pública predeterminada a una de nombre “web”. Cuando vamos a desplegar un proyecto desarrollado con Symfony 1.4 en un hosting compartido, nos encontraremos con una carpeta pública predeterminada con un nombre que puede ser distinto al asignado por Symfony, por ejemplo “public_html”. Cambiar el nombre de la carpeta pública en Symfony no es problema, ya que todo el sistema de Symfony se desarrolla con direcciones relativas. Ver figura siguiente.

localhost1
Figura 1: Organización de las carpetas de un proyecto con Symfony 1.4, donde se cambia el nombre de la carpeta pública

A mi juicio, otra cuestión importante, para facilitar el mantenimiento del sistema, es crear una carpeta propia, por encima de la carpeta pública, donde alojemos a todo el sistema de carpetas de Symfony 1.4, que no son públicas. Evitamos así que se mezclen con las demás carpetas propias del servidor.  Nuestras actualizaciones del sistema serán más sencillas y prolijas de esta manera. Ver la Figura 2. Allí se destacan, recuadradas en rojo, dos carpetas. La carpeta «public_html» es la carpeta pública del servidor y equivale a la carpeta original de Symfony llamada «web». La otra carpeta que se recuadra en la Figura 2, es  «portaldeconflictos». En esta carpeta pondré todo el sistema desarrollado con Symfony (ver Figura 4). En la figura 4, puede verse también la carpeta «public_html» que después debo mover a su lugar correcto. También he creado por mi cuenta una carpeta llamada «backup_portal» cuyo uso ahora no es necesario explicar. Todas las demas carpetas y archivos que se ven en la Figura 2, son propios del servidor remoto y es conveniente no tocarlos. En la Figura 3, se puede ver la misma estructura, capturada desde el Panel de Control del servidor remoto.

hosting remoto
Figura 2: Organización de carpetas del servidor remoto
hosting remoto3
Figura 3: Vista desde el  Panel de Control. Organización de carpetas del servidor remoto
hosting remoto7
Figura 4: Vista del contendio de la carpeta «portaldeconflictos» con todo el sistema Symfony

Cuando tenemos esta estructura de carpetas, surge un problema: debemos cambiar algunas direcciones del sistema Symfony 1.4, para que este siga funcionando, ya que hemos alterado la estructura relativa de carpetas de Symfony 1.4 en el servidor remoto. Hay tres archivos críticos para considerar, que deben ser modificados para que Symfony se pueda adaptar a la nueva estructura y seguir funcionando sin problemas. Esos archivos son:

  • fronted_dev.php (alojado en la carpeta  «public_html»)
  • index.php (alojado en la carpeta  «public_html»)
  • ProjectConfiguration.class.php (alojado en la carpeta  “config”)

Los cambios que hay que realizar en cada uno de estos archivos, se muestran en las imágenes siguientes. En todos los casos se trata de transformar direcciones relativas en absolutas.

hosting remoto4

hosting remoto5

hosting remoto6

Los comentamos brevemente. En las tres imágenes anteriores, correspondientes a los tres archivos del sistema que debemos modificar, al cambiar la estructura de carpetas del sistema Symfony 1.4, se ha recuadrado en rojo la línea que debe ser modificada, donde cambiamos las direcciones relativas de Symfony 1.4, por direcciones absolutas. Como en nuestro servidor remoto, el directorio raíz es «/home/portalde/» escribimos como dirección absoluta a modificar en los  archivos  «frontend_dev.php» e «index.php» (ver figuras de arriba):

require_once(‘/home/portalde/portaldeconflictos/config/ProjectConfiguration.class.php’);

En el archivo «ProjectConfiguration.class.php» cambiamos la línea correspondiente a:

require_once ‘/home/portalde/portaldeconflictos/lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php’;

En las imagenes de los tres archivos,  se ven unos recuadros verdes, que corresponden a líneas que deben cambiarse también, cuando desplegamos un proyecto desarrollado con Symfony 1.4.

Y esto todo, solo basta probar que el sistema funciona adecuadamente.

Desplegar un proyecto de Symfony 2.8 en un servidor Linux: el problema de los permisos

Desplegar (deploy) un proyecto desarrollado con Symfony 2.8 requiere algunas precauciones que si no los tenemos en cuenta, nos complicarán la puesta en producción del sistema.

Supuestos:

1) Cuento con un servidor remoto VPS o dedicado. En mi caso, utilizo un VPS con CentOS Linux 7.3.1611
2) Tengo por lo tanto, acceso a todas las carpetas del sistema del servidor remoto.

Problema:

Cuando tenemos desarrollado un proyecto Symfony 2.8 y queremos subirlo a algún servidor Web remoto para ver como se comporta en modo de producción, suelen surgir una serie de problemas con los permisos en carpetas en las que Symfony debe escribir. Estas carpetas son: cache, logs y spool, que se encuentran a su vez, dentro de la carpeta app del sistema de Symfony (ver imagen).

permisos1
Carpeta app en el servidor local

Las tres carpetas deben poder ser accedidas por Symfony en forma lectura y escritura. El sitio oficial de Symfony sostiene que estas carpetas no deben ser subidas porque Symfony las creará por su cuenta. Pero el problema que surge a menudo, es que Symfony las crea sin los permisos adecuados y luego no las puede escribir haciendo que el sistema falle y aparezca la temida página en blanco.

Solución:

Mi consejo es que Usted proceda a crear estas carpetas en forma manual, la primera vez que suba el sistema al servidor remoto, y las dote de permisos de lectura y escritura, a las carpetas y a todos los archivos que se vayan a crear en ellas, accediéndolas con algún “File Manager”. El código de permisos que hay que asignarles a las carpetas cache, logs y spool es: 0777 (ver imagen de abajo). Por supuesto, debemos asegurarnos que las sub-carpetas, tengan los mismos permisos. Así cache, incluye la carpeta prod y spool incluye la carpeta default
Con esta medida, se ahorrará muchos dolores de cabeza, que no son por deficiencias de Symfony, pero que muchas veces no permiten que los sistemas desarrollados con Symfony, funcionen correctamente.

permisos2
las carpetas logs, cache y spool en el servidor remoto

Un libro fabuloso para aprender Symfony 2.8

El programador español Javier Eguiluz, una de las personas que más sabe en el mundo sobre Symfony, ha sido el primero en escribir un libro completo sobre Symfony2. Se titula: «Desarrollo web ágil con Symfony2″¡Además está en idioma español!. Ahora se encuentra actualizado a la versión Symfony 2.8. La versión 2.8 será la última de Symfony2, pero al mismo tiempo contará con soporte por un largo período hasta Noviembre de 2018, por lo que se convertirá seguramente en el standard de programación en Symfony 2.x.

Luego, solo quedará pasarse a Symfony 3.x, si queremos mantenernos actualizados en el ámbito de este poderoso framework para desarrollo de sitios Web basado en PHP. Pero como el mismo Eguiluz lo aclara, el salto de la versión 2.8 a cualquier versión 3.x de Symfony, será mucho más fácil y suave, tanto para el lector como para el escritor, ahora que el libro está actualizado a la última versión de Symfony2.

El libro desarrolla un ejemplo muy realista de una aplicación enteramente escrita con Symfony 2.8, donde aprenderás a programar el Frontend, el Backend, y la Extranet de una aplicación pensada para comercio electrónico.

Como se explica en la web del libro:

Siempre actualizado

Los libros en papel se quedan viejos antes de comprarlos. Este libro te servirá durante años, ya que sus contenidos se actualizan continuamente.

Compatible desde Symfony 2.0 hasta 2.8.

El libro se publica en para Symfony 2.0, 2.1, 2.3, 2.4 y 2.8. La versión para 2.8 ha sido reescrita por completo para seguir las recomendaciones de las aplicaciones Symfony modernas.

Léelo como y donde quieras

Además de leer la versión HTML5 en symfony.es, podrás descargártelo en PDF y ePub para leerlo cómodamente en tu lector de libros electrónicos.

Empieza desde cero

No importa si no sabes nada de Symfony, ya que el libro empieza realmente desde cero. Sólo necesitas conocimientos previos de programación con PHP 5.3.

Práctico

A lo largo del libro se programa una aplicación web real completa. Así no te perderás en explicaciones abstractas o conceptos teóricos. Todo es práctico y todo te servirá para programar tus propias aplicaciones.

Completo

El libro abarca desde conceptos básicos como el enrutamiento y las bases de datos hasta los conceptos más avanzados como las listas de control de acceso y la inyección de dependencias.

 

Los detalles del contenido y la historia del libro pueden verse aquí:

http://symfony.es/noticias/2016/08/29/desarrollo-web-agil-con-symfony-28/

El índice de contenidos se puede consultar aquí:

https://issuu.com/javier.eguiluz/docs/libro-symfony2-indice?backgroundColor=%2523111111

Si lo quieres comprar (y te aconsejo que lo hagas, si de verdad quieres aprender Symfony 2.8), debes contar con una cuenta en PayPal y una tarjeta de crédito asociada. Solo cuesta 10 euros, y el dinero que gastarás se compensa con creces con lo mucho que aprenderás.

Una vez finalizada la compra, te encontrarás con una página similar a la siguiente (se muestra parcialmente) y el libro se enviará a tu cuenta de e-mail con formato PDF. Te aconsejo imprimirlo en papel ya que resulta más práctico para hacer anotaciones y accederlo con más facilidad como material de estudio.

gracias symfony28