MSQL zu PDO Fragen zu Formatierung!

DualityMind

Lieutenant
Registriert
Dez. 2015
Beiträge
768
Hallo CBler

Ich bin gerade dabei meine Webseite von MySQL Abfragen zu PDO Abfragen umzuschreiben.

Leider stosse ich immer wieder auf Probleme. Verstehe das ganze Konstrukt noch nicht ganz.

Habe jetzt z.B. diesen Code, mit dem ich von "pt_artikel" die neuesten 5 Artikel auf einer Admin Seite anzuzeigen:

PHP:
   $stmt = $pdo->query("SELECT * FROM pt_artikel where exp_date < $time ORDER BY exp_date DESC LIMIT 5");

while ($row = $stmt->fetch())
        {    

    $picnr = $pdo->query("SELECT artikel_id FROM pt_pictureartikel WHERE artikel_id = $row[freegame_id] ORDER BY exp_date DESC");

 
$tmp = getimagesize("../artikel/img/thumbnail/".$picnr['picture_id'].".".$picnr['ext']."");
                                         
    echo  "<tr><td style=padding-left:10px; align=\"left\" bgcolor=$bgcolor width=120><font size=\"-3\"><img src=\"../artikel/img/thumbnail/{$row['picture_id']}.{$row['ext']}\" align=center valign=middle height=\"60\" width=90  class=blackbox border=\"0\">";
                                 
                    echo  substr( $row['artikel_name'], 0, 60 );
                       
 
$dazu++;
$i++;
   $dazu2++;
         
                                }
    ?>

Im alten Code habe ich in der "While Schleife" noch einmal einen Mysql Aufruf, um die Bilder von einer anderen Datenbank Spalte abzurufen. Leider komme ich da bereits an meine Grenzen.

Irgendwie muss ich vom ersten PDO Aufruf, die "Freegame_id" übermitteln in die "While Schleife", wo das "Picture_id" von der "Artikel_id" vom 1th PDO Datenbankaufruf.

Habe den Code Teilweise gelöscht. Im Admin auf meiner Webseite kommen alle Artikel Name und weitere Angaben.

Den Artikel_Name zeigt er zu jedem Artikel korrekt an, also nicht immer das gleiche.

Beim Bild habe ich jetzt die grössten Probleme. Verstehe einfach noch nicht für was das Prepare und Execute benötigt wird ?

Muss die Webseite bis März 2019 Umgeschrieben haben, ansonsten läuft meine Webseite nicht mehr weiter :-((( !

Bitte bitte kann sich jemand kurz Zeit nehmen, wäre sehr froh :-) !

LG
 
Der Aufbau ist leider komplett falsch für PDO. Du baust hier Sicherheitslücken in deine SQL Abfrage ein.

PDO funktioniert grundsätzlich so (Beispiel):

PHP:
//SQL Abfrage mit Platzhalter
$sql = 'SELECT * FROM users WHERE author = :author';

//Statement vorbereiten
$stmt = $pdo->prepare($sql);

//Platzhalter an das Statement binden und ausführen
$stmt->execute([":author" => $author]);
 
  • Gefällt mir
Reaktionen: DubZ und Joshinator
Ich würde zudem deine SQL Queries mal überarbeiten. * sollte vermieden werden und die Tabellen solltest du Joinen.
Beispiel (ungetestet und gehört natürlich überarbeitet)
SQL:
SELECT pta.spalte1_von_pt_artikel, pta.spalte2_von_pt_artikel, ptp.artikel_id FROM pt_artikel as pta
INNER JOIN pt_pictureartikel as ptp ON pta.id = ptp.artikel_id
WHERE pta.exp_date < $time
AND ptp.artikel_id = $row[freegame_id]
ORDER BY pta.exp_date DESC LIMIT 5
 
  • Gefällt mir
Reaktionen: abcddcba
Gibt es einen Grund dafür dass du die DB nicht den Join machen lässt und stattdessen im Client über die Ergebnisse von Query 1 iterierst um dann für jedes Teilergebnis (aka Row/Zeile) eine extra Query 2 auszuführen? Das ist doch absurd, oder nicht?

Eine Datenbank ist extra dafür designed, hat Index Strukturen, diverse Möglichkeiten einen Join intern umzusetzen Arten,etc.

Evtl. solltest du doch erstmal DB Design und SQL Query bei dir überdenken - wer weiß was man da noch verbessern kann
 
Hallo

Erstmals danke für die vielen Antworten.

Habe mich gestern Abend ca. 2 Stunden eingelesen mit Umgang von PDO.

Könnte man statt "Inner Join" auch "Left Join" benutzen und wo ist da der Unterschied ? :lol:

LG
 
natürlich kann man das. Die Frage ist nur, ob das Ergebnis dass ist, was du erwartest. Du solltest dir einfach mal SQL Grundlagen und Fortgeschrittenes per Google zusammen suchen und lernen.
 
Hallo DubZ

Ja bin mich weiterhin am Einlesen. Immerhin habe ich erreicht, dass wenigstens etwas angezeigt wird
unter PHP 7.2 :-)

Problem ist ich habe dutzende "Include Dateien" auf der Webseite, die ich bis März alle Bearbeitet haben
muss, werde daher ein wenig forcieren :-).

Melde mich heute Abend evtl. nochmals, falls wieder ein Problem auftreten sollte.

LG
 
DualityMind schrieb:
Könnte man statt "Inner Join" auch "Left Join" benutzen und wo ist da der Unterschied ?
Warum fragt du ob du es benutzen kannst, wenn du nicht weißt was es überhaupt macht? Du kannst auch einen Full Outer Join verwenden. Ob es Sinn macht stelle ich mal in Frage...

Du solltest schon das Konzept von Joins verstehen. Ansonsten macht es keinen Sinn SQL zu verwenden.
Sollte eigentlich in jedem guten Tutorial relativ gut erklärt werden. Kriegst du hin, halbe Stunde hat man das soweit drauf.
 
Hallo

Habe es so verstanden, dass per Inner Join etc. gleichzeitig zwei Tabellen angesprochen werden.

Ich hoffe ich habe es richtig verstanden. Ausserdem kenne ich mich einigermassen gut aus mit MySQL,
aber mit PDO noch nicht, da das Projekt bereits vor 2010 angefangen habe.

LG
 
@DualityMind du kennst nur die Grundlagen von SQL, und diese auch nur teilweise, da joins ein wichtiger Bestandteil von SQL Abfragen sind. Ohne Joins hängt man irgendwann fest. Selbst Workarounds wie du sie gemacht hast gehen ab einem bestimmten Punkt nicht mehr.

Ich glaube auch dass man ein bisschen mehr als 30 Minuten brauch. Ich kann dir nur nahelegen die Datenbanknormalisierungen anzuschauen, zu verstehen und joins zu lernen und zu verstehen. Damit hast du dann die Grundlagen abgeschlossen um ein vernünftiges Datenbankdesign zu erstellen als auch SQL Abfragen zu schreiben.

Mit PDO hat die ganze Diskussion übrigens gar nichts zu tun. PDO ist quasi nur eine weitere Schnittstelle Datenbankverbindungen und Abfragen inkl. prepared Statements herzustellen und auszuführen.

Mein Text ließt sich schlimmer als ich ihn meine. Mir ist schon klar dass du nur eine schnelle Lösung deines Problems suchst :) Aber arbeite an deinen SQL Grundlagen, denn mit deinem aktuellen Stand wirst du immer irgendwann auf Hindernisse stoßen.
 
Erm, JOINs haben weder mit MySQL noch mit PDO zu tun, das ist einfach SQL.

Nein, Du kannst LEFTies nicht einfach anstelle INNERs verwenden. Das sind zwei verschiedene Paar Schuhe.


Ich schlage vor, Du läßt die Prozeßlogik so wie sie ist, auch wenn sie sicherlich nicht optimal ist.


Stattdessen gehst Du durch den Quellcode auf die Jagd nach SQL-Abfragen und:

-- Ersetzt dynamisch zusammengesetzte Strings durch PDO's Parameter Binding, also

BISHER:
"SELECT a,b,c FROM tabelle WHERE id = $id"
NEU:
"SELECT a,b,c FROM tabelle WHERE id = :id"

(siehe auch im Thread hier weiter oben bzw. Manuals zu PDO).


Und dann sind da diese lausigen Abfragen innerhalb von Schleifen. NORMAL wäre das zu JOINs umzubauen- sollte bei Dir/Euch auf die TODO-Liste.

Aber das geht schief bis März. Daher schaust Du Dir die Schleifen an und:

- Schiebst die Abfragen aus der Schleife raus über die Schleife.
- Ersetzt diejenigen Teile der Abfrage, die KONTEXTBEZOGEN in der Schleife geändert werden, durch Parameter (wie oben).
- Bindest in jedem Schleifendurchlauf die geänderten Werte in der Schleife an die Parameter.
- Sagst nur noch Execute und führst so dieselbe Abfrage transparent erneut aus, aber durchs Parameterbinding dann optimiert (geht sehr viel schneller als eine eigenständige Abfrage).

- Bedarfsweise, weil ichs grad nicht im Kopf hab wie das bei PDO geregelt ist, mußt Du ggf noch die Eigenschaft Prepared auf True setzen. Auch das sollte sich in den PDO-Manuals finden.
 
RalphS schrieb:
- Bindest in jedem Schleifendurchlauf die geänderten Werte in der Schleife an die Parameter.

Wenn man die sich ändernden Werte in einer oder mehreren PHP-Variablen stehen hat, die via PDOStatement::bindParam() zuvor an die entsprechend im SQL-Statement verwendeten SQL-Parameter gebunden wurden, muss man in der Schleife nichts (re)binden, sondern nur noch PDOStatement::execute() & PDOStatement::fetch() oder PDOStatement::fetchAll() aufrufen.
 
  • Gefällt mir
Reaktionen: RalphS
Okay, PDO macht byRef, gut zu wissen.

Ehrlich gesagt gefällt mir‘s mit Rebind besser, da weiß man auch morgen noch was los ist, aber egal. Hauptsache es tut erstmal.
 
Hallo

Jo, ich bins wieder :-))!

Habe jetzt diesen Code, aber funzt gar nichts mehr :-(!
Code:
$statement = $pdo->prepare("SELECT pta.freegame_id,pta.exp_date,pta.subject,pta.download_count,pta.hersteller, ptp.picture_id,ptp.freegame_id FROM pt_android as pta INNER JOIN pt_pictureandroid as ptp ON ptp.picture_id WHERE ptp.picture_id = pta.freegame_id ORDER BY exp_date DESC LIMIT 5");
$statement->execute();
 
while($row = $statement->fetch()){

echo $row[subject];

}

Entweder ist bei der MySQL Abfrage etwas falsch, oder es fehlt irgend eine Funktion z.B.
$statement->execute(); Muss hier noch etwas in Execute() Einfügen wie z.B. execute($exp_date); ?

und in der While Schleife

while($row = $statement->fetch()) "Ist hier etwas falsch ?"

Bei "Echo $row[subject];" zeigt er nichts an, daher irgendwo ist was falsch :-(((!

Kann sich bitte jemand kurz Zeit nehmen dafür ? Wäre sehr Dankbar ()-();

LG
 
Code:
... INNER JOIN ... ON ptp.picture_id WHERE ...
Bin nicht so mit MySql vertraut, kann sein, dass das sogar valide ist, es kommt aber definitiv nicht das raus, was du dir vorgestellt hast.

PDO und PHP selbst bieten ja diverse Möglichkeiten der Fehlerausgabe. Aktivier mal alles was geht. PHP muss dir in der echo-Zeile eine Warnung an den Kopf knallen und PDO müsste sogar Exceptions werfen, die gefangen werden wollen.
 
Klingt mir eher, als würde die Abfrage nichts liefern. Stell zunächst mal sicher, daß da überhaupt ein Ergebnis rauskommt, zB mit phpMyAdmin oder, einfacher, per Kommandozeile ("mysql.exe").

Vom Drübergucken her fällt JOIN ... on game_id = picture_id auf. Soll das so sein?

Und natürlich zeigt er bei $row[subject] nichts an. Subject ist keine Konstante, sondern ein String. Ein paar " " drumrum und dann sieht das womöglich anders aus.

Mir persönlich liegt $row->feldname eher, auch aus diesem Grund, aber zugegeben so richtig sauber ist das auch nicht.
 
Hallo

Habe jetzt diesen Code:

Code:
$sql = ("SELECT * FROM pt_android where freegame_id order by exp_date desc limit 5");
$statement = $pdo->prepare($sql);
$statement->execute();

while($row = $statement->fetch())
{
    $i = 1;

$bild = ("SELECT * FROM pt_pictureandroid WHERE picture_id = :freegame_id order by picture_id desc limit 1");
$statement2 = $pdo->prepare($bild);

$statement2->execute();
 
echo  "<img src=\"../thumbnail/$row[freegame_id].jpg\" align=center valign=middle height=\"60\" width=90  class=blackbox border=\"0\"></td>";

}

Problem ist nun, es geht alles und zeigt alles an, ABER es zeigt mir nur das Bild von "$row[freegame_id]" an, es muss aber das Bild von "$row[picture_id]" sein.

Habe sicher wieder 2 Stunden herumgepastet :-), aber hilft alles nichts. Ich brauche von pt_pictureandroid nur die Zahl von der Tabelle "picture_id".

Habe deswegen geschrieben:

Wähle picture_id von pt_pictureandroid, welches mit der Zahl von freegame_id identisch ist und nur die Neueste picture_id ist (also nur 1mal das Bild Anzeigen pro Eintrag, es gibt ja meherere Bilder pro Artikel mit der gleichen freegame_id ). Ich hoffe jemand hat es verstanden, verstehe es selber auch nicht :evillol::evillol:

Habe ich irgendetwas übersehen was falsch ist. Oder spricht er die PT_ANDROIDPICTURE Abfrage gar nicht an ?

Das mit dem INNER JOIN hat auch nicht geklappt, gab immer leere Felder :-(((.

Kann mir bitte jemand helfen :freak::freak::freak:

LG
 
Code:
... where freegame_id order ...
Du weiß, dass die where-klausel optional ist? Das verwirrt doch nur.

DualityMind schrieb:
Wähle picture_id von pt_pictureandroid, welches mit der Zahl von freegame_id identisch ist
Blöd nur, dass du dem statement gar nicht die Info gibt, welche freegame_id du denn genau haben willst. Das scheint dir aber auch egal zu sein, denn das Ergebnis (wenn es denn ein gäbe) verwendest du ebenfalls nicht.
 
Hallo DualityMind,

also all den gut gemeinten Ratschlägen hier, schließe ich mich uneingeschränkt an. Nichtsdestotrotz habe ich mal stumpf deinen original Auszug in korrektes PDO übersetzt. Bitte beachte, dass ich im Code zwei Stellen mittels Kommentaren markiert habe, an denen eklatante potentielle Sicherheitslücken klaffen. Ein solcher Code würde in unserem Unternehmen nicht mal dem einfachsten Review standhalten. Das Beispiel dient dir aber hoffentlich erstmal dazu, die Aufgabe rechtzeitig zu beenden.

PHP:
<?php

/** @var \PDO $pdo */
$stmt = $pdo->prepare("SELECT * FROM pt_artikel where exp_date < :time ORDER BY exp_date DESC LIMIT 5");
$stmt1 = $pdo->prepare("SELECT * FROM pt_pictureartikel WHERE artikel_id = :article ORDER BY exp_date DESC");

$stmt->execute([':time' => $time]);
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC))
{
    $stmt1->execute([':article' => $row['freegame_id']]);
    $picnr = $stmt1->fetch(\PDO::FETCH_ASSOC);

    // das hier kann saugefährlich sein!!!
    $tmp = getimagesize("../artikel/img/thumbnail/".$picnr['picture_id'].".".$picnr['ext']."");

    // das hier ist ein absolutes NoGo!!! Beschäftige dich mit dem Thema: XSS (Cross-Site-Scripting)
    echo  "<tr><td style=padding-left:10px; align=\"left\" bgcolor=$bgcolor width=120><font size=\"-3\"><img src=\"../artikel/img/thumbnail/{$row['picture_id']}.{$row['ext']}\" align=center valign=middle height=\"60\" width=90  class=blackbox border=\"0\">";

    echo  substr( $row['artikel_name'], 0, 60 );

    $dazu++;
    $i++;
    $dazu2++;

}

$stmt1 = $stmt = null;
?>

Das ganze Konstrukt ohne Join zu bauen ist ziemlicher Käse und vor allem Resourcenverschwendung. Der Code ist wie gesagt voller Sicherheitslücken und der Server somit potentiell gefährdet. Das HTML könnte auch mal wenigstens in das Jahr 1999 gebracht werden (align/valign/height sind als CSS zu schreiben).

Wenn die Seite läuft, suche dir am besten Hilfe wie man sowas mit modernen Mitteln umsetzt.
Merke: Wenn du SQL oder HTML manuell mittels PHP (String Concatination) erstellst, baust du potentiell gefährlichen Code.
 
Hallo @Sgt_H4rtman

Danke vielmals für Deine Mühe :-))

Leider funktioniert es nicht wie es sollte. Die Subjecte zeigt er immer Korrekt in der Reihenfolge an.

Aber immer wenn die Tabelle pt_pictureandroid ins Spiel kommt, also mit "picture_id", funktioniert gar nichts :-(

Anscheinend funktioniert der Code nur mit Tabelle "pt_android". Mit "pt_pictureandroid" kann er anscheinend nichts anfangen :-(.

Hier nochmals der geänderte Code:

PHP:
/** @var \PDO $pdo */
$stmt = $pdo->prepare("SELECT * FROM pt_android where exp_date < :time ORDER BY exp_date DESC LIMIT 5");
$stmt1 = $pdo->prepare("SELECT * FROM pt_pictureandroid WHERE picture_id = :freegame_id ORDER BY exp_date DESC LIMIT 1");

$stmt->execute([':time' => $time]);

while ($row = $stmt->fetch(\PDO::FETCH_ASSOC))
{

   $stmt1->execute([':freegame_id' => $row['picture_id']]);
    $picnr = $stmt1->fetch(\PDO::FETCH_ASSOC);

    // das hier kann saugefährlich sein!!!
    $tmp = getimagesize("../uploadscript/img/android/thumbnail/".$picnr['picture_id'].".".$picnr['ext']."");

    // das hier ist ein absolutes NoGo!!! Beschäftige dich mit dem Thema: XSS (Cross-Site-Scripting)
    echo  "<tr><td style=padding-left:10px; align=\"left\" bgcolor=$bgcolor width=120><font size=\"-3\"><img src=\"../uploadscript/img/android/thumbnail/{$row['picture_id']}.{$row['ext']}\" align=center valign=middle height=\"60\" width=90  class=blackbox border=\"0\">";
echo "<font color=white>";
    echo  substr( $row['subject'], 0, 60 );

}

$stmt1 = $stmt = null;

Wieso funktioniert das mit dem "picture_id" und "ext" nicht obwohl alles deklariert ist ? Habe über 1 1/2 Stunden wieder herumgeputscht aber nichts läuft. Sobald ich aber "freegame_id" und "jpg" zeigt er mir das Bild an. Aber das bringt mir ja nichts, Da jeder Artikel mehrere Bilder hat und deshalb die Reihenfolge von Freegame_id und Picture_id nicht übereinstimmen kann :-(((((.

Was mache ich falsch ? Beim der alten Schreibweise hat das immer funktioniert, dass ich das Bild hole, innherhalb einer While Schleife :-(.

LG
 
Zurück
Oben