2010-12-16 44 views
12

Estoy tratando de escribir una función de PHP. Es muy simple. Es solo una declaración preparada que consulta la base de datos, pero no puedo hacer que funcione. Sigo recibiendo el error Llamar a una función de miembro prepare() en un no objeto. aquí está el código:Llamar a una función miembro prepare() en un objeto PHP Ayuda

$DBH = new mysqli("host", "test", "123456", "dbname"); 
function selectInfo($limit, $offset){ 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
    } 
selectInfo(); 

Cada vez que llamo a la función me sale ese error. ¿Puede ayudarme alguien, por favor?

Respuesta

43

Es un error de alcance. Está haciendo $DBH una variable global. Entonces, cuando ingresas a la función, la variable global no está disponible. Tienes 5 opciones reales.

1. Usar la palabra clave mundial

function doSomething() { 
    global $DBH; 
    //... 

Esto no es una buena idea, ya que hace que el mantenimiento y prueba de un PITA. Imagina intentar depurar esa llamada de función. Ahora tiene que ir a averiguar dónde $DBH se define para tratar de averiguar lo que está pasando ...

2. Hacer $DBH un parámetro a la función

function doSomething(MySQLi $DBH) { 

Tiene la ventaja de ser explícito. Pero todavía no es excelente, ya que el código de llamada necesita realizar un seguimiento de la variable global.

3. Crear una función para "obtener" el objeto $DBH

function getDBH() { 
    static $DBH = null; 
    if (is_null($DBH)) { 
     $DBH = new mysqli(...); 
    } 
    return $DBH; 
} 

function doSomething() { 
    $DBH = getDBH(); 
} 

Esto tiene la ventaja de moverse por el problema variable global completo. Pero también es difícil tener conexiones múltiples o reutilizar cualquiera de los códigos para otras conexiones.

4. Crear una clase para envolver el acceso de base de datos

class Database { 
    public function __construct($host, $user, $pass) { 
     $this->DBH = new MySQli($host, $user, $pass); 
    } 
    public function doSOmething() { 
     $this->DBH->foo(); 
    } 
} 

Esto encapsula todo para usted. Todo el acceso a la base de datos pasará por una única clase, por lo que no tendrá que preocuparse por el acceso variable global o cualquier otra cosa.

5. Utilice una clase/marco pre-construidos

esta es la mejor opción, ya que no es necesario que preocuparse de hacerlo usted mismo.

clases de base de datos de acceso:

marcos completos:

Realmente, las opciones son infinitas. Encuentre algo que le guste y quédese con él. Realmente hará tu vida más fácil ...

¡Buena suerte!

+1

+1 Bonito conjunto de opciones. –

+0

no funcionó para mí: http://stackoverflow.com/questions/40080426/fatal-error-call-to-a-member-function-prepare-on-a-non-object-in-but-value – fresher

3

Intente agregar global $DBH; en la función, o agréguelo a los parámetros de la función.

3
selectInfo($DBH); 

function selectInfo($DBH,$limit, $offset){ 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
    } 
7

$DBH no aplica en el alcance. O lo que desee definir como $DBH global en la función:

$DBH = new mysqli("host", "test", "123456", "dbname"); 
function selectInfo($limit, $offset){ 
    global $DBH; 
    $stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?"); 
    $stmt->bind_param("ii", $limit, $offset); 
    $stmt->execute(); 
} 

o como ircmaxell señaló en su excelente respuesta tiene una función que devuelve una instancia estática de $DBH.

+0

Gracias. ¿Cómo podría hacer que sea global y aún así mantener las cosas seguras? ¿Envolvería la conexión en una función y luego le asignaría una variable como function connect() {new myqsli ("host", "test", "123456", "dbname")} $ DBH = new connect(); (Las variables de conexión están realmente ocultas en otro archivo). – mcbeav

+0

Sí, haría algún tipo de función y tomaré la conexión desde allí. – Jim

+0

@ircmaxell Listo. Estas en lo correcto, por su puesto. Hacer una nueva conexión para cada llamada de método es una mala idea. – Jim

3

Eso es simplemente. $DBH no existe dentro de la función selectInfo(). La variable definida en el alcance global no será visible dentro de la función y viceversa. Lea más sobre variables scope en las páginas de manual.

¿Cómo resolverlo? Pase esa variable como argumento de la función:

$dbh = new MySQLi(...); 

function selectInfo(MySQLi $dbh, $limit, $offset) { 
    $stmt = $dbh->prepare(...); 
    ... 
} 
3

Asegúrese de que la conexión sea correcta.

$DBH = @new mysqli("host", "test", "123456", "dbname"); 

if ($DBH->connect_errno) { 
    die('Connect Error: ' . $DBH->connect_errno); 
} 

o

$DBH = @mysqli_connect("host", "test", "123456", "dbname"); 

if (!$DBH) { 
    die('Connect Error: ' . mysqli_connect_errno()); 
} 
0

Haciendo $ DAP global no es saludable ... excepto que usted puede hacer su DAP $ protegida en clase y la puso en nulo .. y usarlo ..

0
class PDOconnect extends PDO{ 

protected $ con = nulo;

public function __construct(){ 
       try {  

        $this->con= new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); //our new PDO Object 

         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);      
         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);      
         $this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
         echo "hi.. you are connected succcessfully..."; 
        } 
Cuestiones relacionadas