2012-10-09 104 views
7

He estado trabajando para pasar a OOP en PHP. He leído explicaciones en php.net, pero esperaba poder obtener algunas respuestas específicas aquí.Cómo estructurar clases en PHP

Intenté crear el siguiente ejemplo para ilustrar mi pregunta. Digamos que tengo clases de "Base de datos", "Productos" y "Usuarios", y quiero mostrar productos si un usuario tiene acceso.

Llamo la clase "Productos" a la función "showProducts()", que a su vez crea una instancia de la clase "Usuario" que crea una instancia del objeto "Base de datos" y verifica el nivel de acceso de los usuarios.

Si el usuario tiene acceso, la función "showProducts()" crea otra instancia del objeto "Base de datos" y consulta la base de datos.

class Database{ 

    public function query(){ 
     //runs query here 
    } 

    public function __construct() { 
     //sets up connection here 
    } 

} 

class User{ 

    public function checkAccess(){ 
     $db = new Database(); 
     $db->query(//pass in query to check access) 
     //does stuff, then returns true or false 
    } 

} 

class Products{ 

    public function showProducts(){ 

     $user = new User(); 

     if($user->checkAccess()) 
     $db = new Database(); 
     $db->query(//pass in query to get products) 
     } 

} 

Esperaba que alguien pudiera ilustrar cómo hacerlo de la manera correcta.

Me gustaría tener algún tipo de clase de controlador, que crea un objeto "Base de datos", que está disponible para todas las clases que necesitan acceder a él, sin tener que crear múltiples instancias del objeto "Base de datos". Me gustaría lo mismo con la clase de usuarios, por lo que hay un objeto $ users al que todas las clases pueden acceder, sin tener que crear un nuevo objeto cada vez que necesito usar algo en la clase "Usuario".

¡Pido disculpas si mi pregunta no está clara, y gracias de antemano por cualquier respuesta!

Gracias a todos por las respuestas!

Respuesta

11

Al pasar de procedimiento a programación orientada a objetos, debe comprender más que solo cómo crear clases. OOP no está escribiendo clases, se trata de seguir las mejores prácticas, principios y patrones en OOP.

No debe instanciar objetos nuevos dentro de otra, debe proporcionar el objeto Usuario, su objeto Base de Datos del que depende el Usuario, mediante el constructor o el método setter. Eso se llama Inyección de Dependencia. El objetivo es dar objetos a una clase que los necesite a través del método de constructor o instalador. Y deben ser instanciados desde fuera de esa clase, por lo que es más fácil configurar la clase. Y al construir una clase, es fácil ver qué dependencias tiene esa clase. Se puede leer sobre Inversión del Principio de control aquí: IoC

Entonces el código se vería así:

<?php 

// User object that depends on Database object, and expects it in constructor. 

class User 
{ 
    protected $database; 

    public function __construct($database) 
    { 
     $this->database = $database; 
    } 

    // -- SNIP -- 
} 

?> 

ahora de usar esa clase de usuario que hace esto:

<?php 

    $database = new Database($connParams); 
    $user = new User($database); 

?> 

Puede también use Dependency Injection usando métodos setter para establecer dependencias, pero Il le permite googlearlo usted mismo :)

Eso es, joust lea acerca de Inversion of Contro Todo el principio, y sobre Inyección de Dependencia y Contenedores de Inyección de Dependencia, estas son las mejores formas de administrar las clases.

He visto un montón de código PHP que es "OOP" y de hecho solo están utilizando clases como espacios de nombres de funcionalidad :) Así que aprende sobre los principios y patrones de OOP.

¡Diviértete! :)

+0

¡Muchas gracias por la respuesta!Entonces, si tuviera otra clase que hiciera referencia en la clase de usuario, ¿pasaría también el objeto $ usuario como parámetro? – Ben

+0

¡Sí, puedes! Puedes pasar tantas clases como quieras. Puede pasar el objeto a través del constructor si el objeto realmente necesita que ese objeto funcione. Y puede pasarlo a través del método setter si el objeto es opcional. Una vez que obtenga dependencias complicadas, entonces puede pensar en usar Dependency Injection Container donde describiría dependencias y Container podría ensamblar objetos de otros objetos y devolvérselos a usted :) Puede leer más sobre Inyección de Dependencia y Contenedor de Inyección de Dependencia aquí : http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container – otporan

0

Para hacer que un objeto por toda su uso Singleton código de patrón:

class Database{ 
    private $db_descriptor; 

    private function __construct(){ 
     /* connect and other stuff */ 
    } 
    public static function getInstance(){ 
     static $instance; 
     if($instance === null){ 
      $instance = new self(); 
     } 
     return $instance; 
    } 
} 

y se puede utilizar la misma técnica con los usuarios, que decir más con PHP 5.4 se puede utilizar 1 rasgo para el patrón Singleton. Un último consejo: cuando trabajas con bases de datos y otras cosas pesadas usa la técnica llamada lazy initialization. Cuando mejoras tus habilidades OOP mira Doctrine Project ¡usan mucho esas técnicas!

+0

En realidad, yo recomendaría buscar ejemplos de frameworks empresariales ahora para tener una idea de cómo se hacen las cosas. Puede que no necesite usar el inmediato, pero le darán una buena idea de cómo estructurar las cosas. – prodigitalson

+0

¿Puede usted aconsejar alguno? No trabajé con ellos antes. – kirugan

+1

Symfony2 y Zend2 Frameworks son los únicos marcos que vale la pena mirar :) Sé que obtendré muchos votos negativos para esto. ¡Pero esos dos son los mejores para aprender OOP apropiado en PHP! – Limeni

2

No crea objetos en sus constructores u otros métodos. Páselos como parámetro, preferiblemente dentro de una clase diferente conocida como fábrica. Esto hará que sea más fácil probar el código, pero también facilitar la creación de los objetos.

Además, no intente utilizar singletons. Esta es la versión orientada a objetos de "variables globales", y no desea usar variables globales. Hace que probar tu código sea realmente difícil, casi imposible.

Mire este video http://www.youtube.com/watch?v=-FRm3VPhseI para comprender por qué es malo usar singletons. Especialmente vale la pena ver el ejemplo de CreditCard a las 19:00.

Si realmente quiere hacerlo de última generación, eche un vistazo al concepto de "inyección de dependencia". Esencialmente, pasar todo lo que se necesita desde el exterior a una clase es todo un secreto, pero hay marcos que lo hacen por usted automáticamente, por lo que ya no tiene que escribir una fábrica. Estos se llaman "Contenedor de inyección de dependencia" o "DIC".

+0

¡Muchas gracias! Googleing clase de fábrica ahora. ¿Conoces algún buen tutorial general sobre la configuración de estructuras de clase para sitios web? Estoy empezando a entender los principios, pero en cuanto a la implementación práctica, todavía estoy un poco perdido. – Ben

+0

Primero, le recomiendo que eche un vistazo a la carga automática. Hay varios sistemas para que esto sea fácil, pero se reduce a organizar sus clases, una clase por archivo, en un árbol de directorios, y alinear los nombres de clase en consecuencia para que el autocargador, que solo obtiene el nombre de clase necesario como parámetro, pueda construir la ruta y el nombre del archivo en el que se supone que está la clase. Eche un vistazo al Zend Framework (1 o 2) para ver un ejemplo viviente. También puede tener una idea de cómo otras personas nombran sus clases allí. – Sven