Evitando los getters y setters en las entitades de Symfony

symfony logo
symfony logo

Es el día y aún no logro entender porque en las clases de symfony de tipo entidad se debe acceder a las propiedades a través de métodos getters y escribir valores a través de setters, nunca encontré un argumento válido para esta notación, pero si lo sabes y puedes iluminarnos, puedes dejar un comentario (estoy seguro que este concepto fue robado de java -.-)

Sé que no todos los métodos de una clase deberían ser visibles al momento de instanciarse, pero en el caso de las entidades en symfony, creo que si se debería poder, para dejar más claro a que me refiero con entidades, explicaré brevemente que es una entidad.

Entitades en symfony les llaman a las clases que mapean directamente una tabla en nuestra base de datos, en algunos otros frameworks esto se llama modelo, por lo tanto se define una clase de la siguiente manera:

<?php
namespace DemoProject\CoreBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="Usuarios")
 */
class UsuariosEntity
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer", options={"unsigned"=true})
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
 
    /**
     * @var int $nombre
     * @ORM\Column(name="nombre", type="string", nullable=false)
     */
    protected $nombre;
}

Lo curioso, para mi obviamente es que recomiendan crear métodos getters y setters si se quiere escribir o acceder a las propiedades de la clase, por lo que ahora se vería de esta manera:

<?php
namespace DemoProject\CoreBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="Usuarios")
 */
class UsuariosEntity
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer", options={"unsigned"=true})
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
 
    /**
     * @var int $nombre
     * @ORM\Column(name="nombre", type="string", nullable=false)
     */
    protected $nombre;
 
    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }
 
    /**
     * @param mixed
     */
    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }
 
    /**
     * @return mixed
     */
    public function getNombre()
    {
        return $this->nombre;
    }
 
    /**
     * @param mixed
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;
        return $this;
    }
}

Y se implementa así:

$usuario = new UsuariosEntity();
$usuario->setId(1);
$usuario->setNombre("Jack");
 
// y para acceder
$id = $usuario->getId();
$nombre = $usuario->getNombre();

Personalmente creo que en una clase de tipo entidad todas las propiedades deberían ser accesibles, pero escribir métodos para setear o tomar valores para cada propiedad en bd con tablas que tienen al menos 10 o más campos es un poco tedioso este proceso, entonces mi propuesta práctica para evitar este tipo de estructuras es utilizar los métodos mágicos de php que nos ahorran básicamente este tipo de trabajo.

Entonces implementando los métodos mágicos en una entidad en symfony, quedaría de la siguiente manera:

<?php
namespace DemoProject\CoreBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="Usuarios")
 */
class UsuariosEntity
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer", options={"unsigned"=true})
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
 
    /**
     * @var int $nombre
     * @ORM\Column(name="nombre", type="string", nullable=false)
     */
    protected $nombre;
 
    /**
     * [__get description]
     * @param  [type] $property [description]
     * @return [type]           [description]
     */
    public function __get($property) 
    {
        if (property_exists($this, $property)) 
        {
            return $this->$property;
        }
    }
 
    /**
     * [__set description]
     * @param [type] $property [description]
     * @param [type] $value    [description]
     */
    public function __set($property, $value) 
    {
        if (property_exists($this, $property)) 
        {
            $this->$property = $value;
        }
 
        return $this;
    }
}

Por lo que ahora al instanciar la clase UsuariosEntity, fácilmente podría acceder a la propiedad id, o establecer su valor escribiendo algo como lo siguiente:

$usuario = new UsuariosEntity();
$usuario->id = 1;
$usuario->nombre = "Jack";
 
// y para acceder
$id = $usuario->id;
$nombre = $usuario->nombre;

Pues ahí está, si hay algo que crees que estoy haciendo mal, es buen momento para decirlo y corregirlo.. de lo contrario, empecemos a escribir código más legible para los demás, no importa si el framework nos recomienda hacerlo siguiendo una notación específica.

Happy Coding! 😀

Co-fundador de Qbit Mexhico, usuario de linux, Developer en tecnologías web.. Nicaragüense, centro en basketball, primer centro en rugby y pintor los fines de semana. Ortögrafo y ambientalista psicológico (de escritorio).. ese soy yo!

Si te ha servido compártelo y difunde nuestro blog..

Twitter LinkedIn Flickr YouTube 

10 thoughts on “Evitando los getters y setters en las entitades de Symfony

  1. No acabo de entender la razón por la cual haces esto.
    Si tu objetivo es ahorrarte código, porque no trabajas con propiedades públicas?
    Esta forma de utilizar los métodos mágicos, a la larga, siempre tiene un impacto negativo en tu proyecto.
    La magia en PHP es algo que uno debe respetar tanto como le sea posible.

    Un saludo.

  2. El uso de accesores se hace mayormente por encapsulamiento, tu metodo es valido pero si necesitaras realizar alguna validación sobre la propierdad (Con PHP 7 esto esto seria mas corto de hacer) la harías en tus setters, cosa que seria mas engorroso utilizando tu forma, forma que es válida también (Yo la utilice un buen tiempo), ademas si quisieras hacer una propiedad no visible o inmutable tendrías que agregarle mas lógica a tus métodos mágicos, cosa que no es mas fácil usando métodos accesores. Para finalizar es solo mi opinión cada desarrollador tiene su estilo de hacer las cosas, solo explico porque me parece mejor la forma que proponen los frameworks. Como dicen en piratas del caribe es mas bien una guía no reglas.

    1. Piero, si es por tema de validaciones, normalmente esas se hacen desde otra clase, siempre he sido de la idea de mantener limpia la clase entidad, pero es bueno conocer diferentes enfoques sobre el desarrollo.

  3. Así podrías modificar el ID por ejemplo de una entidad, porque no puedes controlar cuando una propiedad se puede leer pero no editar.

    No le veo mucho el sentido tampoco.

    1. Miguel, tienes razón.. aunque es difícil que eso ocurra si tienes bien estructurado lógicamente tu código, pero como dije antes.. es interesante conocer cada punto de vista en cuanto a cómo hacemos las cosas.

  4. If you use an IDE like PhpStorm you loose a lot with magic methods coz you don’t have auto complete, type hint and last but not least you cannot easily verify where a method is being used coz everything is behind a proxy method.

    PhpStorm at the same time provides some handy generators to generate getters/setters out of the property defined in your class.

    1. Okay, some IDEs like PhpStorm, Eclipse or Intellij can help, although I personally never use them, I prefer to use flat editors such as sublime, atom or notepadd++.

      Working with IDEs it’s easy definitely, nevertheless you have to add considerable amount of code to configure all the properties. And code using these notation becomes ambiguous as well.

      However Getters/setters I guess violate the open/closed principle, prevent information hiding and should be considered evil (Long version). Using getters and setters allows to decouples the business logic for setting values from the actual storage. Something that object-orientation was suppose to avoid.

      Thanks for commenting Matteo, your point is very valid too 🙂

  5. Hola, interesante articulo, aunque te recomiendo leer un poco de teoria sobre POO en especial la propiedad de encapsulamiento, el que no le veas utilidad no quiere decir que no la tenga 😉

    Tu apreciación es correcta, Symfony se inspira de (toma “prestada”) la metodologia y convenciones de Java (sobre todo Spring). Esa caracteristica es una de las cosas que lo hace tan amigable en comparación a otro Frameworks.

    Por cierto, el uso de getters y setters no es algo recomendado/impuesto/requerido por el framework, que algunos frameworks te permitan no usarlos… bueno… existe basic, no? XDDD (chiste local)

    Saludos y gracias por el articulo.

    1. Gracias Seraf y sí, la teoría de encapsulamiento ayudaría a definir q es público o privado y por qué.. pero en el caso de clases que mapean directamente de una tabla de Bd, creo q deberían evitar ese tipo de asignaciones por métodos creo q por comodidad y practicidad, y ahora q lo recuerdo, solo symfony hace esto 🤔 .. Saludos!!

Responder a Miguel Ángel Martín Cancelar respuesta

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