2010-12-16 4 views
12

Ich versuche, eine PHP-Funktion zu schreiben. Es ist sehr einfach. Es ist nur eine vorbereitete Anweisung, die die Datenbank abfragt, aber ich kann das nicht zum Laufen bringen. Ich erhalte den Fehler Aufruf an eine Elementfunktion prepare() für ein Nicht-Objekt. Hier ist der Code:Aufruf an eine Member-Funktion Prepare() auf einem Nicht-Objekt PHP Help

$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(); 

Immer wenn ich die Funktion aufrufen, bekomme ich diesen Fehler. Kann mir bitte jemand helfen?

Antwort

43

Es ist ein Scoping-Fehler. Sie machen $DBH eine globale Variable. Wenn Sie die Funktion eingeben, ist die globale Variable nicht verfügbar. Sie haben 5 echte Optionen.

1. Verwenden Sie das Schlüsselwort global

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

Dies ist keine gute Idee, da es die Wartung und Prüfung einer PITA macht. Stellen Sie sich vor, Sie versuchen diesen Funktionsaufruf zu debuggen. Sie müssen jetzt gehen, herauszufinden, wo $DBH definiert, um zu versuchen, um herauszufinden, was los ist ...

2. Stellen Sie $DBH ein Parameter an die Funktion

function doSomething(MySQLi $DBH) { 

Es hat den Vorteil, explizit. Aber es ist immer noch nicht großartig, da der aufrufende Code dann die globale Variable verfolgen muss.

3. Erstellen Sie eine Funktion zu "get" die $DBH Objekt

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

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

Dies hat den Vorteil der globalen Variablen Problem um immer vollständig. Es ist aber auch schwierig, mehrere Verbindungen zu haben oder den Code für andere Verbindungen wiederzuverwenden.

4. Erstellen Sie eine Klasse Zugriff auf die Datenbank

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

Diese kapselt alles für Sie zu wickeln. Der gesamte Datenbankzugriff erfolgt über eine einzige Klasse, sodass Sie sich keine Gedanken über den globalen Variablenzugriff oder etwas anderes machen müssen.

5. Verwenden Sie eine vordefinierte Klasse/Rahmen

Dies ist die beste Option, da Sie es zu tun, sich nicht kümmern müssen.

Database Access Klassen:

Voll Frameworks:

Wirklich, die Möglichkeiten sind endlos. Finde etwas, das du magst und bleibe dabei. Es wird Ihr Leben wirklich einfacher machen ...

Viel Glück!

+1

+1 Schöne Reihe von Optionen. –

+0

es funktionierte nicht für mich: http://stackoverflow.com/questions/40080426/fatal-error-call-to-a-member-function-prepare-on-a-non-object-in-but-value – fresher

3

Versuchen Sie, global $DBH; in die Funktion einzufügen, oder fügen Sie sie zu den Funktionsparametern hinzu.

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 ist nicht im Anwendungsbereich. Sie wollen entweder $DBH als global in der Funktion definieren:

$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(); 
} 

oder als ircmaxell in seiner ausgezeichneten Antwort darauf hingewiesen haben eine Funktion, die eine statische Instanz von $DBH zurückgibt.

+0

Danke. Wie würde ich das global machen und die Dinge trotzdem sicher halten? Würde ich die Verbindung in eine Funktion einfügen und dann eine Variable zuweisen wie Funktion connect() {new myqsli ("host", "test", "123456", "dbname")} $ DBH = new connect(); (Die Verbindungsvariablen sind tatsächlich in einer anderen Datei versteckt.) – mcbeav

+0

Ja, ich würde eine Art von Funktion machen und die Verbindung von dort abholen. – Jim

+0

@ircmaxell Fertig. Du hast natürlich Recht. Es ist keine gute Idee, eine neue Verbindung für jeden Methodenaufruf herzustellen. – Jim

3

Das ist einfach. $DBH existiert nicht innerhalb selectInfo() Funktion. Die im globalen Gültigkeitsbereich definierte Variable ist in der Funktion nicht sichtbar und umgekehrt. Lesen Sie mehr über variables scope auf manuellen Seiten.

Wie löst man es? Übergeben Sie diese Variable als Argument der Funktion:

$dbh = new MySQLi(...); 

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

Sicherstellen, dass die Verbindung erfolgreich hergestellt wurde.

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

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

oder

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

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

machen $ DBH global ist nicht gesund ... außer dass Sie Ihre $ DBH geschützt in der Klasse zu machen und legen Sie es null auf .. und es verwenden ..

0
class PDOconnect extends PDO{ 

protected $ con = Null;

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..."; 
        } 
Verwandte Themen