2016-05-28 9 views
2

Derzeit eine Abfrage mit PDO auszuführen, verwende ich die folgenden Codezeilen:Stenografie PDO Abfrage

$sql = "SELECT * FROM myTable WHERE id = :id"; 
$stmt = $conn->prepare($sql); 
$stmt->bindParam(':id', $id); 
$stmt->execute(); 
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

Und nach einigen Recherchen fand ich einen kürzeren Weg, um den gleichen Befehl ausführt:

$stmt_test = $conn->prepare("SELECT * FROM status WHERE status_id = ?"); 
$stmt_test->execute([$id])->fetchAll(PDO::FETCH_ASSOC); 
$result = $stmt_test->fetchAll(PDO::FETCH_ASSOC); 

Von dort dachte ich, dass ich vielleicht sogar kürzer mit dem folgenden Code machen könnte:

$stmt_test = $conn->prepare("SELECT * FROM status WHERE status_id = ?"); 
$result = $stmt_test->execute([$id])->fetchAll(PDO::FETCH_ASSOC); 

Aber ich bekomme den folgenden ihn ror:

Fatal error: Call to a member function fetchAll() on a non-object in /home/.../index.php on line 20

FRAGE: Warum erhalte ich diesen Fehler? Von meinem Verständnis, $stmt_test->execute([$id]) sollte zuerst ausgeführt werden, dann würde das Ergebnis davon ->fetchAll(PDO::FETCH_ASSOC) ausführen und von dort das Array auf $result zurückgeben, aber da der Fehler passiert, muss etwas in meiner Logik fehlerhaft sein. Was mache ich falsch? Kennt jemand eine bessere Kurzschreibmethode zum Ausführen der vorherigen Abfrage?

+0

Mögliches Duplikat [PDO - Call auf eine Elementfunktion holen() auf einem Nicht-Objekt] (http://stackoverflow.com/questions/ 12126193/pdo-call-to-a-member-function-fetch-on-a-non-object) – johannes

+0

@johannes Obwohl der Fehler einen ähnlichen Namen hat, unterscheiden sich die Situationen, in denen der Fehler verursacht wird. – Webeng

+0

Ah habe nicht sorgfältig genug gelesen, werde unten antworten. – johannes

Antwort

6

So haben Sie eine Antwort auf die Frage bekommen „Warum ich diese Störung erhalten“, aber nicht eine für die „Kurzschrift PDO Abfrage“ habe.

Dafür brauchen wir etwas "Programmierung" genannt.

Eine interessante Sache bei der Programmierung ist, dass wir nicht wie bei anderen Berufen auf die vorhandenen Werkzeuge beschränkt sind. Mit der Programmierung können wir immer ein eigenes Werkzeug erstellen und es dann anstelle eines alten verwenden.

Und Object Oriented Programming ist besonders gut damit, da wir ein vorhandenes Objekt nehmen und nur etwas Funktionalität hinzufügen können, so dass der Rest wie er ist.

Stellen Sie sich beispielsweise vor, wir möchten eine Kurzform, um eine vorbereitete Anfrage in PDO auszuführen. Alles, was wir brauchen, ist, das PDO-Objekt mit einer neuen Kurzschreibweise zu erweitern. Der schwierigste Teil ist, der neuen Methode einen Namen zu geben.

Der Rest ist einfach: you need only few lines of code

class MyPDO extends PDO 
{ 
    public function run($sql, $bind = NULL) 
    { 
     $stmt = $this->prepare($sql); 
     $stmt->execute($bind); 
     return $stmt; 
    } 
} 

Dies ist der gesamte Code Sie benötigen. Sie können es in derselben Datei speichern, in der Sie Ihre Datenbankanmeldeinformationen speichern. Beachten Sie, dass dieser Zusatz in keiner Weise Ihren bestehenden Code beeinflusst - er bleibt genau derselbe und Sie können weiterhin wie gewohnt alle vorhandenen PDO-Methoden verwenden.

Jetzt müssen Sie nur zwei Buchstaben im PDO-Konstruktor ändern, als

$conn = new MyPDO(...the rest is exactly the same...); 

aufrufen und sofort können Sie beginnen, Ihr glänzendes neues Werkzeug:

$sql = "SELECT * FROM myTable WHERE id = :id"; 
$result = $conn->run($sql, ['id' => $id])->fetchAll(PDO::FETCH_ASSOC); 

Oder, um es ein wenig zu geben die Optimierung

$result = $conn->run("SELECT * FROM myTable WHERE id = ?", [$id])->fetchAll(); 

wie Sie Modus ein für alle Male immer gesetzt Standard holen können, und für nur singen Für den benannten Platzhalter gibt es keine Variable. Welche diesen Code auf die akzeptierte Antwort, eine echte Stenografie Vergleich macht

$stmt_test = $conn->prepare("SELECT * FROM status WHERE status_id = ?"); 
$stmt_test->execute([$id]); 
$result = $stmt_test->fetchAll(PDO::FETCH_ASSOC); 

und sogar die beste Antwort, die Sie so weit haben,

$result = $conn->prepare("SELECT * FROM status WHERE status_id = ?"); 
$result->execute([$id]); 

nicht zu erwähnen, dass dieser nicht immer verwendbar, da es nur für ein Array geeignet ist. Während mit einer realen Stenografie jeden Ergebnis-Format ist möglich:

$result = $conn->run($sql, [$id])->fetchAll(); // array 
$result = $conn->run($sql, [$id])->fetch(); // single row 
$result = $conn->run($sql, [$id])->fetchColumn(); // single value 
$result = $conn->run($sql, [$id])->fetchAll(PDO::FETCH_*); // dozens of different formats 
+0

lol Punkt gut gemacht, das war eine sehr vollständige Antwort und zweifellos die ehrenhafte grüne Häkchen – Webeng

+0

Vielen Dank. Dieses Zeichen ist eigentlich nicht für mich, sondern für die anderen Entwickler, die nach der Kurzschreib-PDO-Funktion suchen. Wie ich annehme, ist meine Lösung die einzige, die wirklich die Frage beantwortet und nicht nur das Problem zulässt. –

+0

Erstellen einer Wrapper-Klasse für PDO scheint wie Overkill-Imo, definitiv für das Erstellen einer Methode, die einfach zwei Methoden zu einer kombiniert. Die Antwort ist, dass es keinen schnelleren Weg gibt, vorbereitete Anweisungen mit PDO auszuführen. Es ist eine große Antwort, tho, muss mit Ihnen auf diesem einen zustimmen. – JasonK

4

$stmt_test->execute([$id]) gibt einen boolean Wert zurück. Das bedeutet, dass

$result = $stmt_test->execute([$id])->fetchAll(PDO::FETCH_ASSOC); 

nicht gültig ist. Stattdessen sollten Sie

$stmt_test->execute([$id]); 
$result = $stmt_test->fetchAll(PDO::FETCH_ASSOC); 
+0

perfekte Antwort. Ich akzeptiere diese Antwort, wenn die Zeitlimitierung abgelaufen ist. Es war nicht klar, dass der '$ stmt_test' einen booleschen Wert zurückgab, daher wurde' fetchAll' auf diesen Rückgabewert und nicht auf $ stmt_test selbst angewendet. – Webeng

+1

@Webeng Ich würde diese Antwort nicht als perfekt bezeichnen, da sie nirgendwohin Ihren Code verkürzt. –

0

glaube ich PDOs execute() Methode entweder wahr oder falsch zurückgibt. Wie der Fehler bereits sagt: fetchAll() erwartet ein Objekt. Die Verwendung von drei Codezeilen wäre der kürzeste Weg.

Eine andere Option ist die Verwendung eines ORM wie propel, es funktioniert wirklich reibungslos und spart Ihnen viel Zeit.

+0

Antworten, die ein Tool empfehlen, werden immer von dem realen Anwendungsbeispiel profitieren, das für die Anforderungen des OP geeignet ist. Sonst werden sie nicht beachtet. –

1

Der Fehler, den Sie bekommen, stammt aus der Art, wie PDO entworfen wurde. PDOStatement::execute() gibt die Anweisung nicht zurück, sondern einen booleschen Wert, der den Erfolg anzeigt. Die gewünschte Verknüpfung ist daher nicht möglich.

Siehe Funktionsdefinition in http://php.net/manual/en/pdostatement.execute.php

lassen Sie mich außerdem, dass forEach add() oft (nicht immer) ist ein Code Geruch und nimmt relativ viel Speicher wie es alle Zeilen als PHP-Werte zu speichern hat.

+0

Oh, also würdest du mir empfehlen, zu 'while ($ row = $ stmt_test-> fetch (PDO :: FETCH_ASSOC)) {...} zu wechseln, damit ich' foreach ($ result as ...) 'mit meinem obigen Code? – Webeng

+0

PDOStarement implementiert traversable, so dass Sie 'foreach ($ stmt_test as ...)' (ich muss zugeben, ich bin mir nicht sicher, welcher Modus dies ist, könnte PDO :: FETCH_BOTH sein) mit diesem Ansatz Sie immer sind haben Sie einfach das aktuelle Element im Speicher und iterieren es nur einmal oder zweimal – johannes

+0

und welcher Ansatz ist derjenige, der es zweimal macht?xD Ich bin mir nicht sicher, ob ich verstanden habe, ob es Code ist, der es zweimal macht, und jetzt bin ich wirklich interessiert daran, hahah – Webeng

-1

Dies ist wahrscheinlich das kürzeste Beispiel.

$fetchAll = function ($id) use (&$pdo) { 
    $stmt = $pdo->prepare("SELECT * FROM `status` WHERE `status_id` = ?"); 
    $stmt->execute([$id]); 
    return $stmt->fetchAll(PDO::FETCH_ASSOC); 
}; 
print_r($fetchAll($id)); 
+0

@Webeng Ja das hat er gemacht, deshalb habe ich nur die gekürzte Version geschrieben. '$ stmt_test-> execute ([$ id]) gibt einen booleschen Wert zurück.' ist die Antwort für den Fehler und für diese Frage. –

+0

Dieses Beispiel widerspricht den Bedingungen im OP. Ich frage mich, warum sollte irgendjemand es lauter machen? –

+0

genau welche Bedingung hat das OP diese Antwort widersprochen? @ YourCommonSense beim nächsten Mal könnte ich eine schnelle Klasse für eine Antwort präsentieren. ODER ist nicht die Hauptbedingung diese im Titel 'shorthand PDO query'. Ich dachte wirklich, dass es dieser Teil ist ... "Kurzschrift". Ich dachte wirklich, dass sein Hauptzweck darin bestand, seinen Code zu verkürzen. Und in dieser Antwort widerspricht mein Beispiel den OP-Bedingungen? Ich mag dich, du bist lustig, bist du ein Komiker? Danke für die Abstimmung, aber ich werde nicht antworten, Sie sehen, da Ihre Antwort richtig ist, werde ich es nicht tun. Aber es ist definitiv außerhalb der "verkürzten" Erwartungen von OP. –