2011-01-06 13 views
8

Acabo de empezar a usar OOP PHP y encontré una pregunta. He creado una clase mysql genérico que me permite conectar a una base de datos y tiene algunas funciones para obtener los registros de una tabla:PHP OOP: cómo usar una clase MySQL genérica en otras clases

class mysql{ 
    //some lines to connect, followed by: 
    public function get_record($sql) 
    { 
     $result = mysql_result(mysql_query($sql)); 
     return $result; 
     //obiously it's a bit more advanced, but you get the picture. 

    } 
} 

A continuación, tengo una clase para obtener los detalles del usuario:

class user{ 
    __construct($id) 
    { 
     $this->id = $id 
    } 
    public function get_username($id) 
    { 
     $username = get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 
     return $username; 
    } 
} 

Intenté esto, pero me salió el error de que no se conocía la función get_record. Lo resolví agregando $ mysql = new mysql(); a la clase de usuario.

Sin embargo, se siente bastante ineficiente tener que crear una instancia del objeto mysql para cada clase que usa mis métodos de base de datos (eso es prácticamente todos).

¿Hay alguna manera de hacer que la clase mysql y sus métodos sean accesibles para todas las demás clases, sin tener que llamar a la clase mysql en todos los métodos?

+1

Por favor, no crear clases de MySQL. Hay demasiados de estos alrededor, incluso cuando PHP ya tiene algo incorporado. Se llama PDO (objetos de base de datos PHP). PDO es transferible a otros desarrolladores, mientras que tener que descubrir la clase MySQL de otra persona una y otra vez se siente bastante inútil. – kander

Respuesta

1

Debe pasar el objeto mysql a cada objeto de usuario. Así se vería así:

$mysql = new mysql(); 
$user = new user($mysql, $id); 
$name = $user->get_username(); 

class user { 
    public function __construct($mysql, $id) { 
     $this->mysql = $mysql; 
     $this->id = $id; 
    } 
    public function get_username() { 
     $username = $this->mysql->get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 
     return $username; 
    } 
} 
1

del diseño de la clase de MySQL a ser llamado de forma estática:

$username = Mysql::get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 

http://php.net/manual/en/language.oop5.static.php

+0

Prefiero llamarlo 'Mysql :: get_record (" SELECCIONAR nombre FROM usuarios WHERE id =% d ", $ this-> id);' –

+0

Definitivamente, hay muchas mejoras que OP puede realizar. Mi respuesta se refiere a la cuestión estrecha de evitar una instanciación incesante. – webbiedave

0

el uso de variables globales, aunque eso no es probablemente la mejor opción.

$mysql = new mysql(); 

function someFunction() { 
    global $mysql; 
    $mysql->get_record(...) 
} 

o un método estático para su clase de MySQL (ver Singleton)

class mysql { 
    public static $theInstance = new mysql(); 
    public static function getInstance() { 
    return $this->theInstance; 
    } 
} 

function someFunction() { 
    $database= mysql::getInstance(); 
    $database->get_record(...) 
} 
+4

Uh, ¡no sugiera usar globales! –

2

Este es un problema común, y por lo tanto no es una solución común a este. Como ya sabrá, en el desarrollo de software, las soluciones comunes sobre problemas comunes se denominan Patrones de diseño.

Existen dos patrones de diseño que pueden ayudarlo a resolver este problema. En un sentido más abstracto el problema que se enfrentan es:

¿Cómo puedo hacer que la clase A está disponible en la clase B?

El patrón Singleton

"En el patrón singleton una clase puede distribuir una instancia de sí mismo a otras clases."

Esto no es exactamente lo que está buscando, ya que su sitio web puede usar múltiples conexiones de bases de datos. Sin embargo, es usado por mucha gente de esta manera.

leer alguna información sobre el uso de una clase Singleton como proveedor de base de datos aquí: https://www.ibm.com/developerworks/library/os-php-designptrns/#N10124

Más información sobre el patrón singleton en PHP: http://www.fluffycat.com/PHP-Design-Patterns/Singleton/

Otro enfoque sensato es el patrón de registro:

Registro Patrón

Usted puede f ind información sobre el patrón de registro en el siguiente enlace, así como una implementación casi idéntica que está buscando: http://www.sitecrafting.com/blog/php-patterns-part/

Aún más potente es una combinación entre el singleton y el registro.

¡Buena suerte y disfruta aprendiendo OOP PHP!

+2

En realidad, el patrón singleton, en este caso particular, no es realmente necesario; después de todo, cualquier cosa que no haga nada con una conexión de base de datos no necesita tener acceso a esa clase, y al usar singleton, toda la aplicación obtiene acceso a singleton. Lo mismo ocurre con el registro, aunque es una alternativa ligeramente mejor.No, yo diría que un objeto de interacción de base de datos es un servicio, y los servicios se pueden asignar a objetos que los necesitan, por ejemplo, usando el patrón de inyección de dependencia. Consulte: http://martinfowler.com/articles/injection.html – fwielstra

+0

@Cthulhu: su comentario sobre el uso del patrón singleton no es necesario para que este problema sea correcto, sin embargo, es una solución común utilizada para este problema específico. Personalmente, no estoy muy familiarizado con la inyección de dependencia, pero gracias por señalarlo. Lo investigaré. –

+1

+1 para la inyección de dependencias ... hace que las pruebas unitarias sean mucho más fáciles si no tienes globales por todos lados, sino que inyectas lo que necesitas en tu clase. Y sí, tanto el registro como el singleton también son globales ... simplemente más disfrazados. – kander

5

Para empezar, no necesita usar singleton en este caso, o de hecho, casi nunca lo hace. Ver this article, por ejemplo.

En segundo lugar, creo que sus diseños de OO están un poco apagados. El punto principal de la programación y el diseño orientado a objetos es aislar la responsabilidad en clases separadas. En este momento, le está dando a su clase de Usuario dos responsabilidades principales: almacenar/transportar los datos relevantes de un usuario y consultar el servicio de datos (en este caso, una simple capa de abstracción de MySQL/base de datos).

Primero debe mover esa funcionalidad a un objeto separado. Por lo general, esto se denomina Servicio, por lo que en este caso es UserService. Un UserService tiene una responsabilidad: proporcionar acceso a los objetos User. Por lo tanto, había sorta aspecto:

class UserService { 
    public function __construct($mysql); // uses the mysql object to access the db. 
    public function get($id) { 
     $result = $this->mysql->get_record("select x from y"); 
     $user = new User($result['id'], $result['name']); // assuming user has a constructor that takes an id and a name 
     return $user; 
    } 
    public function save($user); 
    public function delete($user); 
} 

Se ata todo junto en el inicio de su solicitud (o donde se necesita tener acceso a los usuarios):

$mysql = new MySQL($credentials); 
$service = new UserService($mysql); 
$user = $service->find(1337); 

No es perfecto, pero es un diseño mucho más limpio. Su objeto MySQL hace lo que necesita hacer (crear una conexión, ejecutar consultas), su objeto de usuario es tonto, y su servicio solo hace una cosa, es decir, proporciona una capa entre la capa de almacenamiento real y la cosa que lo llama.

+0

+1 ¡Este es un gran diseño! Los objetos de usuario deben tener una responsabilidad, contener datos de usuario. –

+0

¡Esta es la mejor manera de hacerlo! Este es un muy buen consejo. Aún mejor sería con el uso de la interfaz, pero es lo suficientemente bueno. Testable, limpio. pulgares arriba –

+0

He estado buscando una manera simple de explicar el mejor método de comunicación con una base de datos. La única diferencia entre los enfoques aquí es que he estado usando un controlador en lugar de clase de servicio. Sin embargo, ahora que lo he visto, creo que todavía puedo usar mi controlador y separar la funcionalidad del servicio. – Adsy2010

Cuestiones relacionadas