Saltar al contenido
Marcos Peña
Menú
  • Acerca de…
Menú

Sustitución del mapeo original de FOSUserBundle en symfony2

Publicada el octubre 23, 2012septiembre 13, 2020 por Marcos
Para un nuevo proyecto en PHP que estamos empezando, hemos decidido utilizar la plataforma symfony2. En el pasado he tenido la suerte de trabajar, disfrutar y aprender con symfony 1.x, gracias a su coherente organización, buen uso del PHP y unos robustos cimientos fundados en una extensa documentación y una vasta comunidad de activos desarrolladores. En agosto del 2011, SensioLabs, la empresa liderada por Fabien Potencier, liberó la versión 2.0 y este septiembre pasado la 2.1 (la versión actual es la 2.1.2). Ya sólo respecto a la 2.0, la 2.1 incluye una serie de cambios importantes, como puede ser la gestión de la instalación y actualización de los bundles mediante composer. Ahora bien, el cambio de verdad, como es de suponer, se hizo al pasar de la serie 1.x a symfony2. Cierto es que siguen manteniendo la arquitectura MVC en su núcleo, pero la estructura de la aplicación cambia sustancialmente, así como la manera de auto-cargar las clases o los comandos de consola y otros puntos más que no vienen al caso ahora. La gran aportación de symfony2 es la nueva organización basada en paquetes (bundles). En symfony2, todo el código de la aplicación vive y ha de vivir dentro de un paquete (aproximadamente equivalente a lo que venía siendo un plugin en symfony1). De modo que ya no se instalan plugins, si no bundles. Y, en realidad, esto hace la vida más sencilla, sobre todo para el mantenimiento de la aplicación, gracias a que están mucho más desacoplados respecto del código que los antiguos plugins. Uno de los bundles estrella de symfony2 es FOSUserBundle, un paquete para gestionar usuarios, algo así como el sfGuardPlugin de symfony 1.x. Este bundle utiliza el ORM Doctrine y viene con un esquema y un mapeo de las clases, predefinidos en una serie de archivos. De ahí que nos podamos encontrar con un pequeño escollo al intentar cambiar alguna propiedad de las clases mapeadas o el nombre de un tabla, en caso de querer, por ejemplo, adaptar el mapeo a una base de datos heredada. Obviamente no podemos cambiarlo directamente en el bundle de FOSUserBundle, pues los cambios quedarían sobrescritos en la siguiente actualización del bundle. Además, ninguno de los proyectos de Doctrine permite actualmente sobrescribir parte de la asignación de una superclase mapeada en una entidad hijo. ¿Cómo proceder entonces si, por ejemplo, quiero quitar la clave única de una columna? La gente de FOSUserBundle no son muy locuaces al respecto, pero algo de información puedes encontrar en su página de github. Básicamente dicen que hay que volver a escribir el mapeo de la superclase mapeada, que la entidad ha de extender directamente a FOS\UserBundle\Model\User y aconsejan que se respeten todos los campos asignados en el bundle por lo que pueda pasar en futuras actualizaciones. Con la poca información proporcionada (tampoco he encontrado ningún ejemplo que pudiera guiarme), y después de pelearme un ratito, he llegado a la conclusión que básicamente estos son los ficheros que hay que tocar.
  1. /src/Application/MiSuperAPP/UserBundle/Entity/User.php
  2. /src/Application/MiSuperInvento/UserBundle/Entity/Group.php
  3. /src/Application/MiSuperInvento/UserBundle/Resources/config/doctrine/User.orm.xml
  4. /src/Application/MiSuperInvento/UserBundle/Resources/config/doctrine/Group.orm.xml
En el primer archivo hay que sustituir el alias del BaseUser en el use utilizado para importar la clase base de User
1
2
3
4
5
namespace Application\MiSuperInvento\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
 
class User extends BaseUser implements UserInterface
{ ..
por
1
2
3
4
5
6
namespace Application\MiSuperInvento\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Sonata\UserBundle\Model\UserInterface;
 
class User extends BaseUser implements UserInterface
{ ...
Luego hay que traerse todas las propiedades y métodos de la clase /vendor/sonata-project/user-bundle/Sonata/UserBundle/Model/User.php y añadirlas a la clase de la entidad User de nuestra aplicación.
Nótese que, en nuestro caso, hemos utilizado el FOSUserBundle integrado en el bundle de sonata. En caso de utilizar el bundle sin sonata, la ruta sería: /vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Model/User.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
namespace Application\MiSuperInvento\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Sonata\UserBundle\Model\UserInterface;
 
class User extends BaseUser implements UserInterface
{
 
    /**
* @var \DateTime
*/
    protected $createdAt;
 
    /**
* @var \DateTime
*/
    protected $updatedAt;
...
/
* Sets the creation date
*
* @param \DateTime|null $createdAt
*/
    public function setCreatedAt(\DateTime $createdAt = null)
    {
        $this->createdAt = $createdAt;
    }
 
    /**
* Returns the creation date
*
* @return \DateTime|null
*/
    public function getCreatedAt()
    {
        return $this->createdAt;
    }
...
}
Después hacemos exactamente lo mismo con la entidad Group, teniendo en cuenta que donde pone user hay que poner group; por ejemplo en la entidad Group
1
2
3
4
namespace Application\MiSuperInvento\UserBundle\Entity;
use FOS\UserBundle\Model\Group as BaseGroup;
class Group extends BaseGroup implements \FOS\UserBundle\Model\GroupInterface
{ ...
Los siguientes ficheros que tenemos que modificar son los XML donde se define la asignación del esquema de la base de datos respecto al modelo de clases:
  • /src/Application/MiSuperInvento/UserBundle/Resources/config/doctrine/User.orm.xml
  • /src/Application/MiSuperInvento/UserBundle/Resources/config/doctrine/Group.orm.xml
Estos archivos son fundamentales a la hora actualizar la base de datos a partir del modelo ( php app/console doctrine:schema:update --force), pues los campos que no estén definidos no se replicarán en la base de datos y viceversa. El fichero /src/Application/MiSuperInvento/UserBundle/Resources/config/doctrine/User.orm.xml es el que va a tener en cuenta la entidad de nuestra aplicación para las asignaciones del ORM:
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                 http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\MiSuperInvento\UserBundle\Entity\Group" table="fos_user_group">
 
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
</entity>
</doctrine-mapping>
¿Y dónde se encuentra el resto de propiedades de nuestro modelo? Un sitio interesante para ir a echar un vistazo es en /vendor/sonata-project/user-bundle/Sonata/UserBundle/Resources/config/doctrine/User.orm.xml
Recuerda que, en caso de no utilizar el bundle de sonata, la ruta sería: /vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Resources/config/doctrine/User.orm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
 
    <mapped-superclass name="FOS\UserBundle\Entity\User">
 
        <field name="username" column="username" type="string" length="255" />
 
        <field name="usernameCanonical" column="username_canonical" type="string" length="255" unique="true" />
 
        <field name="email" column="email" type="string" length="255" />
 
        <field name="emailCanonical" column="email_canonical" type="string" length="255" unique="true" />
        <field name="enabled" type="boolean" column="enabled" nullable="false"/>
        <field name="salt" type="string" column="salt" length="255" nullable="false"/>
        <field name="password" type="string" column="password" length="255" nullable="false"/>
...
 
    </mapped-superclass>
 
</doctrine-mapping>
En este fichero se define el mapeo de la superclase. Como en los primeros pasos, cambiamos las entidades /src/Application/MiSuperAPP/UserBundle/Entity/User.php y de /src/Application/MiSuperInvento/UserBundle/Entity/Group.php para que no herederan de la superclase, ahora sólo tenemos que añadir las propiedades que nos faltan de /vendor/sonata-project/user-bundle/Sonata/UserBundle/Resources/config/doctrine/User.orm.xml. Con lo que nuestro fichero User.orm.xml quedaría así:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
 
    <entity name="Application\MiSuperIvento\UserBundle\Entity\User" table="fos_user_user">
        <id name="id" type="integer" column="id">
            <generator strategy="IDENTITY"/>
        </id>
        <field name="username" type="string" column="username" length="255" nullable="false"/>
        <field name="usernameCanonical" column="username_canonical" type="string" length="255"/>
        <field name="email" type="string" column="email" length="255" nullable="false"/>
        <field name="emailCanonical" column="email_canonical" type="string" length="255" />
        <field name="enabled" type="boolean" column="enabled" nullable="false"/>
        <field name="salt" type="string" column="salt" length="255" nullable="false"/>
        <field name="password" type="string" column="password" length="255" nullable="false"/>
...
    </entity>
</doctrine-mapping>
Seguimos los mismos pasos con Group.orm.xml y ya estamos listos para poder modificar nuestro esquema y modelo sin perjuicio de futuras actulizaciones. Por ejemplo, en este caso he quitado la clave única de emailCanonical y usernameCanonical. De modo que, después de ejecutar php app/console doctrine:schema:update --force, los cambios se ven reflejados en la base de datos. Por último recordar que, a partir de ahora, los cambios en el esquema han de ser modificados en el User.orm.xml de la aplicación y los del modelo en el User.php de la entidad de la aplicación.

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Artículos

  • abril 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • junio 2021
  • mayo 2021
  • abril 2021
  • marzo 2021
  • febrero 2021
  • enero 2021
  • diciembre 2020
  • noviembre 2020
  • octubre 2020
  • septiembre 2020
  • agosto 2020
  • julio 2020
  • junio 2020
  • mayo 2020
  • abril 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • diciembre 2019
  • noviembre 2019
  • octubre 2019
  • septiembre 2019
  • agosto 2019
  • julio 2019
  • junio 2019
  • mayo 2019
  • abril 2019
  • marzo 2019
  • febrero 2019
  • enero 2019
  • noviembre 2018
  • octubre 2018
  • julio 2016
  • mayo 2016
  • abril 2016
  • agosto 2015
  • febrero 2014
  • junio 2013
  • febrero 2013
  • noviembre 2012
  • octubre 2012
  • septiembre 2012
  • abril 2012
  • enero 2012

Categorías

  • Cómo
  • Consejos
  • Hacks
  • Sin sentido
  • Tutorial

Etiquetas

apache API aws cache Centos Codeigniter EAC firefox flash freebsd freenas gmail Google guacamole java Javascript jQuery kubuntu Linux mysql nas4free nginx php plesk postfix python react rtorrent Seguridad sftp sonata-admin spring spring-boot sql ssh ssl symfony symfony2 symfony4 thymeleaf ubuntu vnc wget windows wine

Entradas recientes

  • Confirmación antes de apagar
  • cURL error 60: SSL certificate problem: unable to get local issuer certificate
  • Oracle JDK 7 is NOT installed.
  • ssh: connect to host: Connection refused
  • Restringir acceso a un bucket de AWS s3 por IP

Comentarios recientes

  • Marcos en Deobbing flash
  • Irosales en Deobbing flash
  • Instalación certificado SSL de un vendedor – Marcos Peña en Instala un certificado SSL en tres pasos
  • gerMdz en Cómo instalar un certificado letsencrypt para un sitio gestionado por Cloudflare
  • Jose Olalla en Cómo ampliar el espacio en disco en 1and1

Archivos

  • abril 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • junio 2021
  • mayo 2021
  • abril 2021
  • marzo 2021
  • febrero 2021
  • enero 2021
  • diciembre 2020
  • noviembre 2020
  • octubre 2020
  • septiembre 2020
  • agosto 2020
  • julio 2020
  • junio 2020
  • mayo 2020
  • abril 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • diciembre 2019
  • noviembre 2019
  • octubre 2019
  • septiembre 2019
  • agosto 2019
  • julio 2019
  • junio 2019
  • mayo 2019
  • abril 2019
  • marzo 2019
  • febrero 2019
  • enero 2019
  • noviembre 2018
  • octubre 2018
  • julio 2016
  • mayo 2016
  • abril 2016
  • agosto 2015
  • febrero 2014
  • junio 2013
  • febrero 2013
  • noviembre 2012
  • octubre 2012
  • septiembre 2012
  • abril 2012
  • enero 2012

Categorías

  • Cómo
  • Consejos
  • Hacks
  • Sin sentido
  • Tutorial

Meta

  • Acceder
  • Feed de entradas
  • Feed de comentarios
  • WordPress.org
© 2022 Marcos Peña | Funciona con Minimalist Blog Tema para WordPress