## Día 5, Bienes Raíces-Poo: Herencia para tener una clase Active Record
Ahora te voy a pedir que con lo aprendido hagas la clase Vendedores pero si te das cuenta va a haber funciones que vas a tener que reescribir solo cambiando el nombre de la tabla por ejemplo:
```
public static function all() {
$query = "SELECT * FROM propiedades";
$resultado=self::consultarSQL($query);
return $resultado;
}
```
```
public static function all() {
$query = "SELECT * FROM vendedores";
$resultado=self::consultarSQL($query);
return $resultado;
}
```
Hemos hecho un poco de trampa por ejemplo en:
```
public function guardar(){
//Sanitizar los datos
$atributos=$this->sanitizarAtributos();
//insertar en la base de datos
$query = "INSERT INTO propiedades (";
$query.=join(',', array_keys($atributos));
$query.=" ) VALUES ('";
$query.=join("' , '",array_values($atributos));
$query.= "')";
$resultado=self::$db->query($query);
return $resultado;
}
```
Porque cuando la escribimos ya estábamos pensando en la este paso y que fuera reutilizable pasando los mismos atributos de la clase al método...pero era la idea desde el principio.
Vamos a crear la clase ActiveRecord para que todas las demás hereden de ella todo lo que tengan en común.
Movemos todo el código de la clase Propiedades a la clase ActiveRecord y dejamos la clase Propiedad como sigue:
```
<?php
namespace App;
class Propiedad extends ActiveRecord{
}
```
Con la clase Propiedad vacía pero heredando de ActiveRecord sigue funcionando todo...lógico verdad?
Necesitamos modificar el ActiveRecord para que actúe distinto dependiendo del objeto hijo.
Por ejemplo cambiamos el método all como sigue:
```
public static function all() {
$query = "SELECT * FROM ".self::$tabla;
$resultado=self::consultarSQL($query);
return $resultado;
}
```
Y en la clase Propiedad definimos:
```
class Propiedad extends ActiveRecord{
protected static $tabla = 'propiedades';
}
```
Si intentas ejecutar esto y pones un debuguear a la query generada verás que da error, no aparece el dato self::$tabla correctamente porque el self se refiere a la misma clase, ActiveRecord.
Para estos casos necesitamos el modificador de acceso static:
```
public static function all() {
$query = "SELECT * FROM ".static::$tabla;
$resultado=self::consultarSQL($query);
return $resultado;
}
```
Con static buscará el atributo en la clase heredera! Así que vamos a modidificar todo el código de ActiveRecord para que todos los self se cambien por static, siempre se va a referir a la clase que hereda.
También vamos a modificar en ActiveRecord donde se referencie la tabla propiedades para que se modifique por el texto static::$tabla .
Cuando hacemos el constructor y la declaración de atributos no se puede generalizar así que así quedaría por ahora la clase Propiedad.php:
```
<?php
namespace App;
class Propiedad extends ActiveRecord{
protected static $tabla = 'propiedades';
protected static $columnasDB = ['id', 'titulo', 'precio', 'imagen', 'descripcion', 'habitaciones', 'wc', 'estacionamiento', 'creado', 'vendedores_id'];
public $id;
public $titulo;
public $precio;
public $imagen;
public $descripcion;
public $habitaciones;
public $wc;
public $estacionamiento;
public $creado;
public $vendedores_id;
public function __construct($args = [])
{
$this->id = $args['id'] ?? null;
$this->titulo = $args['titulo'] ?? '';
$this->precio = $args['precio'] ?? '';
$this->imagen = $args['imagen'] ?? 'imagen.jpg';
$this->descripcion = $args['descripcion'] ?? '';
$this->habitaciones = $args['habitaciones'] ?? '';
$this->wc = $args['wc'] ?? '';
$this->estacionamiento = $args['estacionamiento'] ?? '';
$this->creado = date('Y/m/d');
$this->vendedores_id = $args['vendedores_id'] ?? '';
}
public function validar(){
if (!$this->titulo) {
self::$errores[] = 'Debes añadir un Titulo';
}
if (!$this->precio) {
self::$errores[] = 'El Precio es Obligatorio';
}
if (strlen($this->descripcion) < 50) {
self::$errores[] = 'La Descripción es obligatoria y debe tener al menos 50 caracteres';
}
if (!$this->habitaciones) {
self::$errores[] = 'La Cantidad de Habitaciones es obligatoria';
}
if (!$this->wc) {
self::$errores[] = 'La cantidad de WC es obligatoria';
}
if (!$this->estacionamiento) {
self::$errores[] = 'La cantidad de lugares de estacionamiento es obligatoria';
}
if (!$this->vendedores_id) {
self::$errores[] = 'Elige un vendedor';
}
if (!$this->imagen) {
self::$errores[] = 'Imagen no válida';
}
return self::$errores;
}
}
```
Y así la ActiveRecord:
```
<?php
namespace App;
class ActiveRecord{
// Base DE DATOS
protected static $db;
protected static $tabla = '';
protected static $columnasDB = [];
protected static $errores=[];
public static function setDB($database){
self::$db=$database;
}
public static function all() {
$query = "SELECT * FROM ".static::$tabla;
$resultado=self::consultarSQL($query);
return $resultado;
}
public function guardar(){
//Sanitizar los datos
$atributos=$this->sanitizarAtributos();
//insertar en la base de datos
$query = "INSERT INTO ".static::$tabla ." (";
$query.=join(',', array_keys($atributos));
$query.=" ) VALUES ('";
$query.=join("' , '",array_values($atributos));
$query.= "')";
$resultado=static::$db->query($query);
return $resultado;
}
//identifica y une los atributos de la bd con sus valores en forma de vector
public function atributos(){
$atributos=[];
foreach(static::$columnasDB as $columna){
if ($columna==='id') continue;
$atributos[$columna]=$this->$columna;
}
return $atributos;
}
public function sanitizarAtributos(){
$atributos=$this->atributos();
$sanitizado=[];
//este vector se recorre como asociativo
foreach ($atributos as $key=>$value){
$sanitizado[$key]= static::$db->escape_string($value);
}
return $sanitizado;
}
//Validaciones
public static function getErrores(){
return static::$errores;
}
public function setImagen($imagen){
if ($imagen){
$this->imagen=$imagen;
}
}
public static function consultarSQL($query){
//Consultar la base de datos
$resultado=self::$db->query($query);
//iterar los resultados
$array=[];
while ($registro=$resultado->fetch_assoc()){
$array[]=self::crearObjeto($registro);
}
//liberar la memoria
$resultado->free();
//devolver resultados
return $array;
}
protected static function crearObjeto($registro){
$objeto=new static;
foreach ($registro as $key =>$value){
if (property_exists($objeto,$key)){
$objeto->$key=$value;
}
}
return $objeto;
}
}
```
Te atreverías a:
- intentar hacer el método de eliminar?
- empezar a hacer el crud de vendedores siguiendo este paradigma.Al menos visualizar y crear.