Php orientado a objetos, parte 12: PDO, Buscar registros en una base de datos

Bueno, continuando con el posteo anterior que publiqué hace poco, Php orientado a objetos, parte 11: PDO, Guardar registros en una base de datos, hoy vamos a aprender como hacer un select mediante PDO.

Repasando un poco lo que vimos, primero creamos una base de datos:

CREATE DATABASE batman;

Luego hicimos una tabla para guardar los personajes de la saga Batman:

CREATE TABLE personaje(
 id tinyint(3) unsigned not null auto_increment primary key,
 nombre varchar(255) not null,
 descripcion text not null
)

Para trabajar con la misma utilizamos dos clases: La clase Conexion que hereda de PDO y permite conectarse a la base de datos y la clase Personaje, con todo lo relacionado a la tabla personaje,  y que además usa la clase Conexion para hacer consultas con la base de datos.

Conexion:

<?php 
 class Conexion extends PDO { 
   private $tipo_de_base = 'mysql';
   private $host = 'localhost';
   private $nombre_de_base = 'batman';
   private $usuario = 'root';
   private $contrasena = ''; 
   public function __construct() {
      //Sobreescribo el método constructor de la clase PDO.
      try{
         parent::__construct("{$this->tipo_de_base}:dbname={$this->nombre_de_base};host={$this->host};charset=utf8", $this->usuario, $this->contrasena);
      }catch(PDOException $e){
         echo 'Ha surgido un error y no se puede conectar a la base de datos. Detalle: ' . $e->getMessage();
         exit;
      }
   } 
 } 
?>

Personaje:

<?php
 require_once 'Conexion.php';
 class Personaje {
   private $id;
   private $nombre;
   private $descripcion;
   const TABLA = 'personaje';
   public function getId() {
      return $this->id;
   }
   public function getNombre() {
      return $this->nombre;
   }
   public function getDescripcion() {
      return $this->descripcion;
   }
   public function setNombre($nombre) {
      $this->nombre = $nombre;
   }
   public function setDescripcion($descripcion) {
      $this->descripcion = $descripcion;
   }
   public function __construct($nombre, $descipcion, $id=null) {
      $this->nombre = $nombre;
      $this->descripcion = $descipcion;
      $this->id = $id;
   }
   public function guardar(){
      $conexion = new Conexion();
      if($this->id) /*Modifica*/ {
         $consulta = $conexion->prepare('UPDATE ' . self::TABLA .' SET nombre = :nombre, descripcion = :descripcion WHERE id = :id');
         $consulta->bindParam(':nombre', $this->nombre);
         $consulta->bindParam(':descripcion', $this->descripcion);
         $consulta->bindParam(':id', $this->id);
         $consulta->execute();
      }else /*Inserta*/ {
         $consulta = $conexion->prepare('INSERT INTO ' . self::TABLA .' (nombre, descripcion) VALUES(:nombre, :descripcion)');
         $consulta->bindParam(':nombre', $this->nombre);
         $consulta->bindParam(':descripcion', $this->descripcion);
         $consulta->execute();
         $this->id = $conexion->lastInsertId();
      }
      $conexion = null;
   }
 }
?>

Esta última clase nos permitía crear un objeto con los datos del personaje y luego por medio de un método guardar() podíamos insertar o modificar un registro dependiendo de si le pasábamos un id o no:

<?php
 require_once 'clases/Personaje.php';
 $persona = new Personaje('Batman', 'Encapuchado, disfrazado de murciélago que sale por las noches a combatir el mal.');
 $persona->guardar();
 echo $persona->getNombre() . ' se ha guardado correctamente con el id: ' . $persona->getId();
?>

Con este código el método guardar() insertaba un nuevo registro ya que nosotros no le pasamos ningún id, si no existe id significa que el registro es nuevo, pero si la propiedad $id no está vacía intentará modificar el registro con dicho valor.

Ahora crearemos un nuevo método que buscará un registro en la base de datos con un id específico con un nuevo método, buscarPorId():

<?php
 require_once 'Conexion.php';
 class Personaje {
    private $id;
    private $nombre;
    private $descripcion;
    const TABLA = 'personaje';
    public function getId() {
       return $this->id;
    }
    public function getNombre() {
       return $this->nombre;
    }
    public function getDescripcion() {
       return $this->descripcion;
    }
    public function setNombre($nombre) {
       $this->nombre = $nombre;
    }
    public function setDescripcion($descripcion) {
       $this->descripcion = $descripcion;
    }
    public function __construct($nombre, $descipcion, $id=null) {
       $this->nombre = $nombre;
       $this->descripcion = $descipcion;
       $this->id = $id;
    }
    public function guardar(){
       $conexion = new Conexion();
       if($this->id) /*Modifica*/ {
          $consulta = $conexion->prepare('UPDATE ' . self::TABLA .' SET nombre = :nombre, descripcion = :descripcion WHERE id = :id');
          $consulta->bindParam(':nombre', $this->nombre);
          $consulta->bindParam(':descripcion', $this->descripcion);
          $consulta->bindParam(':id', $this->id);
          $consulta->execute();
       }else /*Inserta*/ {
          $consulta = $conexion->prepare('INSERT INTO ' . self::TABLA .' (nombre, descripcion) VALUES(:nombre, :descripcion)');
          $consulta->bindParam(':nombre', $this->nombre);
          $consulta->bindParam(':descripcion', $this->descripcion);
          $consulta->execute();
          $this->id = $conexion->lastInsertId();
       }
       $conexion = null;
    }
    public static function buscarPorId($id){
       $conexion = new Conexion();
       $consulta = $conexion->prepare('SELECT nombre, descripcion FROM ' . self::TABLA . ' WHERE id = :id');
       $consulta->bindParam(':id', $id);
       $consulta->execute();
       $registro = $consulta->fetch();
       if($registro){
          return new self($registro['nombre'], $registro['descripcion'], $id);
       }else{
          return false;
       }
    }
 }
?>

El método buscará un personaje por su id, si lo encuentra devolverá un objeto con sus datos guardados en las propiedades correspondientes, pero sino devolverá false.

Ahora analicemos el código.

Creamos una nueva conexión para realizar consultas, nada nuevo:

$conexion = new Conexion();

Escribimos la consulta que buscará un personaje por su id:

$consulta = $conexion->prepare('SELECT nombre, descripcion FROM ' . self::TABLA . ' WHERE id = :id');

Agregamos los valores a la consulta:

$consulta->bindParam(':id', $id);

La ejecutamos:

$consulta->execute();

En la siguiente línea lo que hacemos es guardar la respuesta de la consulta mediante un método llamado fetch():

$registro = $consulta->fetch();

Lo que hace el método fetch() es devolvernos un array asociativo con los datos que le pedimos, en caso de encontrar un resultado (fetch() se usa para consultas que deberían devolver un solo registro) Pero en caso de no encontrar nada nos devolverá false.

Preguntamos si nos devolvió algún resultado. Si así fue retornamos un objeto Personaje con las propiedades $id, $nombre y $descripcion cargadas con sus valores correspondientes. Pero si la consulta no encontró nada con ese id nos devolverá false, osea nada.

if($registro){
   return new self($registro['nombre'], $registro['descripcion'], $id);
 }else{
   return false;
 }

Intenten probarlo con un id que exista en la base de datos. En mi caso el id 1 es Batman:

<?php
 require_once 'clases/Personaje.php';
 $personaje = Personaje::buscarPorId(1);
 if($personaje){
    echo $personaje->getNombre();
    echo '<br />';
    echo $personaje->getDescripcion();
 }else{
    echo 'El personaje no ha podido ser encontrado';
 }
?>

Y ahora que tenemos un objeto creado y recuperado por su id, podríamos cambiarle por ejemplo la descripción mediante el método setDescripcion() y probar si lo modifica correctamente con el método guardar():

<?php
 require_once 'clases/Personaje.php';
 $personaje = Personaje::buscarPorId(1);
 if($personaje){
    $personaje->setDescripcion('En realidad es el millonario Bruno Diaz');
    $personaje->guardar();
    echo 'El personaje ha sido modificado';
 }else{
    echo 'El personaje no ha podido ser encontrado';
 }
?>

Bueno, ahora, si quisiéramos por ejemplo recuperar una lista, en este caso de varios personajes, deberíamos usar el método fetchAll(). Este método a diferencia de fetch() no nos devolverá un array asociativo sino que nos devolverá un array de arrays asociativos.

Ahora insertaremos varios registros a mano para poder probarlo rápidamente esto:

INSERT INTO personaje(nombre, descripcion)
VALUES
('Robin', 'El compañero de Batman'),
('El Guasón', 'El que se ríe'),
('Dos Caras', 'El que tiene dos caras'),
('El Acertijo', 'El de verde con un signo de preguntas'),
('Alfred', 'El mayordomo'),
('Bane', 'El que usa máscara');

El nuevo método para recuperar todos los personajes que se llamará recuperarTodos(). La clase ahora quedará así:

<?php
 require_once 'Conexion.php';
 class Personaje {
    private $id;
    private $nombre;
    private $descripcion;
    const TABLA = 'personaje';
    public function getId() {
       return $this->id;
    }
    public function getNombre() {
       return $this->nombre;
    }
    public function getDescripcion() {
       return $this->descripcion;
    }
    public function setNombre($nombre) {
       $this->nombre = $nombre;
    }
    public function setDescripcion($descripcion) {
       $this->descripcion = $descripcion;
    }
    public function __construct($nombre, $descipcion, $id=null) {
       $this->nombre = $nombre;
       $this->descripcion = $descipcion;
       $this->id = $id;
    }
    public function guardar(){
       $conexion = new Conexion();
       if($this->id) /*Modifica*/ {
          $consulta = $conexion->prepare('UPDATE ' . self::TABLA .' SET nombre = :nombre, descripcion = :descripcion WHERE id = :id');
          $consulta->bindParam(':nombre', $this->nombre);
          $consulta->bindParam(':descripcion', $this->descripcion);
          $consulta->bindParam(':id', $this->id);
          $consulta->execute();
       }else /*Inserta*/ {
          $consulta = $conexion->prepare('INSERT INTO ' . self::TABLA .' (nombre, descripcion) VALUES(:nombre, :descripcion)');
          $consulta->bindParam(':nombre', $this->nombre);
          $consulta->bindParam(':descripcion', $this->descripcion);
          $consulta->execute();
          $this->id = $conexion->lastInsertId();
       }
       $conexion = null;
    }
    public static function buscarPorId($id){
       $conexion = new Conexion();
       $consulta = $conexion->prepare('SELECT nombre, descripcion FROM ' . self::TABLA . ' WHERE id = :id');
       $consulta->bindParam(':id', $id);
       $consulta->execute();
       $registro = $consulta->fetch();
       if($registro){
          return new self($registro['nombre'], $registro['descripcion'], $id);
       }else{
          return false;
       }
    }
    public static function recuperarTodos(){
       $conexion = new Conexion();
       $consulta = $conexion->prepare('SELECT id, nombre, descripcion FROM ' . self::TABLA . ' ORDER BY nombre');
       $consulta->execute();
       $registros = $consulta->fetchAll();
       return $registros;
    }
 }
?>

Analicemos el código del método recuperarTodos():

Conectamos a la base de datos:

$conexion = new Conexion();

Creamos la consulta:

$consulta = $conexion->prepare('SELECT id, nombre, descripcion FROM ' . self::TABLA . ' ORDER BY nombre');

La ejecutamos:

$consulta->execute();

Recuperamos la respuesta de la consulta y la retornamos:

$registros = $consulta->fetchAll();
return $registros;

Ahora vemos cómo funciona:

<?php
 require_once 'clases/Personaje.php';
 $personajes = Personaje::recuperarTodos();
?>
<html>
   <head></head>
   <body>
      <ul>
      <?php foreach($personajes as $item): ?>
      <li> <?php echo $item['nombre'] . ' - ' . $item['descripcion']; ?> </li>
      <?php endforeach; ?>
      </ul>
   </body>
</html>

Simplemente guardamos en la variable $personajes el resultado de la consulta y la mostramos en pantalla con código html.

Bueno con esto termino, más adelante espero publicar más información sobre clases en PHP.

Les dejo un ejemplo de listar, crear, modificar y eliminar registros con PDO:

Descargar ejemplo

Les recomiendo esta página: https://www.phpclasses.org/ hay una comunidad muy grande que sube clases para realizar distintas cosas por ejemplo crear archivos PDF y cosas así.

Saludos!

Anterior: Php orientado a objetos, parte 11: PDO, Guardar registros en una base de datos

Siguiente: Php orientado a objetos, parte 13: Singleton


84 Respuestas a “Php orientado a objetos, parte 12: PDO, Buscar registros en una base de datos”

  1. Tan solo agradecer el material encontrado en tu web, sobre todo los temas de PDO, que gracias a tus explicaciones y ejemplo pude sacar un error que tenia.
    Espero que sigas cn el material sobre todo lo que respecta a PDO, un abraso desde CHILE.

  2. Muchas gracias Juan. PDO al principio puede parecer un dolor de cabeza, pero es la mejor forma hoy por hoy de conectarse con una base de datos en PHP.

    Gracias por el comentario y cualquier duda o sugerencia que quieras hacerme bienvenido serás.

    Saludos!!!

  3. Excelente!
    justo lo que buscaba, ya tengo bastante experiencia programando, pero me hace falta hacer mi propio sistema PDO, por supuesto con este ABMC que hiciste con 2 simples ejemplos me basta para hacer grandes aplicaciones.

    muchas gracias!!

  4. Hola Amigo, muy bueno el post me gustaria que muestres como hacer esto

    ASI:

    getNombre() . ‘ – ‘ . $item->getDescripcion(); ?>

    Y POR SUPUESTO LOS METODOS ENCADENADOS!!

    Con eso me doy por hecho.

    muchas gracias! 30.04.2013

    1. Sebas:

      Bueno, respondiendo a tu primer solicitud, la forma de hace esto que vos decís sería modificando el método recuperarTodos() de esta forma:

      public static function recuperarTodos() {
      $conexion = new Conexion();
      $consulta = $conexion->prepare(‘SELECT id FROM ‘ . self::TABLA . ‘ ORDER BY nombre’);
      $consulta->execute();
      $registros = $consulta->fetchAll();
      $registrosObjs = array();
      foreach ($registros as $item){
      array_push($registrosObjs, self::buscarPorId($item[‘id’]));
      }
      return $registrosObjs;
      }

      El problema es que esto consume mucha memoria.

      Si en cambio lo que vos querés es recuperar de la consulta un array de objetos y no de arrays asociativos lo que tenés que hace es en lugar de hacer eso:

      public static function recuperarTodos(){
      $conexion = new Conexion();
      $consulta = $conexion->prepare(‘SELECT id, nombre, descripcion FROM ‘ . self::TABLA . ‘ ORDER BY nombre’);
      $consulta->execute();
      $registros = $consulta->fetchAll();
      return $registros;
      }

      Hacer esto:

      public static function recuperarTodos() {
      $conexion = new Conexion();
      $consulta = $conexion->prepare(‘SELECT id, nombre, descripcion FROM ‘ . self::TABLA . ‘ ORDER BY nombre’);
      $consulta->execute();
      $registros = $consulta->fetchAll(PDO::FETCH_OBJ);
      return $registros;
      }

      El método fetchAll(PDO::FETCH_OBJ) con el parámetro PDO::FETCH_OBJ indicará que debe devolver un array de objetos en donde cada valor será llamado como una propiedad en lugar de hacer esto:

      Vas a hacer esto:

      • nombre . ‘ – ‘ . $item->descripcion; ?>

      Con respecto a tu otra pregunta nunca creé una clase con métodos encadenados, sin embargo sí los usé. Normalmente las clases con métodos encadenados sirven para crear consultas a una base de datos, se me ocurre de repente tener una clase cómo ésta:

      class DbQuery {
      private $consulta = »;
      //Método encadenado.
      public function select($campos){
      $this->consulta .= ‘ SELECT ‘ . $campos . ‘ ‘;
      return $this;
      }
      //Método encadenado.
      public function from($tabla){
      $this->consulta .= ‘ FROM ‘ . $tabla . ‘ ‘;
      return $this;
      }
      //Método encadenado.
      public function orderBy($campos){
      $this->consulta .= ‘ ORDER BY ‘ . $campos . ‘ ‘;
      }
      public function getConsulta(){
      return $this->consulta;
      }
      }

      A través de los métodos encadenados select(), from() y orderBy() los iré llamando para ir armando la consulta:

      $dbQuery = new DbQuery();
      $dbQuery->select(‘id, nombre, descripcion’)
      ->from(‘personaje’)
      ->orderBy(‘nombre, id’);

      Y luego obtener el código generado con otro método. Algo así:

      echo $dbQuery->getConsulta();

      Que devolverá: ‘SELECT id, nombre, descripcion FROM personaje ORDER BY nombre, id’

      Un framework que suele utilizar métodos encadenados es codeigniter, por ejemplo para hacer los queries hace cosas cómo:

      $this->db->select(‘titulo’)->from(‘tabla’)->where(‘id’, $id)->limit(10, 20);

      Espero haberte ayudado.

      Saludos!

      1. Hola muchas gracias por la ayuda!
        bueno finalmente aplique todos los ejemplos que me indicaste (estoy haciendo mi miniframework asi que tomo todas las ideas y las pruebo)

        en el caso de los array de objetos es casi casi lo que queria:
        Este metodo
        prepare(«SELECT id FROM » . self::TABLA . » ORDER BY nombre»);
        $consulta->execute();
        $registros = $consulta->fetchAll();
        $registrosObjs = array();
        foreach ($registros as $item){
        array_push($registrosObjs, self::buscarPorId($item[‘id’]));
        }
        return $registrosObjs;
        }
        ?>
        Lo uso asi:
        FETCH OBJECT FULL

        getNombre() . » – » . $item->getDescripcion(); ?>

        Me gustaria cambiar el

        por
        iterate()){ … }
        Creo que es un patron de diseño

        En cuanto a los metodos encadenados, soy de los que buscan simplesa y a la vez potencia. esta bueno tener la opción de PDO para relacionar tablas pero avaces la queries estan reestringidas a un Framework X y tenes que hacer malabares o bien hacer cientas de queries innecesarias para obtener un valor calculado por sql.

        Te dejo como me quedo (parcialmente) la clase dbQuery:
        campos .= $campos;
        $this->consulta .= » SELECT » . $this->campos . » «;
        return $this;
        }
        //Método encadenado.
        public function from($tabla){
        $this->consulta .= » FROM » . $tabla . » «;
        return $this;
        }
        //Método encadenado.
        public function orderBy($campos){
        $this->consulta .= » ORDER BY » . $campos . » «;
        }
        public function getConsulta(){
        return $this->consulta;
        }
        public function execute(){
        $conexion = new Conexion();
        $consulta = $conexion->prepare($this->getConsulta());
        $consulta->execute();
        $registros = $consulta->fetchAll(PDO::FETCH_OBJ);
        return $registros;

        }

        }?>
        Para ver el ejemplo (siguiendo con tu tutorial) :
        select(«id, nombre, descripcion»)->from(«personaje»)->orderBy(«nombre, id»);

        echo $dbQuery->getConsulta();

        $personajes = $dbQuery->execute();
        ?>

        nombre . » – » . $item->descripcion; ?>

        Como veras en este ultimo caso no me interesa demasiado si devuelvo un array sql u de objeto
        el objetivo es poder hacer queries complejas independientes del framework que esté usando.

        Seguro te voy a seguir molestando.

        gracias otra vez!

        1. No conocía el iterate, ahora lo estoy viendo en la documentación de PHP. Gracias por el dato.

          Y no me molestas para nada. Cualquier cosa si te puedo ayudar, te ayudo. En realidad este blog lo creé para poder publicar cosas que voy aprendiendo o que aprendí hace un tiempo. Yo hace sólo 4 años aprox. que programo. Me gusta ayudar en lo que puedo.

          Abrazo!

  5. Hola copie tus clases tal cual pero no me graba en la base de datos.
    Sin embargo cuando evaluo el $consulta->execute() con el var_dump(), me da true…

    ¿tenes idea que puede ser?

      1. Hola Fernando!!
        Gracias por tu respuesta, pero revisando el codigo de nuevo, me di cuenta que estaba pasando un parametro de mas. Mandaba 1 como id cuando ni siquiera habia un registro en la base.

        Lo cual ya que estoy aprovecho para preguntarte como se puede hacer para controlar eso, pues no me mandaba error.

        Slds

        Joaquin

        1. Sí, después que disparás la consulta con execute(), tenés un método que se llama errorCode(). Ese método te va a devolver un array con información, si es que ha habido un error:

          $consulta->execute();
          var_dump($consulta->errorInfo());

          De cualquier manera es extraño que execute() te haya devuelto true, si no había insertado.

          Saludos!

      1. ok gracias amigo ferchu, quisiera acotar esta funcion a personaje es otro tipo de busqueda, es la busqueda por fecha y se implementaria solo caon agregar otro campo en la base de dato llamado fecha, y definir el campo en la clase,
        public static function buscarPorFechas($fecha,$dfecha){
        $conexion = new Conexion();
        $consulta = $conexion->prepare(‘SELECT * FROM ‘ . self::TABLA . ‘ where fecha BETWEEN :fecha and :dfecha and estatus_id=2’);
        $consulta->bindParam(‘:fecha’, $fecha);
        $consulta->bindParam(‘:dfecha’, $dfecha);
        $consulta->execute();
        $registros = $consulta->fetchAll();
        return $registros;
        }

  6. buen dia amigo Ferchu, quisiera saber que posibilidades hay de que me mostrara como hacer un paginado siguiendo esta tecnica de programacion y por otro lado si tienes conocimiento de codegniter la posibilidad de un login de usuario pero donde sea identificado el tipo de usuario para poder mandarlo a su pagina dependiendo si es un administrador, supervisor o empleado

    1. Para paginar deberías usar con MySQL LIMIT, dependiendo de dónde estás parado, y la cantidad de páginas que quieras mostrar. La verdad es que no tengo ningún ejemplo en este momento, pero por lo general los paginados van a depender de la consulta que tengas.

      Un buen tutorial de Codeigniter es éste

      Y con respecto al login, yo usaría una tabla donde se guarden los permisos, «administrador», «supervisor», «empleado», y que cada usuario tenga un rol, y cuando el usuario se loguea, que se guarde en la sesión, además del id, el rol, entonces dependiendo de ese rol, tenga acceso a determinadas cosas.

      Saludos!

  7. Buenas, solo paso a agredecer por compartir tus conocimientos. Y la predisposición a las preguntas. Un saludo y muchisimas gracias! 🙂 me sirvió mucho.

  8. Hola Fernando.
    Te hago una consulta, de que manera se puede implementar en un formulario cargar los datos que retornan del metodo que creaste «buscarPorID»?
    Ejemplo: Si es que se puede volcar los datos del objeto dentro de la etiqueta:
    <input type="text" value='’>
    Gracias.

  9. Hola Ferchu, valiosisimo aporte, muy bueno y muy completo, sobre todo para la POO, yo vengo de programar en ASP.NET C#, pero me salio algo para hacer en PHP, y este tuto me ha caído de maravilla, pues sabía algo muy rudimentario en PHP, pero con tu pagina estoy pensando en la posibilidad cambiarme a PHP… ojala si pudieras seguir subiendo este tutorial, sobre todo orientado a la POO.

    Gracias

  10. hola amigo este tuto esta muy bueno cuentame habra la posibilidad que me mueste un ejemplo de paginado con la misma estrategia de programacion que usas en este tuto

  11. estimado quisiera hacerle una consulta cual es tu mail para enviar mi consulta espero que me puedas ayudar

  12. Hola,

    Primero que nada felicitarte buen tuto. Soy nuevo en programación php y pues tengo unas dudas o problemas.

    He intentado adaptarlo y todo bien, pero al momento de querer guardar el documento o actualizarlo o crear un item adicional, pues no ejecuta nada y me vuelve a mostrar los datos pero sin cambios.

    Podrías explicarme como haces para guardar los datos?, no lo entiendo muy bien, espero sea posible y gracias.

    Te adjunto el link de mi modificacion a ver si me apoyas. Gracias nuevamente por tu apoyo.

  13. Hola,

    Ya encontre mi error, no le estaba pasando el Id a la consulta. Gracias amigo esta genial tu clase.

  14. Que tal amigo,

    Otra vuelta para molestarte, tengo una duda, quiero hacer un registro del contenido de un directorio, pero extrañamente me registra solo el ultimo item del bucle.

    Cito———–
    path . «»;
    ?>

    read())) {
    if (strpos($archivo, «.jpg») !== false or strpos($archivo, «.JPG»))
    {
    if (strpos($archivo, «thumb_») !== false)
    {
    echo «»;
    echo «$archivo»;
    echo «path.$archivo.»\» />»;
    echo «»;
    }else{
    $imagenes->setcod_proy(‘2’);
    $imagenes->setnom_foto($archivo);
    $imagenes->setpath_foto($directorio->path.$archivo);
    $imagenes->setdscp_foto(‘registro de la foto’);
    $imagenes->guardar();
    echo «»;
    echo «$archivo»;
    echo «path.»thumb_».$archivo.»\» />»;
    echo «»;
    }
    }
    }

    $directorio->close();
    ?>

    FIN CITA————

    A este archivo le falta aún algunas cosas, pero es la idea, que me registre en la BD, todas las imagenes jpg que encuentre en la ruta que le paso.

    Espero se entienda, y espero puedas orientarme, Gracias de antemano amigo.

  15. Hola Fernando, temgo un problemita estaba poniendo a funcionar tu codigo (el cual agradezco que hallas publicado y explicado amablemente), cree la tabla, cambie base de datos y pasword (conexion.php) y me surgio este inconveneiente que se denota asi :

    Ha surgido un error y no se puede conectar a la base de datos. Detalle: could not find driver

    Espero me ayudes, Gracias por todo un saludo desde aca de Colombia.

  16. Hola yo utilizo mysql, atravez de un servidor local (AppServer) ya descomente algunas extensiones en el php.ini, pero me sigue apareciendo dicho error, gracias por todo

    1. Es extraño, si tenés la versión de PHP 5, deberías tener la extensión habilitada. De cualquier manera después de habilitar las mismas deberías reiniciar el servidor.

      Saludos!

  17. AMIGO ME LLAMA MUCHO LA ATENCION PROGRAMAR PDO, PERO NO ENTIENDO MUY BIEN EL CODIGO, ES DECIR PRIMERO CREAS UN ARCHIVO conexion.php, luego personaje.php, y de ahy no se que archivo crear para q la busqueda me sirva si me puedes establecer el orden por favor en el q va el codigo.

      1. amigo en el codigo que subiste a github solo elimina y crea un registro, yo necesito es hacer busquedas usando pdo , por favor si me puedes ayudar en esto te agradeceria.

        1. Yo no sé qué tipo de consulta tengas que hacer, pero simplemente tenés que crear un objeto PDO y con el método prepare(), ejecutar tu consulta:

          try{
          //Se conecta a la base de datos.
          $pdo = new PDO(‘mysql:host=localhost;dbname=nombredebase’, ‘usuario’, ‘contraseña’);
          } catch (PDOException $e) {
          //Por si hubo un error.
          echo ‘Error: ‘ . $e->getMessage();
          exit;
          }

          //Se escribe la consulta.
          $consulta = $pdo->prepare(‘Tu consulta’);
          //Tira la consulta.
          $consulta->execute();
          //Devuelve los resultados.
          $resultado = $consulta->fetchAll();

  18. AMIGO DISCULPA LA MOLESTIA PERO ME PODRIAS PASAR UN EJEMPLO DE BUSQUEDA EN PDO, QUE TENGA UN FORMULARIO EN EL CUAL CUANDO SE DIGITE ALGO MUESTRE LA REGISTROS QUE COINCIDA CON LOS CRITIREIOS , Y QUE LOS REGISTROS SE MUESTREN EN UNA TABLA ESPERO SU PRONTA RESPUESTA GRACIAS.

    1. Javier para hacer un buscador necesitas más que PDO, PDO sólo te va a permitir conectarte a la base de datos. Para eso necesitas Ajax, yo no tengo ningún ejemplo de momento. Vas a tener que buscarlo en otro sitio.

      Gracias.

  19. Excelente!!! 😀 me podrias ayudar con un ejemplo mas claro de buscar por id, y me muestre el resto por ejm el nombre, descripcion, telefono etc… no encuentro la manera de hacerlo o podrias subir un ejm claro con respecto a tu ejercicio donde implementar la funcion buscar porque solo esta el codigo

    1. Fácil, cambiando la consulta, en donde va:

      $consulta = $conexion->prepare(‘SELECT nombre, descripcion FROM ‘ . self::TABLA . ‘ WHERE id = :id’);

      Por otro atributo:

      $consulta = $conexion->prepare(‘SELECT nombre, descripcion FROM ‘ . self::TABLA . ‘ WHERE otro = :otro’);

      $consulta->bindParam(‘:otro’, $otro);

      Saludos!

  20. Sebastian eres un genio, hace tiempo buscaba un tuto bien explicado y detallado, este es lo mejor que he encontrado y lo mejor es que usas el PDO y lo explicas, mil gracias desde Rep. Dominicana!

  21. no puedes darte una idea lo que me has ayudado…
    grande viejo, sos un capo y esta tan claro todo lo que posteas…
    gracias a vos me destrabe jejeje

    gracias

      1. oye solo una duda, no se si tu puedas ayudarme mi proyecto muestra los datos por fecha, pero como hago para que muestre solo las de un mes y no todas las que hay

        1. Si usás MySQL, podés hacer una cosa así:

          SELECT * FROM tu_tabla WHERE MONTH(columna_fecha) = 11;

          Esto te devolvería los registros del mes de Noviembre.

          Saludos!

  22. Hola amigo, primero para felicitarte soy de Honduras y un dedicado a cualquier tema que sea programación. felicito tu actitud para ensenar y el proyecto que realizastes de pdo.

    En esencia es lo que muestras, los libros andan con muchos rodeos y con ejemplos difíciles.

  23. Hola Fernando… me gustan mucho tus tutoriales, son bastante explicativos y prácticos.
    Tengo una interrogante sobre recuperar los datos de la base de datos y me gustaría si me podrías guiar un poco, es la siguiente…
    Estoy intentando una pagina que muestra el catálogo de productos de una empresa… y como es normal, primero tienes la foto del producto con el precio y luego al darle click se muestran la descripción del mismo. Yo muestro todos los productos con fetchAll() y como puedo hacer para al hacerle click al producto me pueda recuperar las descripcion y demas?

    1. Tenés muchas formas, la más común sería que vos en el enlace incluyas el id del producto, y redirigir a esa página con ese id pasándoselo por GET

      Sabés cómo pasar variables por GET?

      Saludos!

      1. Gracias por tu respuesta… Aun no he visto ese punto, me recomendarías alguna pagina donde me explique mejor?

        Saludos!

  24. Y tengo otro problemita… cuando trato de guardar los datos en la base de datos me lanza un error «could not find driver»… Leí que puede ser por que no tiene el plugin instalado o no se ha iniciado, pero vi que tiene el servicio iniciado y en phpinfo() estan habilitados y todo lo demás; estoy usando WAMPPSERVER para hacer las pruebas, no se si podría ser ese el problema…

    Saludos

  25. Amigo una pregunta si ejecutas varias veces el codigo por ejemplo cuando colocas un campo unico y falla la subida, tengo el siguiente problema al volver a insertar el dato el ID va corriendo a medida que ejecutaste la pagina en el codigo es decir en vez de ser 1 2 3 registro es asi insertaste el primer dato 1 y luego fallaste intentando subir nuevamente 9 veces al insertar depues el dato no repetido la BD toma el id como 10 no te ha sucedido eso

  26. hola espero y me puedan ayudar tengo un problema tengo que buscar la manera de cachar datos de una base de datos en MYSQL pero mediante PDO espero y me puedan ayudar

  27. HOLA gtacias por todo, un abrazo enorme.

    PD: no falto un $conexion = null; en el final de buscar por id? creo que el alcance de las variables no interfieren porque son locales dentro de cada metodo, pero estarias usando dos conexiones distintas consumiendo recursos, va eso entendi. saludos!

    1. Sí, es cierto lo que decís, la realidad es que este ejemplo lo hice hace mucho (como tres años) y cometí algunos errores.

      Lo más óptimo en este tipo de cosas, es crear una única conexión y que los métodos que dentro suyo realizan consultas tengan un parámetro que espere el objeto de conexión.

      Gracias por la corrección.

      Saludos!

  28. Muy buenas tardes, agradecerte el tutorial que es el más completo que he encontrado.
    Me he bajado el código y creado las carpetas correspondientes. Al ejecutar crear nuevo personaje tengo el siguiente error.
    setNombre ( $ nombre ); $ personaje -> setDescripcion ( $ descripcion ); $ personaje -> GUARDAR (); cabecera ( ‘ Location: index.php ‘ ); } Demás { incluir ‘ vistas / guardar_personaje.php ‘ ; } ? >
    Aunque he mirado no encuentro nada anormal.
    Agradeciendo de antemano la ayuda.

    1. Perdón José Enrique, no veo el error. Podrías indicarme cuál es el error que te devuelve por pantalla, por fa?

      Saludos!

  29. Hola Fernando, antes que nada agradecerte el aporte, es fabuloso como defines la clase y sus métodos para insertar, modificar y leer registros. Me gustaría saber cómo implemetarías en la misma clase un método para una relación maestro-detalle, por ejemplo, al buscarPorId() obtener los regitros de otra tabla detalle relacionada por el ID. Me queda claro que hay que hacer otra consulta pero me interesa saber si es conveniente implementarla en la misma clase o en otra con su método para recuperarTodos(). ¿Cual es tu recomendación?. Un saludo y gracias nuevamente!

  30. Hola Fernando, muy buena explicación del tutorial, estoy comenzando con programación en PHP, tengo una inquietud si quiero hacer una consulta entre varias tablas ose a un join, te agredeceria si das una pequeña explicación sobre este tema.

    Saludo cordial, gracias

  31. consulta

    para este ejemplo como se pude hacer setAttribute

    $pdo = new coneccion();
    $pdo ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    me confunde un poco cuando lo haces desde el contructor;

  32. 0){
    ?>
    hola trabajo en un sistema soy un tanto nuevo en esto mmmmmmm la verdad tengo que hacer cuatro buscadores y el sistema ya tiene uno que funciona correctamente pero no logro entender este tipo de programacion … quisiera un poco de ayuda

  33. Que tal;

    Primero que nada; agradeszo mucho tu tiempo y paciencia para enseñarnos y compartir tus conocimientos.

    Disculpa si mi pregunta es derrepente muy obvia; soy aficionado en programación. Al probar el escript de inserción de registro.

    Y validar si fue ingresado a la BD; noto que la tabla está vacía; pero claro en la pantalla me dice que fue ingresado me recupera el $id.

    Lo extraño es que no inserta a la tabla. Pero si me muestra el contenido y realiza la busqueda.

    Gracias de antemano.

    1. Fijate si realmente está apuntando a la conexión correcta o a la base de datos correcta. O bien, fijate refrescando la tabla.

      Saludos!

  34. Ferchu, te pido disculpas no se que ocurre , no puedo enviar la primera parte del codigo,

    get_conexion();
    $sql = «insert into tablausuarios (nombre, usuario,password) values(:nombre, :usu, :passw)»;
    debe ser que hay alguna restricción especial que no conozco.

    1. Por favor enviarme el código PHP y en lo posible las tablas que te dan error de MySQL por correo. fernando.g.gaitan(gmail)

      Gracias.

  35. Hola te quería hacer una consulta, me podrías dar tu correo, es relacionado con una tabla que quiero realizar con los registros, pues guardar me funciona super bien, pero cuando integro la tabla en la index me da error cuando llamo la clase y según veo si esta bien en el require, me podrías ayudar?

  36. Muchas Gracias

    Llevaba varios meses estudiando la programación orientada a objetos en Php y gracias a tus publicaciones he aprendido mucho. Saludos desde Venezuela

  37. Hola: me gustaría hacerte una pregunta. Al igual que buscas por id, como puedo hacer que busque o me saque una búsqueda de una palabra que coincida en una parte del registro? De normal en la consulta yo utilizo campo like ‘%$busqueda%’ pero como lo hago para aplicarlo a tu código? Campo like :búsqueda.

    Muchas gracias

    1. Algo como esto:

      public static function buscarPorNombre($nombre) {
      $conexion = new Conexion();
      $consulta = $conexion->prepare(‘SELECT id, nombre, descripcion FROM ‘ . self::TABLA . ‘ WHERE nombre LIKE :nombre’);
      $nombre = «%{$nombre}%»;
      $consulta->bindParam(‘:nombre’, $nombre);
      $consulta->execute();
      $registro = $consulta->fetch();
      $conexion = null;
      if ($registro) {
      return new self($registro[‘nombre’], $registro[‘descripcion’], $registro[‘id’]);
      } else {
      return false;
      }
      }

      Saludos!