¿Alternativa a usar una variable global en una clase?

Comencé a aprender cómo usar OOP y creé una clase de autorización de usuario para verificar si el usuario existe, etc. Actualmente estoy conectado a la base de datos usando la variable global $dbh que es una conexión PDO. Escuché que usar variables globales de esta manera no es una buena práctica, pero no estoy seguro de cómo puedo mejorarlo, ¿simplemente pasaría el $dbh variable en el método que lo requiere cuando se conecta a una base de datos y por qué exactamente esto no se considera una buena práctica?

Aquí hay un código que estoy usando:

Conexión de base de datos PDO incluida en el programa de llamada:

//test the connection
    try{
        //connect to the database
        $dbh = new PDO("mysql:host=localhost;dbname=oopforum","root", "usbw");

    //if there is an error catch it here
    } catch( PDOException $e ) {
        //display the error
        echo $e->getMessage();
    }

La clase que requiere la conexión a la base de datos:

class Auth{

        private $dbh;

        function __construct(){

            global $dbh;
            $this->dbh = $dbh;
        }

        function validateLogin($username, $password){

            // create query (placing inside if statement for error handling)
            if($stmt = $this->dbh->prepare("SELECT * FROM oopforumusers WHERE username = ? AND password = ?")){

                $stmt->bind_param(1, $username);
                $stmt->bind_param(2, $password);
                $stmt->execute();


                // Check rows returned
                $numrows = $stmt->rowCount();

                //if there is a match continue
                if( $numrows > 0 ){
                    $stmt->close();
                    return TRUE;
                }else{
                    $stmt->close();
                    return FALSE;
                }

            }else{
                die('ERROR: Could not prepare statement');
            }

        }


        function checkLoginStatus(){

            if(isset($_SESSION['loggedin'])){

                return TRUE;

            }else{

                return FALSE;

            }

        }

        function logout(){

            session_destroy();
            session_start();

        }
    }

preguntado el 30 de junio de 12 a las 17:06

3 Respuestas

Debe pasar la conexión PDO al constructor:

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

La conexión se llama dependencia de su clase porque obviamente su clase lo necesita para llevar a cabo su función. La buena práctica dicta que su clase debe hacerlo explícito que esta dependencia existe; esto se logra convirtiéndolo en un parámetro constructor obligatorio.

Si, en cambio, extrae la dependencia de una variable global, crea varios problemas:

  • No está nada claro para un usuario de su clase que existe una dependencia en primer lugar
  • Su clase ahora está acoplada a la variable global, lo que significa que la variable no se puede eliminar o renombrar sin romper el programa
  • Ha creado las condiciones previas para la "acción a distancia": modificar el valor de la variable global hace que otra parte (aparentemente no relacionada) de su aplicación cambie el comportamiento

Respondido el 30 de junio de 12 a las 18:06

¿Qué sucede si necesito crear un instante de una clase dentro de una clase que paso la conexión DB al constructor de la misma? - Mostafa

En mi clase de usuario, llamo new User().. y ahora, ¿cómo le envío la conexión Db? - Mostafa

Simplemente puede pasarlo al constructor.

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

Cuando creas un objeto, haces:

$obj = new Class($dbh);

Respondido el 30 de junio de 12 a las 18:06

Pase el objeto de la base de datos a través del constructor. El modelo de objetos de PHP significa que = crea nuevas referencias a la misma instancia de un objeto.

class ThingThatDependsOnDatabase
{
    private $db = NULL;

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

    public function selectSomething ($id)
    {
        $sql = 'SELECT * FROM table WHERE id = ?;'
        $this -> db -> prepare ($sql);
        // And so on
    }
}

Este es un ejemplo de un patrón llamado Inyección de dependencia, porque las cosas de las que depende su clase se inyectan a través de un método (setter, constructor, etc.).

Respondido el 30 de junio de 12 a las 18:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.