Php orientado a objetos, parte 4: Métodos getters y setters

Ok, en mi posteo anterior, Php orientado a objetos, parte 3: Niveles de acceso, hablamos sobre los niveles de acceso public y private, y mencioné que las propiedades deberían ser de tipo private para evitar que accidentalmente se acceda las mismas ya sea recuperando su valor o modificándolas.

Ahora bien, ¿qué pasa si nosotros tenemos la necesidad de recuperar el valor de una propiedad o cambiar su valor? ¿La convertimos en public? Podría ser una solución a simple vista, pero no, las propiedades deberían ser siempre private.

Para solucionar dicho problema existen los métodos getters y setters.

Los métodos getters son aquellos que nos devuelven los valores de las propiedades. Por lo general estos métodos no reciben parámetros y deben devolver algo, osea tener un return. Si bien cada uno de estos métodos suele crearse para devolver el valor de una sola propiedad hay programadores que utilizan un método que devuelve un array con los valores de las propiedades. En mi caso no hago esto último.

Cambiaremos un poco de clase, ya que hace tres posteos que vengo con la misma Persona. En esta ocasión crearemos una clase llamada Producto que tendrá cuatro propiedades: un id, un nombre, una descripción y el precio:

<?php 
 class Producto { 
    private $id;
    private $nombre;
    private $descripcion;
    private $precio; 
    public function __construct($id, $nombre, $descripcion, $precio) {
       $this->id = $id;
       $this->nombre = $nombre;
       $this->descripcion = $descripcion;
       $this->precio = $precio;
    } 
 } 
?>

Nada, nuevo, propiedades y un constructor en donde se definen los mismos.

Ahora supongamos que yo necesito recuperar el nombre del producto desde el objeto, para eso dentro de la clase crearé un nuevo método con este aspecto:

public function get_nombre(){
   return $this->nombre;
}

Facíl, muy fácil. Ahora ¿qué es un método setters?

Los métodos setters son aquellos que permiten modificar el valor de una propiedad. Por lo general estos reciben un parámetro con el nuevo valor de la propiedad y no devuelven nada. Al igual que los getters, estos métodos suelen crearse un por cada propiedad a la cual es posible cambiarle el valor, sin embargo también hay programadores usan uno  para modificar varias propiedades con un array de parámetro. Yo tampoco hago esto último.

Veremos cómo se utliza:

public function set_nombre($nombre){
   $this->nombre = $nombre;
}

Muy fácil. Como vemos el método recibe un parámetro que es el nuevo valor de la propiedad. Entonces, no sólo podemos recuperar el valor de nuestra propiedad, sino también modificarla.

Ahora teniendo en cuenta que ya entendemos la lógica de esto crearé los métodos getters y setters para las demás propiedades:

<?php 
 class Producto { 
    private $id;
    private $nombre;
    private $descripcion;
    private $precio; 
    public function __construct($id, $nombre, $descripcion, $precio) {
       $this->id = $id;
       $this->nombre = $nombre;
       $this->descripcion = $descripcion;
       $this->precio = $precio;
    }
    public function get_nombre(){
       return $this->nombre;
    }
    public function get_descripcion(){
       return $this->descripcion;
    }
    public function get_precio(){
       return $this->precio;
    }
    public function get_id(){
       return $this->id;
    }
    public function set_nombre($nombre){
       $this->nombre = $nombre;
    }
    public function set_descripcion($descripcion){
       $this->descripcion = $descripcion;
    }
    public function set_precio($precio){
       $this->precio = $precio;
    }
 } 
?>

Si es la primera vez que ves esto tal vez te preguntes lo mismo que yo la primera vez que lo vi: ¿Para qué c… esto? ¿No es más fácil que las propiedades sean public?

Bueno, la respuesta es muy simple:

Existe la necesidad de recuperar el valor del nombre, la descripción, el precio y el id del producto. También, el nombre del producto, la descripción y el precio pueden cambiar, por ejemplo si tenemos una aplicación para un negocio que vende artículos de computación y la persona que ingresa el registro se equivoca y debe modificar cosas o simplemente quiere cambiarle el precio al producto. Pero suponiendo el id del producto sea la clave primaria de una base de datos, ¿existiría la posibilidad de modificarlo? NO. Por tanto la propiedad $id tendrá un método getters, mas no un setters.

Si no usáramos métodos getters y setters y dejamos las propiedades como public, entonces esto estaría bien:

echo $producto->id;

Pero esto no:

 $producto->id = 2000;

Por ese motivo, en la clase que creé arriba, si te fijaste bien no hay un método setters, por el simple hecho de que el id no debería ser modificado.

También existe la posibilidad de que una propiedad tenga un método setters y no un getters. De todas formas, ahora sabemos que es recomendable proteger nuestras propiedades con private, y luego de acuerdo a la lógica de cada una crear métodos getters y setters según lo amerite.

Para probar el funcionamiento copiá la clase creada de Producto en un archivo con nombre Producto.php y luego probar esto en tu navegador:

<?php
 require_once 'clases/Producto.php';
 $producto = new Producto(111, 'Pendrive 8', 'Pendrive marca Kingston de 8GB', 150);
 echo 'Id: ' . $producto->get_id() . '<br />';
 echo 'Nombre: ' . $producto->get_nombre() . '<br />';
 echo 'Descripción: ' . $producto->get_descripcion() . '<br />';
 echo 'Precio: $' . $producto->get_precio() . '<br />';
 $producto->set_nombre('Pendrive 16');
 $producto->set_descripcion('Pendrive marca Kingston de 16GB');
 $producto->set_precio(300);
 echo '<hr />';
 echo 'Id: ' . $producto->get_id() . '<br />';
 echo 'Nombre: ' . $producto->get_nombre() . '<br />';
 echo 'Descripción: ' . $producto->get_descripcion() . '<br />';
 echo 'Precio: $' . $producto->get_precio() . '<br />';
?>

Saludos!

Anterior: Php orientado a objetos, parte 3: Niveles de acceso

Siguiente: Php orientado a objetos, parte 5: Constantes


18 Respuestas a “Php orientado a objetos, parte 4: Métodos getters y setters”

  1. Excelente explicacion, voy siguiendo tus tutoriales o capitulos de PHP orientado a objetos y hasta el momento todo me a resultado muy claro.

  2. Gracias nuevamente la estructura de poo es similar en php y java esto me ha ayudado muchísimo, además el método pedagógico me resulta muy apropiado ya que se permite mediante un ejemplo practico la aprehensión del tema. Gracias!

    1. De hecho PHP se ha copiado muchas cosas de Java, vos pensá que PHP a diferencia de Java, no es un lenguaje de programación orientado a objetos, es un lenguaje de programación estructurado que tuvo que adaptarse a los objetos.

      Saludos!

  3. Estimado ! Muy bueno el post. Es de hace unos años pero muy bien explicado.

    Porqué razón no utilizas un array como mencionas que algunos programadores sí pero tú no.

    Qué sucedería si tuvieras que crear un método para acceder a una tabla con más de 20 atributos ?

    Soy programador php pero hace poco salí de lo estructurado.

    Saludos y gracias !

    1. Porque creo que es una forma más amigable. Usar getters y setters para cada atributo, como se suele hacer en Java. Que de hecho es el lenguaje que es inspiró a PHP, en la parte de POO.

      Sinceramente nunca trabajé con una tabla con tantas columnas, es más no me imagino qué tabla, o qué entidad puede llevar a tener tantas columnas.

      Saludos.

      1. Disculpa que me meta… yo tampoco me imagino una tabla con tantas columnas, pero la pregunta es válida, porque yo también quería saber por qué no usabas ese recurso :D.

        Excelente tu explicación, para serte sincero lo habia visto antes en muchos códigos java y no lo entendía, y a decir verdad por ignorancia nunca mostré interés en saber que onda con eso, pero hoy he recibido tremenda lección, no importa que sea del año pasado, de verdad gracias por el tiempo que te has tomado en compartir tu conocimiento.

        Llegué acá porque estoy haciendo mi primer proyecto CRUD con PHP-PDO-PostgreSQL utilizando el patrón MVC sin usar Frameworks de ningún tipo, básicamente quiero entender como funciona la POO en PHP para dar el salto a Laravel.

        Lo cierto es que buscaba información sobre PDO y terminé viendo tus lecciones desde el principio XD. En fin amigo, agradecido por tus lecciones sencillas y concretas, saludos desde Caracas-Venezuela.

  4. Muy interesante el post.
    Tengo una consulta: Trabajo con MVC/PHP/Smarty con patrones DAO y VO.
    En mi base de datos tengo una tabla Prueba que tiene su respectivo PruebaDAO y PruebaVO.
    Y PruebaVO tiene declarados todos los cambios de la tabla de la B.D.
    Los métodos getters y setters me van a permitir declarar o utilizar solamente algunos campos para no utilizar todos?
    Cómo lo haría? Gracias y éxitos.

    1. En el DAO se declaran métodos que son las consultas, mientras que en la segunda va el objeto en sí (los atributos, y los métodos getters, setters y constructor.

      Por ejemplo:

      class Perro {
      private $nombre;
      public function __construct($nombre){}
      public function getNombre(){}
      public function setNombre($nombre){}
      }

      class PerroDao {
      public function insertar($perro){}
      public function modificar($perro){}
      public function eliminar($perro){}
      public function buscar($perro){}
      }

      Saludos!

      1. Y solo por curiosidad es correcto lo que pusiste en el ejemplo?

        public function getNombre(){}
        public function setNombre($nombre){}

        Se puede poner un setter y un getter? Esas funciones al momento de visualizarlo en mi plantilla no debo invocar a una de esas funciones?
        Gracias.

        1. Si es correcto? No entiendo tu pregunta.

          El getter te devuelve el valor de un atributo, y el setter te permite modificar su valor.

  5. Hola esto esta muy interesante, estoy aprendiendo de lo estructurado a POO, recientemente estoy pasando un proyecto de programacion estructurada a POO, por decirte los campos que una tabla tenga como PK o Id y el resto de campos son private los atributos, sin embargo si este mismo campo Id tuviese un Fk en otra tabla mi pregunta es, en el caso que el Id o cualquier otro atributo tenga «herencia» o se usa en otra tabla, entonces este Id seria un protected?.. el atributo y los metodos setter y getter por regla general son publicos pero en caso que sea para ese atributo protected, necesariamente ese metodo debe ser protected?.. gracias.

    1. Yo lo que haría no es guardar el atributo id de la otra tabla, sino el objeto entero.

      Osea que si vos tenés un objeto Usuario, no vas a guardar (a nivel objetos, no base de datos) el id del país, sino el objeto país en sí.

      No sé si me explico, sino hago un ejemplo de dos clases, para que puedas entenderlo.

      Saludos!

  6. Al trabajar con MVC usando DAO y VO, 1) se declara el __construct(){} tanto en el VO y DAO? Y 2) Es necesario declarar el destructor?

    1. 1) Lo declarás si lo necesitás, osea si al momento de instanciar un objeto, necesitás que suceda algo. Perdón, no entiendo muy bien la pregunta.
      2) El destructor se declara, cuando necesitás que al momento de destruirse el objeto, pase algo.

      Saludos!