Andreas: Gästebuchscript in Perl/mit MySQL - Adminfunktion

Mittels
print '<form action="http://localhost/cgi-bin/gaestebuch.pl" method="POST">';
print '<input type="hidden" name="action" value="delete" />';
....
<input type="checkbox" name="$hash_ref->{'id'}" value="$hash_ref->{'id'}" />

übergebe ich den Wert der checkbox an ein Unterprogramm

elsif ($query->param('action') eq 'delete') {
  delete();
}

sub delete {
  print $query->header;
  my $sql = "DELETE FROM eintraege WHERE id=$query->param($hash_ref->{'id'}) LIMIT 1";
  my $sth = $dbh->prepare($sql) || die "$dbh->errstr";
  print $query->start_html(-title=>'Adminfunktionen',
                           -author=>'jl@visualgrafyx.com',
                           -style=>{'src'=>'../stylesheets/style.css'});
  print "<p>Eintrag erfolgreich gelöscht</p>\n";
  print $query->end_html;
}

Es erscheint folgender Fehler:

Software error:

Not enough arguments for delete at D:\Server\Apache2\cgi-bin\gaestebuch.pl line 72, near "delete()"
Global symbol "$hash_ref" requires explicit package name at D:\Server\Apache2\cgi-bin\gaestebuch.pl line 311.
Execution of D:\Server\Apache2\cgi-bin\gaestebuch.pl aborted due to compilation errors.

Wie müsste es richtig heissen? Ich komme mit diesen Checkboxen nicht so ganz klar.

  1. guten morgen,

    Mittels [ ... ] übergebe ich den Wert der checkbox an ein Unterprogramm

    Das machst du gut, da es dabei offenbar keine Probleme gibt. Wenn aber jemand seine Eingaben wieder wegschmeißt und nix abschicken will, willst du dafür

    elsif ($query->param('action') eq 'delete') {
      delete();
    }

    benutzen. Auch gut. Mit der Klammer wird lediglich verlangt, daß null oder mehr Argumente für "delete" gelten sollen.

    Jetzt hast du aber mit

    sub delete {

    [ ... ]

    }

    angewiesen, daß dein "delete" gar keine Argumente hat - hier fehlt ganz einfach die Klammer, die du eben selbst gefordert hattest. Folgerichtig hat PERL ein Problem:

    Not enough arguments for delete

    Grüße aus Berlin

    Christoph S.

    1. guten Morgen,

      Mittels [ ... ] übergebe ich den Wert der checkbox an ein Unterprogramm
      Das machst du gut, da es dabei offenbar keine Probleme gibt. Wenn aber jemand seine Eingaben wieder wegschmeißt und nix abschicken will, willst du dafür
      elsif ($query->param('action') eq 'delete') {
        delete();
      }
      benutzen. Auch gut. Mit der Klammer wird lediglich verlangt, daß null oder mehr Argumente für "delete" gelten sollen.

      Der Wert von $hash_ref->{'id'} soll übergeben werden, damit der/die jeweilige(n) Eintrag/Einträge im Unterprogramm aus der Datenbank gelöscht werden kann/können.

      Jetzt hast du aber mit

      sub delete {
      [ ... ]
      }
      angewiesen, daß dein "delete" gar keine Argumente hat - hier fehlt ganz einfach die Klammer, die du eben selbst gefordert hattest. Folgerichtig hat PERL ein Problem:
      Not enough arguments for delete

      Das ändert nichts. $hash_ref->{'id'} scheint nicht übergeben zu werden, was ich an der zweiten Zeile der Fehlermeldung zu erkennen glaube?!

      gruss, Andreas

      1. guten Morgen nochmals,

        Der Wert von $hash_ref->{'id'} soll übergeben werden, damit der/die jeweilige(n) Eintrag/Einträge im Unterprogramm aus der Datenbank gelöscht werden kann/können.

        Es geht also nicht nur darum, daß jemand im Formular seine gerade gemachten Eingaben widerrufen können darf, sondern darum, per Script bereits vorhandene Datenbankeinträge zu löschen? Sowas ist durchaus möglich, nur sind die Scriptbestandteile, die du gepostet hast, an den Stellen, die $hash_ref betreffen, unproblematisch. Wie, warum, an welcher Stelle im Script erhält es denn seine/n Wert/e?
        Wenn $hash_ref überhaupt irgendwelche Werte an &delete() übergeben soll, so zeigt dein bisheriges Snipplet nur eine Zeile dazu, und die ist als einzelne Zeile ebenfalls unproblematisch  -  im Zusammenhang des gesamten Scripts aber möglicherweise fehlerhaft.

        Die Fehlermeldung im log "Global symbol "$hash_ref" requires explicit package name at D:\Server\Apache2\cgi-bin\gaestebuch.pl line 311" sollte ziemlich zuverlässig sein. Aber du hast nicht gesagt, was genau nun in Zeile 311 deines Scripts steht bzw. welche der von dir geposteten Zeilen die Nummer 311 ist. Dasselbe trifft auf Zeile Nummer 72 zu.

        Richtig ist auf jeden Fall, daß du bei offenbar deutlich über 311 Scriptzeilen versucht hast, nur die Stellen anzugeben, die dir problematisch erschienen sind. Es sieht allerdings so aus, als gäbe es noch mehr Stellen im Script, an denen man nachschauen müßte  -  eventuell "klemmt" es ja bereits im aufrufenden Formular. Das kann den "lesbaren" Umfang eines Forumspostings deutlich übersteigen, daher ist es vielleicht günstiger, wenn du dein gesamtes Script mal als temporäre Textdatei hochlädst und die URL hier angibst, damit man mal den Zusammenhang sehen kann. Das "listing" dabei bitte nicht vergessen, weil bestimmt nicht jeder Lust hat, erstmal bis 311 zu zählen ...

        Meine vorhin gemachte Anmerkung bleibt davon unberührt.

        Das ändert nichts. $hash_ref->{'id'} scheint nicht übergeben zu werden, was ich an der zweiten Zeile der Fehlermeldung zu erkennen glaube?!

        Obwohl ich nicht genau weiß, was denn die "zweite Zeile" ist, bin ich ähnlicher Ansicht, wie du ja aus meinen Anmerkungen herauslesen kannst. Aber was dagegen zu tun ist, erschließt sich mir (noch) nicht.

        Christoph S.

    2. elsif ($query->param('action') eq 'delete') {
        delete();
      }
      benutzen. Auch gut. Mit der Klammer wird lediglich verlangt, daß null oder mehr Argumente für "delete" gelten sollen.

      Unfug.

      Jetzt hast du aber mit

      sub delete {
      [ ... ]
      }
      angewiesen, daß dein "delete" gar keine Argumente hat - hier fehlt ganz einfach die Klammer, die du eben selbst gefordert hattest.

      Unfug.

      Folgerichtig hat PERL ein Problem:

      Not enough arguments for delete

      Höre doch bitte endlich auf, derartigen Unsinn zu verbreiten. Das ist ja grausam.

      H.

      P.S.: perldoc -f delete

      1. hallo Henner,

        Unfug.
        Unfug.
        Höre doch bitte endlich auf, derartigen Unsinn zu verbreiten. Das ist ja grausam.

        Ich werde es beherzigen.

        Grüße aus Berlin

        Christoph S.

  2. Hallo,

    <input type="checkbox" name="$hash_ref->{'id'}" value="$hash_ref->{'id'}" />

    Ich denke mal in $hash_ref->{'id'} steht die ID eines Datensatzes, den Du gerade von der Datenbank gelesen hast. Es ist allerdings imho sehr problematisch, Formularelemente so zu benennen, da sie bei der Abarbeitung des abgesendeten Forumulars schwer zu identifizieren sind.
    Sinnvoll wäre es imho, wenn alle Checkboxen einen Namen haben, und Du sie beispielsweise mit

    my(@delete_ids) = $query->param('delete_id');

    ausliest. (Wernn ich davon ausgehe, daß die Checkboxen delete_id heißen und Du das CGI-Modul einsetzt, und Dein Query-Objekt $query heißt)

    sub delete {

    Es ist äußerst gefährlich, wenn Du Namen von build-in-Funktionen für deine eigenen verwendest. Perl unterstützt zwar das Überladen von Funktionen, es sollte allerdings wirklich  nur in den seltensten Fällen Sinn machen, es auch zu tun. In Deinem Fall hat es nicht so funktioniert, deshalb auch die Fehlermeldung bezüglich fehlender Argumente

    print $query->header;
      my $sql = "DELETE FROM eintraege WHERE id=$query->param($hash_ref->{'id'}) LIMIT 1";

    Ich denke einmal, daß das die ominöse Zeile 311 ist. Aufgrund der Fehlermeldung denke ich, daß $hash_ref im aktuellen Kontext des Programmes nicht erzeugt ist, geschweige denn einen sinnvollen Wert besitzt.
    Bedenke, daß jeder Script-Aufruf quasi ein Universum für sich ist. _Nach_ dem abschicken des Formulars weiß das aufgerufene Script nichts über die Zustände jenes Scripts, welches das Formular erzeugt hat (auch wenn beide das selbe Script sind). Du mußt schon die CGI-Parameter auslesen, um zu den übergebenen Werten zu kommen. Einfach nur einen Variablennamen wieder zu verwenden reicht nicht.

    my $sth = $dbh->prepare($sql) || die "$dbh->errstr";
      print $query->start_html(-title=>'Adminfunktionen',
                               -author=>'jl@visualgrafyx.com',
                               -style=>{'src'=>'../stylesheets/style.css'});
      print "<p>Eintrag erfolgreich gelöscht</p>\n";
      print $query->end_html;

    Dir ist hoffentlcih klar, daß hier kein Löschvorgang ausgeführt wird. Ein prepare() alleine genügt nicht. Du muß es dann schon noch mit execute() ausführen und, je nach DB-Verbindungseinstellungen auch mittels commit() bestätigen (wenn AutoCommit abeschaltet ist, was ich persönlich immer mache).

    Außerdem lassen Checkboxen vermuten, daß Du potentiell mehrere Einträge gleichzeitig löschen willst, welshalb ich an Deiner Stelle die Bestätigungsmeldung überarbeiten würde.

    Grüße
      Klaus