Foros del Web » Programando para Internet » PHP »

[APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Estas en el tema de [APORTE] Control Select con datos desde la Base de Datos - Avanzado - en el foro de PHP en Foros del Web. Mucho he visto en el foro que preguntan como pueden obtener el "label" de un control <select>, por defecto esto no es posible, ya que ...
  #1 (permalink)  
Antiguo 09/06/2008, 17:31
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
[APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Mucho he visto en el foro que preguntan como pueden obtener el "label" de un control <select>, por defecto esto no es posible, ya que el explorador no envía este dato, sin embargo podemos jugar un poco con la fuente de datos para obtener el label.

Por eso presento el siguiente aporte, sirve para dibujar controles <select> y poder obtener varias caracteristicas del control una vez que lo procesamos en PHP.

Antes de poner el código y como usarlo, debo de mencionarles que la fuente de datos esta separada del control, esto le da mucha flexibilidad ya que no es necesario que la fuente de datos sea una base de datos, puede ser un array, o un archivo de texto con tal de que implemente la interfaz necesaria.

Primero lo primero, y es que hay que darle una fuente a los datos:
Código PHP:
/** Primero creamos nuestro access layer a los datos y conectamos **/
$db = new DBAccess"localhost""root""""" );
$db->Connect();
/** Luego creamos nuestra fuente de datos **/
$ds = new SQLDataSource$db"SELECT `id`, `nombre` FROM `nombres`" );
$ds->bind(); 
En $ds ya tenemos una fuente de datos que podemos meter a nuestro control:
Código PHP:
/** El select se llamara "nombres" y lo podemos rescatar como $_POST['nombres'] aunque más abajo veremos una forma mas efectiva **/
$sel = new Select"nombres" );
$sel->setDataSource$ds ); 
El ultimo paso es construir el control y mostrarlo en nuestro formulario esto lo hacemos sencillo:
Código PHP:
<?php
$sel
->buildControl();
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="demo">
<?php echo $sel->getControl(); ?> <input type="submit" name="enviar" value="Enviar" />
</form>
Ahora más arriba mencione que es posible rescatar más opciones del control y esto es leyendo sus propiedades:
Código PHP:
$selected $sel->getSelectedValue();
$label $sel->getSelectedLabel();
$name $sel->getName();
    
printf"Del control %s, usted selecciono el valor %s, que corresponde a %s"$name$selected$label ); 
Con esto podemos tener un acceso OOP a un control de una forma más limpia y de forma 100% OOP.

Aquí esta el archivo final:
Código PHP:
<?php
require( 'DBAccessInterface.php' );
require( 
'DBResultInterface.php' );
require( 
'DBAccess.php' );
require( 
'DBResult.php' );

require( 
'DataSourceInterface.php' );
require( 
'SQLDataSource.php' );

require( 
'Select.php' );

$db = new DBAccess"localhost""root""""" );
$db->Connect();
$ds = new SQLDataSource$db"SELECT `id`, `nombre` FROM `nombres`" );
$ds->bind();
$sel = new Select"nombres" );
$sel->setDataSource$ds );

if( 
strtolower$_SERVER['REQUEST_METHOD'] ) == 'post' ) {
    
$selected $sel->getSelectedValue();
    
$label $sel->getSelectedLabel();
    
$name $sel->getName();
    
    
printf"Del control %s, usted selecciono el valor %s, que corresponde a %s"$selected$label );
}

$sel->buildControl();
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="demo">
<?php echo $sel->getControl(); ?> <input type="submit" name="enviar" value="Enviar" />
</form>
En los próximos posts pondre el Source Code de toda la aplicación para que lo puedan probar en sus servers.

Última edición por GatorV; 15/06/2008 a las 10:42
  #2 (permalink)  
Antiguo 09/06/2008, 17:33
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Interfaces necesarias:
DataSourceInterface:
Código PHP:
<?php
interface DataSourceInterface {
    public function 
bind();
    public function 
getData();
}
?>
DBAccessInterface:
Código PHP:
<?php
interface DBAccessInterface {
    public function 
Connect();
    public function 
Query($query);
    public function 
Disconnect();
}
?>
DBResultInterface.php
Código PHP:
<?php
interface DBResultInterface {
    public function 
fetchRow();
    public function 
numRows();
}
?>
Luego viene el acceso a datos (es una clase muy sencilla que seguramente deberá ser completada):
DBAccess.php:
Código PHP:
<?php
class DBAccess implements DBAccessInterface {
    private 
$host;
    private 
$user;
    private 
$pass;
    private 
$db;
    private 
$link;
    
    public function 
__construct($host$user$pass$db ) {
        
$this->host $host;
        
$this->user $user;
        
$this->pass $pass;
        
$this->db $db;
    }
    
    public function 
Connect() {
        
$this->link mysql_connect$this->host$this->user$this->pass );
        if( 
$this->link ) {
            
mysql_select_db$this->db );
        } else {
            throw new 
Exception'MySQL Error: ' mysql_error() );
        }
    }
    public function 
Query($query) {
        
$result mysql_query$query$this->link );
        if( 
is_bool$result ) ) {
            return 
$result;
        } else {
            return new 
DBResult$result );
        }
    }
    public function 
Disconnect() {
        
mysql_close$this->link );
    }
}
?>
DBResult.php
Código PHP:
<?php
class DBResult implements DBResultInterface {
    private 
$result;
    
    public function 
__construct$result ) {
        
$this->result $result;
        if( 
is_bool$result ) ) {
            throw new 
Exception'$result parece ser un booleano, no un resultado exitoso de una DB: ' mysql_error() );
        }
    }
    
    public function 
fetchRow() {
        return 
mysql_fetch_row$this->result );
    }
    
    public function 
numRows() {
        return 
mysql_num_rows$this->result );
    }
    
    public function 
__destruct() {
        
mysql_free_result$this->result );
    }
}
?>
Luego viene el DataSource o la fuente de datos:
SQLDataSource:
Código PHP:
<?php
class SQLDataSource implements DataSourceInterface {
    private 
$query '';
    private 
$data = array();
    private 
$dbh null;
    
    public function 
__construct($dbh$query) {
        if( !(
$dbh instanceof DBAccess ) ) {
            throw new 
Exception'$dbh debe implementar la interface DBAccess' );
        }
        
$this->dbh $dbh;
        
$this->query $query;
    }    
    
    public function 
bind() {
        
$result $this->dbh->Query$this->query );
        if( 
$result->numRows() == ) {
            
$this->data = array();
            
$result null;
            return;
        }
        
        
$data = array();
        while( 
$row $result->fetchRow() ) {
            if( 
count$row ) == ) { // cuando viene como valor, nombre
                
$data[$row[0]] = $row[1];
            } else {
                
$data[] = $row[0];
            }
        }
        
        
$this->data $data;
        
$result null;
    }
    
    public function 
getData() {
        return 
$this->data;
    }
}
?>
.. Continua ..

Última edición por GatorV; 15/06/2008 a las 10:38 Razón: Error de Copy/Paste
  #3 (permalink)  
Antiguo 09/06/2008, 17:35
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Luego viene el archivo "core" que es el control en sí:
Select.php:
Código PHP:
<?php
class Select {
    private 
$name '';
    private 
$selected '';
    private 
$currSelected '';
    private 
$html;
    private 
$ds null;
    
    protected 
$selectopen '<select name="%s">';
    protected 
$selectclose '</select>';
    protected 
$option '<option value="%s">%s</option>';
    protected 
$optionselected '<option value="%s" selected="selected">%s</option>';
    protected 
$selectLabel ' - Selecciona - ';
    
    public function 
__construct($name) {
        
$this->name $name;
        if( isset( 
$_REQUEST[$name] ) ) {
            
$this->currSelected $_REQUEST[$name];
            
$this->selected $_REQUEST[$name];
        }
    }
    
    public function 
setSelected$selected ) {
        
$this->selected $selected;
    }
    
    public function 
setDataSourceDataSourceInterface $ds ) {
        
$this->ds $ds;
    }
    
    public function 
getDataSource() {
        return 
$this->ds;
    }
    
    public function 
getControl() {
        return 
$this->html;
    }
    
    public function 
getName() {
        return 
$this->name;
    }
    
    public function 
getSelectedValue() {
        return 
$this->currSelected;
    }
    
    public function 
getSelectedLabel() {
        
$data $this->ds->getData();
        
        return 
$data[$this->currSelected];
    }
    
    public function 
buildControl() {
        if( 
$this->ds == null ) {
            throw new 
Exception'No hay ninguna fuente de datos disponible, favor de llamar a Select::setDataSource() antes de llamar a esta función' );
        }
        
$data $this->ds->getData();
        
$options = array();
        
$options[] = sprintf$this->option""$this->selectLabel );
        
        foreach( 
$data as $val => $label ) {
            if( 
$val == $this->selected ) {
                
$template $this->optionselected;
            } else {
                
$template $this->option;
            }
            
            
$options[] = sprintf$template$val$label );
        }
        
        
$html sprintf$this->selectopen$this->name );
        
$html.= implode"\n"$options );
        
$html.= $this->selectclose;
        
        
$this->html $html;
    }
}
?>
Espero con esto se den una idea un poco básica de la forma de separar los datos de la vista y que es uno de los principios básicos de la POO.

Saludos.
  #4 (permalink)  
Antiguo 11/06/2008, 16:38
 
Fecha de Ingreso: enero-2005
Mensajes: 149
Antigüedad: 19 años, 11 meses
Puntos: 2
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Primero !! hehe

Que grande eres jojo... sabes moverte entre mares de objetos ^^

Muchas gracias por el aporte !! si bién algunos quizá no lleguemos a usarlo. Nos ayudará a aprender.

Un saludo
  #5 (permalink)  
Antiguo 13/06/2008, 16:27
Avatar de jahepi
Colaborador
 
Fecha de Ingreso: diciembre-2004
Ubicación: Querétaro
Mensajes: 1.124
Antigüedad: 20 años
Puntos: 43
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Hola GatorV !

Muy buena aportación , esta perféctamente descoplada la capa de datos del control, como siempre un gusto leerte.

Nada mas se te escapo, hay un error de dedo, en la interfaz DBResultInterface.php te equivocaste pusiste la anterior.

Un saludo y gracias por compartir !
__________________
Una contraseña es como la ropa interior. No deberías dejarlas afuera a la vista de otras personas, deberías cambiarla regularmente, y ni se te ocurra prestarla a extraños.
  #6 (permalink)  
Antiguo 14/06/2008, 20:54
Avatar de jaronu  
Fecha de Ingreso: febrero-2008
Mensajes: 2.183
Antigüedad: 16 años, 9 meses
Puntos: 52
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Increible, GatorV, tu forma de programar es impresionante, ahora empiezo a leer sobre POO, tudavia no me entero demasiado, pero se que sun muy utiles,

Lo unico es que si agregaras una breve explicacion o un ejemplo para "Tontos", como yo, mas que nada para saber y entender un poco en que consiste bien, tu aporte.

Gracias, eres el mejor, sin duda
  #7 (permalink)  
Antiguo 15/06/2008, 10:52
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Corregidos los errores de copy/paste.

@jaronu, Si lees el primer post podrás ver el ejemplo y el porque del aporte.

Saludos.
  #8 (permalink)  
Antiguo 25/09/2008, 13:37
 
Fecha de Ingreso: mayo-2006
Ubicación: Santiago de Chile
Mensajes: 8
Antigüedad: 18 años, 6 meses
Puntos: 0
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

muy buen, codigo..

!!

Excelente Aporte!
  #9 (permalink)  
Antiguo 29/09/2010, 11:46
 
Fecha de Ingreso: abril-2008
Mensajes: 435
Antigüedad: 16 años, 7 meses
Puntos: 10
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Excelente GatorV como siempre tu forma de programar es digna de admirar y un ejemplo para todos nosotros que aprendemos mas dia a dia

solo una consulta

Código PHP:
public function bind() {
        
$result $this->dbh->Query$this->query );
        if( 
$result->numRows() == ) {
            
$this->data = array();
            
$result null;
            return;
        } 
me preguntaba si cuando $result no devuelve un objeto esto no tiraria un fatal?

Código PHP:
$result->numRows() 
saludos
  #10 (permalink)  
Antiguo 29/09/2010, 16:12
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Hola,

Gracias por tus comentarios, y no, ya que mysql_num_rows te devuelve 0 en ese caso y no habría problema, más tarde lo voy a actualizar para usar PDO ya que de esa forma, reutilizamos código y una librería que es más usada, no me gusta siempre "reinventar la rueda".

Saludos.
  #11 (permalink)  
Antiguo 29/09/2010, 21:43
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 9 meses
Puntos: 52
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Hola GatorV gracias por este valioso aporte, estoy empezando con la POO con PhP y la verdad me parece muy bueno pero estoy un poco perdido aun, de forma estructurada esto del control (select) se hubiera sacada en unas cuantas lineas de codigo pero de forma OO cambia todo.

En tu ejemplo al dar click en "Enviar" me salata este error:


Warning: printf() [function.printf]: Too few arguments in D:\xampp\htdocs\ejemplo\index.php on line 32
  #12 (permalink)  
Antiguo 29/09/2010, 22:01
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años, 6 meses
Puntos: 2135
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Solo agrega $name en la línea para que quede así:
Código PHP:
Ver original
  1. printf( "Del control %s, usted selecciono el valor %s, que corresponde a %s", $name, $selected, $label );

Saludos.
  #13 (permalink)  
Antiguo 30/09/2010, 09:37
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 9 meses
Puntos: 52
Respuesta: [APORTE] Control Select con datos desde la Base de Datos - Avanzado -

Ok, muchas gracias, ya funciono.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 2 personas (incluyéndote)




La zona horaria es GMT -6. Ahora son las 12:52.