Variable löschen, die per Get übergeben wird
Steffen
- php
Hallo zusammen,
ich habe ein Problem, bei dem ich auf dem Schlauch stehe. In einem Formular biete ich für jedes Element einer langen Auflistung einen Button an, mit dem ich dieses Element löschen kann:
<input type="button" name="loeschen" value="löschen" onclick="self.location.href=\'benutzerverwaltung.php?loeschen='.$auslesen['id'].'\'" />
Der empfangende PHP Code tut dann dies: (er löscht also das Element aus der Datenbank)
if (isset($_REQUEST['loeschen']) && $_REQUEST['loeschen'] > 0)
{
$zuloeschen = $_REQUEST['loeschen'];
$sql = "DELETE FROM benutzertabelle WHERE id = '$zuloeschen' LIMIT 1;";
}
if (!($e = mysql_db_query($datenbankname,$sql)))
{
$meldung .= 'Konnte Datenbankkommando zum Löschen eines Benutzers nicht absetzen! ';
$fehler = 1;
}
Das funktioniert nun wirklich ganz prima. Einziger Haken an der Sache: Da ich die ID des Elements per Get übertrage (ich brauche ja die ID, damit ich weiss, was gelöscht werden soll), verschwindet diese ID nicht nach dem Löschvorgang sondern bleibt erhalten, es wird jedes Mal, wenn ich noch andere Sachen auf der Seite mache, wieder die Schleife angefahren. (Es passiert zwar momentan nichts, aber schön ist das nicht). Hat jemand eine Idee, wie ich die GET Variable löschen oder die ID anders übergeben kann?
Danke schonmal!
Steffen.
PS: unset($_REQUEST['loeschen'])
war nicht erfolgreich.
hallo,
vielleicht kann ich dir einen ansatz geben:
verwendest du für die id spalte "auto_increment"?
mfg
revo
Hallo,
ja, die id Spalte in der MySQL Tabelle verwendet auto_increment. Allerdings funktioniert das ja soweit alles und das Problem liegt meines Erachtens nach einfach nur darin, dass die Variable, die ich einmal mit GET übergbe, immer gesetzt bleibt und ich sie nicht mehr los werde.
viele Grüße,
Streffen
Mahlzeit Steffen,
if (isset($_REQUEST['loeschen']) && $_REQUEST['loeschen'] > 0)
{
$zuloeschen = $_REQUEST['loeschen'];
$sql = "DELETE FROM benutzertabelle WHERE id = '$zuloeschen' LIMIT 1;";
}
Das Umkopieren des $\_GET-Parameters (Wieso benutzt Du übrigens nicht genau dieses superglobale Array? Durch Verwendung von $\_REQUEST verschleierst Du nur unnötig die Herkunft des Werts) wird die Herkunft des Inhalts der Variablen $zuloeschen verschleiert. Darüber hinaus ist eine SEHR schlechte Idee, Eingaben von außerhalb ungeprüft an die Datenbank weiterzugeben - merke: ALL INPUT IS EVIL!
~~~php
if (isset($_GET['loeschen']) && $_GET['loeschen'] > 0) {
$sql = sprintf("DELETE FROM benutzertabelle WHERE id = '%s' LIMIT 1",
[link:http://de3.php.net/manual/de/function.mysql-real-escape-string.php@title=mysql_real_escape_string]($_GET['loeschen']));
}
Da ich die ID des Elements per Get übertrage (ich brauche ja die ID, damit ich weiss, was gelöscht werden soll), verschwindet diese ID nicht nach dem Löschvorgang sondern bleibt erhalten,
Wieso sollte auch "automagisch" irgendeines der Elemente des Arrays $_GET "verschwinden"?
es wird jedes Mal, wenn ich noch andere Sachen auf der Seite mache, wieder die Schleife angefahren.
Warum das? Verwendest Du vielleicht in Deinen Links den übergebenen QueryString? Überlege genau, wo das erneute Auftreten von $GET['loeschen'] herkommt ... was z.B. ist das Array $auslesen?
Insgesamt habe ich - ausgehend von den paar Codezeilen, die Du gezeigt hast - das Gefühl, dass Dein Code sehr unübersichtlich ist und Du selbst eigentlich gar nicht mehr so genau weißt, wo wann was passiert und wer wie welche Werte manipuliert. Ändere das ... in Deinem eigenen Interesse. :-)
MfG,
EKKi
Hallo Ekki,
vielen Dank für Deinen Rat. Ich habe nochmal geschaut und komme leider auf keine andere Erklärung.
Die Schleife
if (isset($_POST['loeschen']) && $_POST['loeschen'] > 0)
{
$zuloeschen = $_POST['loeschen'];
$sql = "DELETE FROM benutzer WHERE id = '$zuloeschen' LIMIT 1;";
}
if (!($benutzerliste = mysql_db_query($datenbankname,$sql)))
{
$meldung .= 'Konnte Datenbankkommando zum Löschen eines Benutzers nicht absetzen! ';
$fehler = 1;
}
wird jedesmal angesteuert, wenn die Seite neu geladen wird, sobald man einmal auf Löschen geklickt hat und die ID 'loschen' per GET übergeben wird. (Das erste Mal soll das ja auch so sein, wenn die Seite aber wiederholt aufgerufen wird, weil andere Benutzer hinzugefügt oder bearbeitet werden, stört das gewaltig, auch wenn nichts passiert).
viele Grüße,
Steffen
PS: Selbes Prinzip funktioniert übrigens hervorragend, wenn ich statt $_GET['loeschen'] nur $loeschen abfrage. Der Server ist alt und daher geht das wohl noch, gleichwohl weiss ich, dass man so nicht mehr programmieren sollte, allerdings bringt diese Umstellung die bisherige Vorgehensweise offenbar erheblich durcheinander.
Mahlzeit Steffen,
vielen Dank für Deinen Rat.
... den Du allerdings nicht wirklich befolgst. Mal schauen, wann der erste SQL-Injection-Versuch bei Dir stattfindet.
Die Schleife
if (isset($_POST['loeschen']) && $_POST['loeschen'] > 0)
{
$zuloeschen = $_POST['loeschen'];
$sql = "DELETE FROM benutzer WHERE id = '$zuloeschen' LIMIT 1;";
}if (!($benutzerliste = mysql_db_query($datenbankname,$sql)))
{
$meldung .= 'Konnte Datenbankkommando zum Löschen eines Benutzers nicht absetzen! ';
$fehler = 1;
}
> wird jedesmal angesteuert, wenn die Seite neu geladen wird, sobald man einmal auf Löschen geklickt hat und die ID 'loschen' per GET übergeben wird.
1\. ist das keine [Schleife](http://de.wikipedia.org/wiki/Schleife_(Programmierung)). Es gibt keine [if-Schleifen](http://www.if-schleife.de/)!
2\. Warum trifft die Bedingung immer zu? Hast Du das mal untersucht? Anscheinend wird doch das Skript erneut mit den gleichen GET-Parametern aufgerufen. Wieso wird es das? Wie sieht der Link im aufrufenden Skript aus? Wieso enthält er GET-Parameter?
> PS: Selbes Prinzip funktioniert übrigens hervorragend, wenn ich statt $\_GET['loeschen'] nur $loeschen abfrage. Der Server ist alt und daher geht das wohl noch, gleichwohl weiss ich, dass man so nicht mehr programmieren sollte, allerdings bringt diese Umstellung die bisherige Vorgehensweise offenbar erheblich durcheinander.
Zeig mal mehr Code und - viel wichtiger! - beschreibe, wie der Programmablauf/Workflow sein soll ... bisher habe ich immer noch nicht so recht verstanden, was Dein Skript eigentlich macht bzw. machen soll.
MfG,
EKKi
--
sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
Hallo zusammen,
nun, zum Thema Sicherheit: Ist mir bewusst, dass jede Variable untersucht werden sollte. Hier aber nicht. Das Skript läuft in einem geschützten Bereich und ist von aussen nicht zugänglich. Sollte es zugänglich sein, dann ist dieses Skript das kleinste Problem.
- Warum trifft die Bedingung immer zu? Hast Du das mal untersucht? Anscheinend wird doch das Skript erneut mit den gleichen GET-Parametern aufgerufen. Wieso wird es das? Wie sieht der Link im aufrufenden Skript aus? Wieso enthält er GET-Parameter?
Das ist genau die Frage. Der GET Parameter wird nur einmal gesetzt, wenn ich das erste Mal auf den Button klicke. (siehe Code). Lade ich die Seite neu, sollte er weg sein und das ist er nicht.
Der Workflow:
Ich habe eine Auflistung mit verschiedenen Benutzern auf einer Seite. Auf der Seite soll man Benutzer neu anlegen können, alte Benutzer löschen und bestehende Benutzer bearbeiten können. Alle Verarbeitungen und Ausgaben finden auf der selben Seite statt, die Formulare rufen also jedesmal die gleiche Seite auf. In etwa sieht die ganze php Seite so aus:
-------
hier ist ein toller php teil, der dafür verantwortlich ist, dass neue benutzer in die datenbank eingetragen werden, wenn die variablen $benutzername und $passwort übergeben werden
-------
hier ist ein toller php teil, der bestehende benutzer löscht, wenn die variable $loeschen mit der betreffenden id gesetzt ist
-------
hier ist ein toller php teil, der benutzer bearbeitet, wenn die variable $bearbeiten eine id enthält
-------
-------
hier werden jetzt alle benutzer angezeigt. zu jedem benutzer gibt es einen button, der die variable löschen oder bearbeiten an die gleiche seite sendet.
Ein Element der Auflistung sieht so aus:
<div class="downloadliste" style="margin-left: 20px;">
<p>Name: sd dfs<br />
Benutzername: dsafadfs<br />
Passwort: dsaf<br />
Rechte: Praktikanten, Forum
</p>
<input type="button" name="loeschen" value="löschen" onclick="self.location.href='benutzerverwaltung.php?loeschen=10'" />
Die 10 ganz am Ende ist die ID des betreffenden Elements, die brauche ich ja, um Datenbankoperationen durchzuführen. Mehr passiert eigentlich garnicht.
Viele Grüße,
Steffen
Hi!
nun, zum Thema Sicherheit: Ist mir bewusst, dass jede Variable untersucht werden sollte. Hier aber nicht. Das Skript läuft in einem geschützten Bereich und ist von aussen nicht zugänglich. Sollte es zugänglich sein, dann ist dieses Skript das kleinste Problem.
Du meinst, dass nur Leute, die eh an den Code und die Daten kommen, auf dieses Skript Zugriff haben?
Hallo,
nun, zum Thema Sicherheit: Ist mir bewusst, dass jede Variable untersucht werden sollte. Hier aber nicht. Das Skript läuft in einem geschützten Bereich und ist von aussen nicht zugänglich. Sollte es zugänglich sein, dann ist dieses Skript das kleinste Problem.
nein, das ist eine schlechte Idee. Hier ein Beleg: </archiv/2008/3/t168724/>.
Wie ich dort schrieb:
"Bitte escape _alle_ Eingaben, selbst wenn sie von geschützten Admin-
Skripten kommen. Es ist viel einfacher, _immer_ die angemessene Behandlung
zu verwenden. Es spart Überlegung - und Du bist immer auf der sicheren
Seite."
Freundliche Grüße
Vinzenz
echo $begrüßung;
Die Schleife [..] wird jedesmal angesteuert, wenn die Seite neu geladen wird, sobald man einmal auf Löschen geklickt hat und die ID 'loschen' per GET übergeben wird. (Das erste Mal soll das ja auch so sein, wenn die Seite aber wiederholt aufgerufen wird, weil andere Benutzer hinzugefügt oder bearbeitet werden, stört das gewaltig, auch wenn nichts passiert).
Zum einen kannst du nie verhindern, dass der Client Sachen anfordert, die er nicht soll. Du kannst nur dafür sorgen, dass dabei nichts geschieht, was nicht geschehen soll. Zum anderen kannst du die URL beim Client nicht manipulieren. Um sie zu ändern, muss der Client einen Request auf die neue Ressource stellen. Als Server kann man den Client mit einem Location-Header bitten, das zu tun.
echo "$verabschiedung $name";
Hello,
Das Umkopieren des $_GET-Parameters (Wieso benutzt Du übrigens nicht genau dieses superglobale Array? Durch Verwendung von $_REQUEST verschleierst Du nur unnötig die Herkunft des Werts) wird die Herkunft des Inhalts der Variablen $zuloeschen verschleiert. Darüber hinaus ist eine SEHR schlechte Idee, Eingaben von außerhalb ungeprüft an die Datenbank weiterzugeben - merke: ALL INPUT IS EVIL!
Es ist auch keine gut Idee DML-Statements (also solche, die Deine Daten verändern) per GET abzuwickeln (mit Parametern zu versorgen). Get-Requests sind u.a. dafür vorgesehen, um bookmarked zu werden.
Nimm also lieber einen Post-Request dafür und vor allem, sichere ihn ab gegen falsche oder gefälschte Parameter!
Liebe Grüße aus Syburg bei Dortmund
Tom vom Berg
Hallo Tom,
glaub mir, ich würde auch sehr gern einen Post Request verwenden, stehe allerdings gerade auf dem Schlauch, wie ich das mache. Post kann ich doch nur aus einem Formular heraus machen, oder? Der Kunde will zu jedem Eintrag einen Button mit "Löschen" und "Bearbeiten" und nicht nur einen Button ganz unten am Seitenende. Bisher habe ich das wie gesagt mit einem grafischen Link gelöst, der die ID des betreffenden Eintrags per GET mitgibt. Das funktioniert nun wohl leider nicht mehr. Für einen anderen Lösungsansatz wäre ich dankbar. Die Ausgabe sieht in etwa so aus:
Bentutzername
Passwort
Recht1, Recht2, Recht3 usw.
Button Löschen | Button Bearbeiten
---- nächster Eintrag
Bentutzername
Passwort
Recht1, Recht2, Recht3 usw.
Button Löschen | Button Bearbeiten
---- nächster Eintrag
Bentutzername
Passwort
Recht1, Recht2, Recht3 usw.
Button Löschen | Button Bearbeiten
---- nächster Eintrag
usw.
viele Grüße, Steffen
Hello,
Du kannst in Deinem Formular soviele Submitbuttons einbauen, wie Du möchtest.
Um sie zu unterscheiden, gib ihnen unterschiedliche Namen:
echo "<input type="submit" name="btn[delete][$id]" value="X" />
dann kannst Du im Formular abfragen, ob ein Button geclickt wurde, und welcher es ist:
if(isset($_POST['btn']['delete']) and count($_POST['btn']['delete']) == 1)
{
$delete_id = intval(key($_POST['btn']['delete']));
}
0 sollte eine neutrale ID darstellen, die es im Datenbestand nicht gibt.
Wenn 0 herauskommt, ist das Formular vermutlich missbraicht worden.
Ob der User einen Datensatz überhaupt Löschen darf, musst Du ja sowieso noch feststellen.
Liebe Grüße aus Syburg bei Dortmund
Tom vom Berg
Hallo Tom, hallo dedlfix,
danke schonmal. Zwei kurze Fragen:
ist mit Deiner Lösung das Problem mit dem Enter Button, das dedlfix meinte, behoben? (ich denke ja eher nicht).
Wenn du nicht pro Button ein Formular haben möchtest, dann bleibt nur ein Formular mit vielen Submitbuttons, bei dem du dann auswertest, welcher verwendet wurde. Beachte aber dabei, dass ein Formular auch per Enter abgesendet werden kann und die Nicht-IEs dann einfach irgendeinen der nicht gedrückten Submit-Buttons als aktiviert mitsenden. Dieses Problem entfällt natürlich mit einem Formular pro Eintrag, das nur einen Submitbutton als sichtbares Element hat.
bist Du sicher, dass die Syntax richtig ist? (Ich wusste nicht, dass man eckige Klammern als Name von Elementen in HTML verwenden darf und natürlich erst recht nicht, dass dadurch im auswertenden PHP Skript ein Array entsteht, aber man lernt ja nie aus).
echo "<input type="submit" name="btn[delete][$id]" value="X" />
dann kannst Du im Formular abfragen, ob ein Button geclickt wurde, und welcher es ist:
if(isset($_POST['btn']['delete']) and count($_POST['btn']['delete']) == 1)
{
$delete_id = intval(key($_POST['btn']['delete']));
}
danke schonmal!
Steffen
PS: ich dachte, du kommst aus Andreasberg? ;-)
Hallo
bist Du sicher, dass die Syntax richtig ist? (Ich wusste nicht, dass man eckige Klammern als Name von Elementen in HTML verwenden darf und natürlich erst recht nicht, dass dadurch im auswertenden PHP Skript ein Array entsteht, aber man lernt ja nie aus).
Doch, da PHP, zum Beispiel im Gegensatz zu Perl, aus den übergebenen Daten, die den gleichen Namen haben, nicht automatisch ein Array macht, braucht es die eckigen Klammern.
Du könntest auch die Datensätze in einer Liste ausgeben und einen Link zum Laden eines Datensatzes in ein Formular setzen, in dem du dann die Änderungen vornimmst. Das ergäbe allerdings einen weiteren Arbeitsschritt pro Datensatz. Ob das in deinem Fall sinnvoll wäre, musst du selbst wissen.
PS: ich dachte, du kommst aus Andreasberg? ;-)
Er kam auch schonmal aus Braunschweig. :-)
Tschö, Auge
Hello,
PS: ich dachte, du kommst aus Andreasberg? ;-)
Er kam auch schonmal aus Braunschweig. :-)
You're right. :-)
Schaun wir mal, wohin es mich dann im Januar 2009 verschlagen wird.
Zum Thema:
Ich würde das Delete nicht mit einem Button pro Datensatz machen, sondern mit einer Checkbox pro Datensatz und dann einem zusätzlichen Button. Das ist wesentlich benutzungsfreundlicher.
http://selfhtml.bitworks.de/strukturierung/deleteliste.php
Liebe Grüße aus Syburg bei Dortmund
Tom vom Berg
Hallö,
hat niemand ne Idee, wie man sowas sonst lösen kann? Mir fällt nur noch ein, für jeden Eintrag aus der Liste ein eigenes Formular mit Button machen, aber das wäre ja wirklich overengineered.
viele Grüße,
Steffen
echo $begrüßung;
hat niemand ne Idee, wie man sowas sonst lösen kann? Mir fällt nur noch ein, für jeden Eintrag aus der Liste ein eigenes Formular mit Button machen, aber das wäre ja wirklich overengineered.
Du kannst natürlich mit AJAX was zaubern, aber als eine Lösung ohne Javascript ist eine mit einem POST-Request die beste.
Du umgehst damit, dass Parameter angezeigt werden. Formulare werden im Allgemeinen auch nicht von Linkcheckern ausgeführt und ein solcher kann damit nicht mal eben beim Prüfen der Erreichbarkeit alle Datensätze löschen.
Wenn du nicht pro Button ein Formular haben möchtest, dann bleibt nur ein Formular mit vielen Submitbuttons, bei dem du dann auswertest, welcher verwendet wurde. Beachte aber dabei, dass ein Formular auch per Enter abgesendet werden kann und die Nicht-IEs dann einfach irgendeinen der nicht gedrückten Submit-Buttons als aktiviert mitsenden. Dieses Problem entfällt natürlich mit einem Formular pro Eintrag, das nur einen Submitbutton als sichtbares Element hat.
Nach dem Abarbeiten des POST-Requests empfiehlt sich ein Location-Header. Dann merkt sich normalerweise auch der Browser nicht, dass er einen solchen ausgeführt hatte beim Zurückgehen in der History.
echo "$verabschiedung $name";