PHP Lektionen – Lektion 3.5 – Arbeiten mit der MySQL-Datenbank. JOIN-Operator. Dateien auf den Server hochladen.
Bevor ich mit dieser Lektion beginne, habe ich lange darüber nachgedacht, wie man Anfragen mit JOIN-Operatoren am besten vermittelt. Der Grund ist, dass der JOIN-Operator benötigt wird, um aus mehreren Tabellen gleichzeitig auszuwählen. Und da eine weitere Tabelle benötigt wird, erstellen wir sie. Ich schlage vor, eine Tabelle für Dateien zu erstellen, die wir im Rahmen dieser Lektion über ein Formular hochladen werden. So entsteht eine Lektion mit zwei unterschiedlichen Themenbereichen: Arbeit mit der Datenbank und Arbeit mit Formularen.
Beginnen wir wohl mit dem Hinzufügen eines Feldes zum Hochladen von Dateien. Damit das Formular Dateien hochladen kann, muss der Formulartyp in seinen Parametern ergänzt werden:
$content .= '<form action="' . $_SERVER['PHP_SELF'] . '" method="post" enctype="multipart/form-data">';
So geben wir über den Parameter enctype
dem Browser zu verstehen, dass wir über dieses Formular Dateien hochladen wollen. Nun, da das Formular vorbereitet ist, fügen wir ein Feld zum Hochladen der Datei hinzu:
public function display_admin() { // Methode zur Eingabe einer Nachricht $content = ''; $content .= '<form action="' . $_SERVER['PHP_SELF'] . '" method="post" enctype="multipart/form-data">'; $content .= '<label for="title">Name:</label><br />'; $content .= '<input name="title" id="title" type="text" maxlength="150" />'; $content .= '<div class="clear"></div>'; $content .= '<label for="bodytext">Nachricht:</label><br />'; $content .= '<textarea name="bodytext" id="bodytext"></textarea>'; $content .= '<input type="file" name="filename">'; // Feld zum Hochladen der Datei $content .= '<div class="clear"></div>'; $content .= '<input type="submit" value="Nachricht hinzufügen" />'; $content .= '</form>'; $content .= '<p><a href="/index.php">Zurück zur Startseite</a></p>'; return $content; }
Über das input-Feld mit Typ file
werden wir unsere Datei hochladen. Wenn Sie die Dateien speichern und die Seite zur Nachrichtenerstellung aktualisieren, sollte ein Upload-Feld für die Datei erscheinen.
Nun sehen wir uns an, wie die Datei im POST-Request übergeben wird.
public function write($p) { print_r($p); // Ausgabe des Formular-Arrays print_r($_FILES); // Ausgabe des Datei-Arrays $sql = 'INSERT INTO Messages (title, bodytext, created) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ')'; return mysql_query($sql); }
Jetzt laden wir eine beliebige Datei hoch und speichern die Nachricht. Alle über das Formular hochgeladenen Dateien sind in der Superglobalen Variable $_FILES
verfügbar. Ich habe eine Datei hochgeladen und folgende Arrays erhalten:
Array ( [title] => asfasdf [bodytext] => asfasdf ) Array ( [filename] => Array ( [name] => ip.txt [type] => text/plain [tmp_name] => Y:\tmp\phpAA.tmp [error] => 0 [size] => 13 ) )
Nun, da wir Daten- und Datei-Arrays haben, erstellen wir eine Dateitabelle, um die hochgeladenen Dateien zu speichern. Zuerst erstellen wir im Root-Verzeichnis unserer Seite einen Ordner files
und wenn Sie ein Linux-System verwenden oder auf einem Hosting arbeiten, geben Sie diesem Ordner die Rechte 777, damit unser Skript Dateien dort speichern kann.
Ändern wir die Abfrage zum Erstellen der Tabellen in der Methode buildDB()
:
$sql = "CREATE TABLE Messages ( mid int NOT NULL AUTO_INCREMENT, PRIMARY KEY(mid), title varchar(15), bodytext text, created int(11), file int(11), ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; CREATE TABLE Files ( fid int NOT NULL AUTO_INCREMENT, PRIMARY KEY(fid), filename varchar(255), filepath varchar(255), filemime varchar(255), filesize int(10), timestamp int(10), )ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;";
Neben dem Hinzufügen einer neuen Tabelle fügen wir auch das Feld fid
hinzu, das ein Fremdschlüssel zur Dateitabelle sein wird. Für die neue Dateitabelle haben wir folgende Felder:
fid – der Primärschlüssel unserer Tabelle, die Dateinummer.
filename – der Dateiname.
filepath – der Pfad zur Datei relativ zum Root-Verzeichnis der Seite.
filemime – der Dateityp, um die Dateiendung und den Verwendungszweck zu bestimmen (zum Beispiel text/plain bei Textdateien, image/jpg, image/png bei Bildern).
filesize – die Dateigröße in Bytes.
timestamp – der Zeitpunkt des Dateiuploads.
Jetzt speichern wir die Datei und schreiben die Abfrage zum Einfügen der Datei in die Datenbank. Die nötigen Felder können Sie über phpMyAdmin anlegen.
if($_FILES["filename"]["size"] > 1024*3*1024) { echo ("Die Dateigröße überschreitet drei Megabyte"); exit; } // Prüfen, ob die Datei hochgeladen wurde if(is_uploaded_file($_FILES["filename"]["tmp_name"])) { // Wenn die Datei erfolgreich hochgeladen wurde, verschieben wir sie // aus dem temporären Verzeichnis in das Zielverzeichnis move_uploaded_file($_FILES["filename"]["tmp_name"], "/files/".$_FILES["filename"]["name"]); } else { echo("Fehler beim Hochladen der Datei"); }
So speichern wir die Datei im Ordner files
. Nach erfolgreichem Upload fügen wir einen Datensatz in der Tabelle Files hinzu:
$sql = 'INSERT INTO Files (filename, filepath, filemime, filesize, timestamp) VALUES ("'. $_FILES['filename']['name'] . '", "files/' . $_FILES['filename']['name'] . '", "'. $_FILES['filename']['type'] .'", '. $_FILES['filename']['size'] .', '. time() . ')'; mysql_query($sql);
Nachdem wir den Dateidatensatz eingefügt haben, müssen wir auch die Nachricht einfügen. Die Insert-Abfrage für die Nachricht ändern wir ebenfalls leicht und fügen das Feld fid
hinzu.
$sql = 'INSERT INTO Messages (title, bodytext, created, fid) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ',LAST_INSERT_ID())';
Beachten Sie die Funktion last_insert_id()
, das ist eine MySQL-Funktion, die die zuletzt eingefügte ID aus irgendeiner Tabelle der Datenbank zurückgibt. In unserem Fall wurde zuletzt ein Datensatz in der Tabelle Files eingefügt, daher wird die ID aus der Dateitabelle zurückgegeben.
Jetzt werden Datensätze in beiden Tabellen eingefügt, es bleibt noch, sie mit dem JOIN-Operator auszugeben. Ändern wir die Abfrage zum Anzeigen der Nachrichten so, dass auch der Dateiname mit ausgegeben wird:
public function display_public() { // Methode zum Anzeigen der Nachrichten $content = ''; $sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid ORDER BY mid DESC'; $result = mysql_query($sql) or die(mysql_error()); ...
Ich habe hier den JOIN-Operator zusammen mit LEFT verwendet. Das liegt daran, dass das Zusammenführen von Tabellen für eine Auswahl auf verschiedene Arten erfolgen kann. In einer der nächsten Lektionen betrachten wir die Verwendung von JOIN genauer. Für jetzt einigen wir uns darauf, dass LEFT JOIN alle Datensätze ausgibt, auch solche, bei denen das Feld fid fehlt.
Wenn wir jetzt das Ergebnis-Array ausgeben:
public function display_public() { // Methode zum Anzeigen der Nachrichten $content = ''; $sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid ORDER BY mid DESC'; $result = mysql_query($sql) or die(mysql_error()); while($row = mysql_fetch_array($result)){ // die Ergebnisvariable muss mit mysql_fetch_array() verarbeitet werden print_r($row);
sehen wir, dass sowohl Daten aus der Nachrichtentabelle als auch aus der Dateitabelle ausgegeben werden. Wenn keine entsprechende Datei vorhanden ist, sind die Felder leer. Deshalb muss man prüfen, ob etwas in diesen Feldern steht.
if(!empty($row['filename'])){ $content .= '<p>Anhang: <a target="_blank" href="/'. $row['filepath'] .'">'. $row['filename'] .'</a></p>'; }
Nun wird zusammen mit der Nachricht auch der Anhang als Link auf die hochgeladene Datei ausgegeben. In der nächsten Lektion werden wir den großartigen JOIN-Operator detaillierter betrachten, der es ermöglicht, Daten aus mehreren Tabellen gleichzeitig auszugeben. Als Anhang werde ich jetzt auch einen aktuellen Datenbank-Dump beifügen, der über phpMyAdmin erstellt wurde.