Aufgeben ist keine Option! ![]()
Was passiert denn? Fehlermeldung?
Aufgeben ist keine Option! ![]()
Was passiert denn? Fehlermeldung?
Da fehlen " und '.
$neu[melden] sollte sicherlich $neu['melden'] sein.
Teste mal deine Scripte mit allen Errorausgaben:
// an den anfang des scripts oder am besten in das eingangsscript (index.php)
error_reporting(E_ALL);
ini_set('display_errors', 1);
Da werden einige Warnings und Notices fliegen.
Und sowas hier:
kann böse enden (SQL injection).
Ich weiß, dass Du die Daten hier selbst setzt.
Aber bei einem Update, oder wenn Du mal einen Codeblock zum wiederverwenden kopierst, ...
kann es schnell passieren, dass Du auf einmal Unsichere Daten in die Query schreibst.
Wie dann:
Die id per platzhalter dürfte keine große Sache sein. (Empfehle btw :platzhalter statt ? )
Die Column $code allerdings musst Du in die Query schreiben (Platzhalter sind nur bei Values erlaubt)
aber in solchen Fällen nutzt man Whitelists
$whiteListCode = ['abc', 'def', '...'];
if (in_array($code, $whiteListCode, true)) {
$sql = "UPDATE `bilderdatenbank` SET `{$code}` WHERE `id` = :id";
// ...
} else {
// ERROR, unerlaubter wert
// die oder exit oder throw new Exception ...
die("nope");
}
oder du rennst mit nem Regex drüber und lässt nur bestimmte Zeichen zu:
// bad input:
$code = "id` = `id`; DROP TABLE admin; -- .";
// letter number underscore only
$cleanColumnName = preg_replace("/[^\w]/", '', (string)$code);
$sql = "UPDATE `bilderdatenbank` SET `{$cleanColumnName}` WHERE `id` = :id";
var_dump($sql);
// UPDATE `bilderdatenbank` SET `ididDROPTABLEadmin` WHERE `id` = :id
Das letzte Script: die Datei Test2.php
Du nutzt FETCH_OBJ, bekommst also ein Object (per $object->property angesprochen).
Du sprichst es allerdings als Array an: echo $row['image'];
Außerdem fehlt ein ; in Zeile 8 ![]()
Probier mal das hier:
<?php
//$id = addslashes($_GET['id']); // addslashes ist murks. weg damit
$id = $_GET['id']; // id unbehandelt. könnte alles sein (thema SQL-injection).
// sehr nice, dass du prepared statements nutzt. du musst es aber auch richtig einsetzen.
// was fehlt ist, dass du die daten per platzhalter in die SQL query setzt um SQL injections zu vermeiden:
//$statement = $pdo->prepare("SELECT image, mimetype FROM images WHERE id='$id'");
$statement = $pdo->prepare("SELECT `image`, `mimetype` FROM `images` WHERE `id` = :id;");
$result = $statement->execute(['id' => $id]);
// siehe http://php.net/manual/de/pdo.prepare.php#refsect1-pdo.prepare-examples
$row = $result->fetch(PDO::FETCH_OBJ);
header("Content-type: " . $row->mimetype);
echo $row->image;
Alles anzeigen
Bitte immer Daten (egal aus welcher Quelle - selbst, wenn es aus der eigenen db kommt) per PLatzhalter in die SQL query schreiben.
Und die anderen Scripte nicht vergessen zu updaten, um Platzhalter zu verwenden.
EDIT: btw - was ist in der db.images das Feld `image` für ein Typ?
-- hab den Artikel gefunden - hat sich erledig. Sicherlich Type BLOB.
Nur noch zur Ergänzung der Prepared Statements -Geschichte:
wie gesagt alle anderen Scripte updaten, und immer Platzhalter zu nutzen.
Ab dann kannst Du nämlich auch addslashes weglassen.
wird dann
Nix zu korrigieren.
Evtl was hinzuzufügen:
echo "Dies ist ein {$foo}"; // Ausgabe: Dies ist ein Test
Hier sind die Klammern kein muss. Beim nächsten Bsp aber doch:
$array = [
'foo' => 'Test'
];
echo "Dies ist ein {$array['foo']}"; // Ausgabe: Dies ist ein Test
Manchmal kann es übersichtlicher sein, wenn man "" benutzt, statt viele Verkettungen.
Oder man nutzt sprintf()
$var = 'Test';
$format 'Dies ist ein %s'; // %s ist platzhalter für einen string (s)
echo sprintf($format, $var); // Ausgabe: Dies ist ein Test
Zeilenumbruch
"\r\n" bzw \n (new line - neue Zeile; reset - auf der momentanen zeile an den Anfang)
oder PHP_EOL(EOL ^= End Of Line - neue Zeile)
echo 'Hier kann ich kein \r\n nutzen. Also verkette ich den Zeilenumbruch: ' . "\r\n";
echo 'Hier kann ich kein \r\n nutzen. Also verkette ich den Zeilenumbruch: ' . PHP_EOL;
echo "Hier kann ich \r\n nutzen. PHP_EOL Muss ich aber weiterhin verketten, da es als Konstante nicht inline genutzt werden kann" . PHP_EOL;
Das (oder so ähnlich) hatten wir doch schon: Einzelnes Datenfeld bei UPDATE anzeigen
BTW: Ganz wichtig - niemals sensible Daten posten. Dein pw bei mysqli_connect kanst Du jetzt vergessen.
Wo auch immer Du das genutzt hast, solltest Du es sofort ändern!
Ziel: eine MySql Datenbanktabelle erweitern, um zu sehen, wann eine Zeile erstellt wurde, oder geändert wurde.
Verwendete Techniken: MySql
Schwierigkeitsgrad: für Anfänger geeignet, Grundkenntnisse über die Funktionsweisen von SQL vorausgesetzt
Wichtig: IMMER Daten sichern, bevor man an Produktivdaten rangeht!
Angenommen, Du hast eine Tabelle `user` erstellt, und Du möchest abfragen können, wann ein Benutzer erstellt bzw geändert wurde.
Dann ist der einfachste weg das hinzufügen zweier Felder:
`created_at` und `updated_at`.
Das Ganze wird ein "Einmalaufwand". Die beiden Felder werden hinzugefügt, und Auslöser (Trigger) erledigen den Rest.
ALTER TABLE `user`
ADD COLUMN `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'datetime row inserted',
ADD COLUMN `updated_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT 'datetime row updated';
Wichtig: bei einem INSERT INTO oder UPDATE sollten keine Werte für die Felder `created_at` und `updated_at` mitgegeben werden.
Das sollte komplett dem MySql-Server überlassen werden.
Was passiert hier:
Bei einer neuen Zeile (INSERT INTO) wird der Wert für das Feld `created_at` mit dem momentanen Zeitstempel versehen.
Dieser Zeitstempel wird nie wieder geändert. Somit ist klar, wann genau diese Zeile eingefügt wurde.
Beim ändern einer Zeile (UPDATE) wird der Wert für das Feld `updated_at` mit dem momentanen Zeitstempel versehen.
Das passiert immer nur dann, wenn sich auch wirklich Daten geändert haben.
Am Beispiel: Testtabelle erstellen und Beispieldaten einfügen
(Die Tabelle wird hier `user_test` genannt, um nicht evtl vorhandene Tabellen zu "versauen")
Erstellen der Tabelle
CREATE TABLE `user_test` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(32) NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP
);
Testdaten einfügen
Testausgabe
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | hans | 2017-06-06 17:03:22 | 0000-00-00 00:00:00 |
| 2 | wurst | 2017-06-06 17:03:25 | 0000-00-00 00:00:00 |
+----+-------+---------------------+---------------------+
Der MySql-Server hat sich hier also wie gewollt um die Werte der Spalten `created_at` und `updated_at` gekümmert.
Jetzt wollen wir wissen, was passiert, wenn eine Zeile geändert wird:
Testausgabe
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | hans | 2017-06-06 17:03:22 | 0000-00-00 00:00:00 |
| 2 | peter | 2017-06-06 17:03:25 | 2017-06-06 17:09:50 |
+----+-------+---------------------+---------------------+
Wir sehen also, dass sich ser MySql-Server um das Feld `updated_at` gekümmert hat.
Jetzt noch ein Bsp, bei dem wir eigtl gar keine Änderungen verursachen
Info: hier sollte sich nichts ändern, da wir ja den Namen zuvor auf genau diesen Wert ('peter') gesetzt haben.
Testausgabe
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | hans | 2017-06-06 17:03:22 | 0000-00-00 00:00:00 |
| 2 | peter | 2017-06-06 17:03:25 | 2017-06-06 17:09:50 |
+----+-------+---------------------+---------------------+
Keine Änderung. Das Feld `updated_at` behält seinen Wert von '2017-06-06 17:09:50' beim Benutzer mit `id` 2.
Das wars.
Wäre nur noch zu erwähnen, dass man den DEFAULT Wert bei `updated_at` statt '0000-00-00 00:00:00'
auf CURRENT_TIMESTAMP setzen kann.
Warum:
'0000-00-00 00:00:00' ist eigtl kein gültiger Zeitstempel. Manche stört es, manche nicht.
Ändert man den DEFALUT Wert von
`updated_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP
auf
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
dann bekommt man bei einem INSERT INTO z.B.
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | hans | 2017-06-06 17:19:19 | 2017-06-06 17:19:19 |
| 2 | wurst | 2017-06-06 17:19:22 | 2017-06-06 17:19:22 |
+----+-------+---------------------+---------------------+
Die Felder `created_at` und `updated_at` sind genau gleich.
Möchte man also wissen, ob eine Zeile nie geändert wurde, dann fragt man ab, ob `created_at` und `updated_at` gleich sind:
SELECT * FROM `user_test` WHERE `created_at` = `updated_at`;
Hier noch einmal die CREATE TABLE Variante ohne '0000-00-00 00:00:00':
CREATE TABLE `user_test` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(32) NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Falls eine schon bestehende Tabelle erweitert werden soll:
ALTER TABLE `table_name` -- add your table name
ADD COLUMN `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Bei bereits bestehenden Daten fehlen nun natürlich die richtigen Zeitwerte.
Das könnte man hinnehmen - alle bereits vorhandenen Zeilen bekämen den jetzigen Zeitstempel.
Oder man lässt deren `created_at` und `updated_at` Felder auf den Wert '0000-00-00 00:00:00' setzen.
Dazu benötigen wir mehrere Schritte:
Ausgangs Tabelle
CREATE TABLE `user_test` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(32) NOT NULL
);
Testausgabe
+----+-------+
| id | name |
+----+-------+
| 1 | hans |
| 2 | wurst |
+----+-------+
Upgrade - dabei setzen wir auf allen vorhandenen Zeilen den (vorübergehenden) DEFAULT Wert auf NULL
ALTER TABLE `user_test`
ADD COLUMN `created_at` DATETIME DEFAULT NULL,
ADD COLUMN `updated_at` DATETIME DEFAULT NULL;
Testausgabe
+----+-------+------------+------------+
| id | name | created_at | updated_at |
+----+-------+------------+------------+
| 1 | hans | NULL | NULL |
| 2 | wurst | NULL | NULL |
+----+-------+------------+------------+
Jetzt ändern wir die neuen Felder, um die Werte vom MySql-Server befüllen zu lassen
ALTER TABLE `user_test`
MODIFY COLUMN `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFY COLUMN `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Testausgabe
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | hans | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
| 2 | wurst | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+-------+---------------------+---------------------+
Alle zuvor vorhandenen Zeilen bekommen nun also den Wert '0000-00-00 00:00:00'.
Es gitb also keinen `created_at` Wert für diese Einträge (woher auch - da gab es die Erweiterung ja noch nicht).
Aber alle jetzt eingefügten bzw geänderten Zeilen bekommen ihre korrekten Zeitstempel:
Testausgabe
SELECT * FROM `user_test`;
+----+-------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------+---------------------+---------------------+
| 1 | Hans | 0000-00-00 00:00:00 | 2017-06-06 17:46:39 |
| 2 | wurst | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+-------+---------------------+---------------------+
Möchte man hier wissen, ob eine Zeile geändert wurde, dann fragt man ab,
ob `created_at` und `updated_at` gleich sind und `updated_at` größer als '0000-00-00 00:00:00':
SELECT * FROM `user_test` WHERE `created_at` = `updated_at` and `updated_at` > 0;
Es gibt sicherlich noch andere Möglichkeiten, um bereits vorhandene Daten zu "kennzeichen". Ideen einfach mal posten.
ZitatSicherheit ist in dieser Uebung kein Thema
Bitte nicht. Auch wenn Du nur in einer Testumgebung schreibst - gewöhne Dir keine Sicherheitslücken an.
SQL-injection möglich! Keine Daten direkt in die SQL-Query schreiben.
Du nutzt mysqli_, daher ist das hier für Dich interessant: http://php.net/manual/de/mysqli.prepare.php
(bei Fragen einfach fragen)
Auch keine Daten direkt in die Ausgabe aufnehmen/anhängen.
Bsp böse
echo "Dein Name ist " . $_POST['name'];
Auch keine db-Daten:
echo "Dein Name ist " . $dbResult'name'];
Warum: in der Variable könnte zB Javascribt stecken. Teste mal einen Namen - ändere ihn in
<script>alert(1)</script>
Der browser wird eine Alertbox ausgeben (Bei einem Angriff würde da natürlich viel schlimmeres passieren).
Wie verhinderst Du das:
echo "Dein Name ist " . htmlspecialchars($_POST['name']);
bzw
echo "Dein Name ist " . htmlspecialchars($dbResult'name']);
Info: kurze Namen sind schnell geschrieben (zB "nn"), aber schlecht für die Lesbarkeit. Es ist für alle einfacher, wenn Du namen ausschreibst.
zB statt "nn" "nach_name" (oder noch besser gleich alles in Englisch "last_name").
Stichwort csv. Eine Textdatei mit format.
Lesen: http://php.net/manual/de/function.str-getcsv.php bzw http://php.net/manual/de/function.fgetcsv.php
So ging es mir auch.
Weiß gar nicht, wie ich das neue Forum dann gefunden hab. Ich glaub der Link zum Account ging aufs neue.
![]()
Keine Ahnung woher der Code stammt, aber ich würde ihn nicht online nutzen.
Von undefined index bis hin zur garantierten SQL-injection alles dabei.
(Den Fehler, den Du beschrieben hast, kann ich nicht finden. Aber das sollte die geringste Sorge sein.)
Siehe Kommentare:
<?php
class session
{
var $session_id = 0;
var $session_name = "mysess";
// --- constructor ---
function session()
{
// NOTE: __construct nutzen
}
function board_account()
{
global $db;
$session_id = session_id();
$id = $_GET[account_id];
// ERROR: undefinierte constante, sollte sicher 'account_id' werden
// NOTE: jeder kann jede account id in der url setzen. wer/was hindert mich daran,
// "alle" account ids auszuprobieren?
$data = $db->sql_query("select id,benutzername from account where id='$id'");
// ERROR: SQL-injection möglich! -- id frei wählbar (via GET)
$_SESSION["account_id"] = $data[0][0];
$_SESSION["account"] = $data[0][1];
// NOTE: warum nicht die account id in der session halten?
}
function user_identity()
{
global $db;
$u_identity = rand(0, 100000);
$_SESSION["user_identity"] = $u_identity;
// NOTE:
// weiß nicht, was damit gemacht werden soll,
// aber kollision nicht ausgeschlossen
}
function startSession()
{
global $user, $db, $network, $smarty;
$session_id = session_id();
if ($_POST[form_username]) {
$_SESSION["nickname"] = $_POST[form_username];
$nickname = $_POST[form_username];
// ERROR: undefinierte constante, sollte sicher 'form_username' werden
$userid = $db->sql_query("Select * from userprofil where s_user='$_SESSION[account]' AND nickname='$nickname'");
// ERROR: SQL-injection möglich! -- nickname frei wählbar (via POST)
// ERROR: undefinierte constante, sollte sicher 'account' werden
$userid = $userid[0][0];
$_SESSION["userid"] = $userid;
} else {
$accid = $_SESSION["account_id"];
$cn = "1aboard_name_" . $accid;
$cpw = "1aboard_pw_" . $accid;
$_SESSION["nickname"] = $_COOKIE[$cn];
$nickname = $_COOKIE[$cn];
$userid = $db->sql_query("Select * from userprofil where s_user='$_SESSION[account]' AND nickname='$nickname'");
// ERROR: SQL-injection möglich! -- nickname frei wählbar (via COOKIE)
// ERROR: undefinierte constante, sollte sicher 'account' werden
$userid = $userid[0][0];
$_SESSION["userid"] = $userid;
};
}
function my_session_unregister()
{
session_unregister("nickname");
session_unregister("userid");
// WARNING: This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
// use unset($_SESSION['nickname']); ...
}
// destroy a session
function destroySession()
{
// session_unset();
$this->my_session_unregister();
$file = session_save_path() . "sess_" . session_id();
// @session_destroy();
// @unlink($file);
}
}
Alles anzeigen
Was Stef schreib plus Du kannst statt
auch
nutzen. Siehe http://php.net/manual/de/reserved.constants.php
Weiß jetzt nicht in wie weit Du dicht mit PHP, HTML und JS auskennst.
Aber eine Empfehlung ist es auf jeden Fall wert: websocket
Es gibt viele Beispiele im Netz. Such mal nach "php websocket chat"
Das is alles so RIESIG ![]()
Ich bin ja auch schon älter, aber so alt auch noch net ![]()
Empfehle auch PHP password_hash, password_verify, ... (wenn PHP denn verwendet wird).
Aber zum Fehler:
PASSWORD ist eine Mysql Funktion.
Und die erstellt einen Hash.
Beim SELECT musst Du also den Hash vergleichen.
Bsp:
-- insert, wobei 123 das klartextpassword ist
INSERT INTO `users` SET `nickname` = 'horst', `password` = PASSWORD('132');
-- empfehle auch einzahl `user`. man merkt, dass es komisch klingt, wenn man abfragt:
-- users.id, users.nickname
-- select
SELECT `id`, `nickname`, `password` FROM `users` WHERE `nickname` = 'horst' AND `password` = PASSWORD('123');
-- bei
-- AND `password` = PASSWORD('123')
-- sagts du dem server "UND feld password = (der hash aus '123')"
--
-- in der db steht ja ein hash =)
Alles anzeigen
BTW: immer ` verwenden. Warum? Weil zB ein Feld names order in einer Query als Sclüsselwort für zB ORDER BY gewertet wird.
EDIT:
Wenn Du zB PHP nutzt, dann nutze PHP um die Hashes zu erstellen.
Sonst sendest Du dauernd das Klartextpasswort (per Query) an den Mysql Server. Das muss nicht sein. Je mehr das unterwegs ist, desto mehr Chancen gibt es, dass es irgendwo "auftaucht" (error logs ect !).
Nicht inaktiv. Aber gerade keine Zeit.
Da Du sagtest, dass Du 0 Ahnung von PHP hast, kann ich hier keine Hilfe geben,
denn das würde zu lange dauern.
Du solltest Dir PHP schon erstmal ansehen und verstehen.
Oder jemand findet sich und geht mir Dir alles von vorn bis hinten durch.
Zum Thema email hier ein Link zum PHP "Bruder" dieses Forums: http://www.php-kurs.com/email-per-php.htm
var lflaeche = $a_lagerflaeche;
Kann ja nicht gehen.
probier mal das:
// globale var setzen (in functions erreichbar)
var lflaeche = <?php echo $a_lagerflaeche ?>; // per PHP den inhalt setzen
var updateSelect = function () {
$("#a_lagerflaeche").load("inc/auslesen-lagerflaechen.php", {id_hauptkategorie: $('#a_lager').val()});
};
var updateSelectEDIT = function () {
$("#a_lagerflaeche").load(
"inc/auslesen-lagerflaechen.php",
{id_hauptkategorie: $('#a_lager').val(), id_a_lagerflaeche: lflaeche}
);
};
$(document).ready(function(){
$("#a_lager").change(updateSelect);
<?php if (isset($_GET['artikel'])): ?>
updateSelectEDIT();
<?php endif; ?>
});
Alles anzeigen
Das kommt daher, dass die JS (jQuery) Funktion nicht gestarted/angestoßen wird.
Die wird ja nur per "onchange" gestartet.
Was Du machen kannst:
beim Laden der Seite weißt Du ja, ob ein Artikel angelegt, oder bearbeitet wird.
Wenn bearbeiten (EDIT), dann startes Du die JS (jQuery) Funktion manuell 1 mal.
Bsp:
<!-- somewhere in your code the js function -->
<script>
var updateSelect = function () {
$("#a_lagerflaeche").load("inc/auslesen-lagerflaechen.php", {id_hauptkategorie: $('#a_lager').val()});
};
$("#a_lager").change(updateSelect);
<?php if (/*HERE YOUR CHECK IF IS EDIT*/): ?>
$(document).ready(
function () {
updateSelect();
// something else you wanna do on document ready
}
);
// or just: $(document).ready( updateSelect() );
<?php endif; ?>
</script>
Alles anzeigen
Vorweg: image resize ist tricky. Wenn Du was fertiges wilst, dann guck mal hier: http://stackoverflow.com/a/23772147/3411766
Das Bild wird auf die $maxsize zugeschnitten, wobei es egal ist, ob Breite oder Höhe.
Wenn das Bild Hochkannt ist, dann ist die max Höhe eben $maxsize. Sonst die max Breite.
Es wird immer ein png (imagepng) erstellt. Denke aber, wenn man statt imagepng() zB imagejpeg() nutzt, sollte es auch funktionieren.
Das Bild wird durch imagepng() in den ielordner gepseichert.
Das Original (zB PHP tmp) bleibt wo es ist. Nach Scriptende wird der tmp Ordner automatisch geleert (wenn nicht in php.ini oder ini_set() geändert).
Lief bei mir ohne Probleme.
Kann bei Dir auf Anhieb nix falsches sehen. Hab aber leider auch gerade keine Zeit es zu testen.
Bekommst Du denn Fehlermeldungen?
nutze mal:
Sollte funtionieren.
Das einfachste wäre meiner Meinung nach eine $_SESSION, in der Du eine optionale URL hinterlegst.
In dienstplan.php:
if(isUserLoggedIn($mysqli) === FALSE) {
// ich gehe davon aus, dass session_start() schon aufgerufen wurde
$_SESSION['page_after_login'] = 'login.php'; // order "page_to_redirect" oder was immer du möchstest
header('Location: login.php');
exit;
}
in login, bei erfolgreichem Login:
error_reporting(E_ALL);
ini_set('display_errors', 0);
if (isUserLoggedIn($mysqli) === true) {
header('Location: index.php');
} else {
if (isset($_POST['einloggen'])) {
$nickname = $_POST['nickname'];
$passwort = hash('sha256', $_POST["passwort"] . $salt);
if (login($mysqli, $nickname, $passwort) === true) {
$page = 'index.php'; // default to index.php
if (
isset($_SESSION['page_after_login'])
and strlen((string)$_SESSION['page_after_login'])
) {
// user came from ...
$page = (string)$_SESSION['page_after_login'];
}
header('Location: ' . $page);
} else {
$fehler = "Login fehlgeschlagen!";
}
}
}
Alles anzeigen
Naja, kommt drauf an, in wie weit Du Dich mit Klassen (OOP - Objekt orientierte Programmierung) auskennst.
Um Exceptions zu verstehen, brauchst Du Grundwisen in OOP.
Um Exceptions gut einsetzen zu können, brauchst Du fundiertes OOP Wissen.
Hier mal ein Bsp:
Class Car
{
protected $name;
public function setName($name)
{
if (!is_string($name)) {
throw new \Exception('Car name must be a string!', 123);
}
$this->name = (string)$name;
}
public function getName()
{
return $this->name;
}
}
try {
$car = new Car();
$car->setName(0);
echo $car->getName();
} catch (\Exception $e) {
echo 'Error: [' . $e->getCode() . ']' . $e->getMessage();
}
Alles anzeigen
Eine Exception ist ein Objekt. Es ist throwable.
Mit throw wird die new Exception geworfen.
Das heißt, dass der Ablauf des Scripts an der Stelle abgebrochen wird.
// datei index.php
echo 'some foo to do ...';
// exception wird geworfen und NICHT mit try/catch abgefangen:
throw new \Exception('this is a test exception!', 123);
// ^ throw wirft die exception und "wir sind raus".
// das hier wird nie ausgeführt
echo 'nobody can see that :(';
Alles anzeigen
Hier ein Bsp über 2 Dateien:
// datei index.php
echo 'some foo to do ...';
require 'test.php';
// ^ in test.php wird eine exception geworfen und NICHT aufgefangen.
// hier wird sie auch nicht aufgefangen und daher scheißt uns PHP den fehler:
// "uncaugth exception ..." (nicht aufgefangene exception ...) um die ohren.
// das zeigt uns nebenbei, das wir HIER exceptions von "irgendwo tiefer drin"
// ausfangen können.
// die exception "fällt" also von scope to scope (raum zu raum) immer weiter
// nach draußen.
// das hier wird nie ausgeführt
echo 'nobody can see that :(';
# - - - - -
// datei test.php
throw new \Exception('this is a test exception!', 123);
// ^ throw wirft die exception und "wir sind raus" aus der test.php,
// weil die exception hier nicht aufgefangen wird.
// das hier wird nie ausgeführt
echo 'nobody can see that :(';
Alles anzeigen
Um den Ablauf dennoch steuern zu können nutzt man try/catch
// datei index.php
echo 'some foo to do ...';
try{
require 'test.php';
}
catch (\Exception $e) {
echo 'Error: [' . $e->getCode() . ']' . $e->getMessage();
}
# - - - - -
// datei test.php
throw new \Exception('this is a test exception!', 123);
Alles anzeigen
Man kann (und später wird) auch eigene Exceptions nutzen.
Dabei erweitert man einfach die Exception:
// datei Car/CarException.php
class CarException extends \Exception
{
const EXC_CODE_INVALID_PARAMETER_TYPE = 123;
}
// datei Car.php
Class Car
{
protected $name;
public function setName($name)
{
if (!is_string($name)) {
throw new \CarException(
'Car name must be a string!',
CarException::EXC_CODE_INVALID_PARAMETER_TYPE
);
}
$this->name = (string)$name;
}
public function getName()
{
return $this->name;
}
}
// datei index.php
require 'Car/CarException.php';
require 'Car.php';
try {
$car = new Car();
$car->setName(0);
echo $car->getName();
} catch (\CarException $e) {
// catch only CarException
echo 'Something is wrong with da car:';
if($e->getCode() === CarException::EXC_CODE_INVALID_PARAMETER_TYPE){
echo 'i just identified that the car does not like the parameter you provided =)';
echo 'Car says: [' . $e->getCode() . ']' . $e->getMessage();
}else{
echo 'Something went wrong.';
echo 'Car says: [' . $e->getCode() . ']' . $e->getMessage();
}
} catch (\Exception $e) { // das 2tw und evtl 3tw, 4te, ... catch verhällt sich jeweils wie ein elseif
// catch any other exceptions
echo 'Something is wrong at all:';
echo 'Error: [' . $e->getCode() . ']' . $e->getMessage();
}
Alles anzeigen
HTML-Seminar.de - mit Videos zum schnellen Lernen, wie man eine Website selbst erstellt.