3

Tengo dos archivos, uno llamado connection.php y otro llamado suggest.php, en connection.php hago la conexión perfectamente con una función llamada connectDB y la utilizo sin ningún problema en suggest.php.

Sin embargo, tengo otra función en la cual quiero desplegar con un SELECT la información de mi base de datos, y me gustaría hacerlo a través de una función también. El error que me arroja PHP es el siguiente:

Fatal error: Call to a member function query() on null in C:\AppServ\www\object\db\inc\connection.php on line 18

No soy muy experto pero creo que tiene que ver con el ámbito de la variable, ya que dentro de la función connectDB esta la variable(objeto) $db.

¿Esa variable puedo hacerla global para poder utilizarla en todas las funciones? ¿Cómo puedo hacerlo?

suggest.php

<?php 
  include 'connection.php';

  connectDB('root','administrador');
  selectMedia();
?>

connection.php

  function connectDB($user, $pass, $dsn = 'mysql:host=localhost;dbname=database'){
    try {
      $db = new PDO($dsn, $user, $pass);
      $db->setAttribute(PDO::ATTR_CASE,PDO::CASE_UPPER);

    } catch (Exception $e) {
      echo "Error: " . $e->getMessage()."<br>";
      echo "Código de excepción: " . $e->getCode()."<br>";
      echo "Línea fuente: " . $e->getLine()."<br>";
      echo "Archivo: " . $e->getFile();
    }
  }

  function selectMedia(){
    try {
      $results = $db->query("SELECT title, category FROM Media");
      echo "Cool!";
    } catch (Exception $e) {
      echo "Error: " . $e->getMessage();
    }
  }

  ?>
Hoose
  • 2,993
  • 5
  • 22
  • 52

5 Answers5

2

Crear una variable global no es una buena practica / Globals are evil

Puedes crear un fichero global donde guardas por ejemplo todas tus funciones esenciales para tu aplicación, en este caso sería por ejemplo la configuración para conectar a tu base de datos connectDB(...).

connection.php

<?php

$dsn  = 'mysql:host=localhost;dbname=database'
$user = 'root'
$pass = 'administrador' 


function connectDB($user, $pass, $dsn){

    try {
        $db = new PDO($dsn, $user, $pass);
        $db->setAttribute(PDO::ATTR_CASE,PDO::CASE_UPPER);

    } catch (Exception $e) {
        echo "Error: " . $e->getMessage()."<br>";
        echo "Código de excepción: " . $e->getCode()."<br>";
        echo "Línea fuente: " . $e->getLine()."<br>";
        echo "Archivo: " . $e->getFile();
    }
}

// Aquí lo llamas solo una vez
$db = connectDB($user, $pass, $dsn);


//.... más funciones

function selectMedia($db){

    try {
        $results = $db->query("SELECT title, category FROM Media");
        echo "Cool!";
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage();
    }
  }

Una vez creado el fichero global lo incluyes en cualquier fichero donde siempre lo necesites.

cualquierFichero.php

<?php

// cambiado a require_once
require_once 'connection.php';  

selectMedia($db);

otraFuncionQueNecesitaDB($db);
Black Sheep
  • 13,096
  • 6
  • 36
  • 60
  • ¡Perfecto! Funciona pero no tal como esperaba por que sigue sin ser una variable global. ¿Qué pasa si quiero hacer una función updateMedia()? Tengo que volver a poner $db = connectDB('root','administrador'); y no es lo que quiero precisamente, solo quiero ponerlo una vez. – Hoose Oct 21 '16 at 13:07
  • 1
    He mejorado las respuesta... si necesitas de verdad una variable `global` lo puedes crear dentro de la función `connectDB()` [aquí](http://php.net/manual/es/language.variables.scope.php#language.variables.scope.global) puedes leer más como crearlo y llamar a las variables `global`. – Black Sheep Oct 21 '16 at 13:51
  • ¡Muchas gracias! Eso pedía, y un plus el saber las desventajas de las variables globales. – Hoose Oct 22 '16 at 23:31
1

Una sola acotacion a la solucion que propuso @aldanux, si tu archivo connection.php es llamado en varios archivos, te recomiendo ocupar include_once

include_once 'connection.php';

Esto hace exactamente lo mismo que un include normal, pero si tu archivo ya fue incluido, no lo vuelve a incluir, esto te evitara errores por variables ya definidas.

0

Mas elegante seria crear una clase, en un .php aparte, y utilizar el patrón singleton para tener una unica instancia del objeto que quieres crear (en este caso tu supuesta variable global) de forma de poder acceder siempre desde cualquier lado a ella y que esté siempre instanciada y con un valor unico a todo el proyecto. Te dejo un link para que te orientes: https://www.uno-de-piera.com/el-patron-singleton-en-php/

Emiliano Torres
  • 1,064
  • 9
  • 18
0

¿Tal vez te estás complicando en vano? Creo que todo lo solucionarías con un simple return en tu función:

function connectDB($user, $pass, $dsn){
  try {
    $db = new PDO($dsn, $user, $pass);
    $db->setAttribute(PDO::ATTR_CASE,PDO::CASE_UPPER);
    return $db;

  } catch (Exception $e) {
    echo "Error: " . $e->getMessage()."<br>";
    echo "Código de excepción: " . $e->getCode()."<br>";
    echo "Línea fuente: " . $e->getLine()."<br>";
    echo "Archivo: " . $e->getFile();
    return false;
  }
}
lalengua
  • 640
  • 4
  • 13
0

Algo más sencillo y menos complicación, sobre todo obtenemos una function más limpia es crear un archivo config.ini.php

Y en el documento PHP que requiera conexiones a la base de datos, llamarlas por medio de include_once

include_once 'config.ini.php';

Dentro del archivo creas la conexión, imaginando que la variable $con tenga los valores de la conexión.

Sólo bastaría añadir una de las palabras reservadas de PHP global a la function

Ejemplo:

function selectMedia(){...
  global $con; //Con esto ya tendrías los valores de la conexión

   // Código
}
Otto
  • 632
  • 5
  • 22
  • 48