Antworten auf deine Fragen:
Neues Thema erstellen

Antworten zum Thema „Vermeiden, daß mehrere gleichzeitig den selben Datensatz bearbeiten (erl. Danke)“

strichcode

Nicht mehr ganz neu hier

Hallo Ihr Lieben,

Über ein Formular können die Datensätze meiner DB geändert werden.
Nun möchte ich vermeiden, daß mehrere Leute gleichzeitig den selben Datensatz aufrufen können.

In der DB habe ich dazu ein Feld "BESETZT".

Ich möchte jetzt, wenn ich die Seite aufrufe, sofort das Feld BESETZT auf "on" setzten.
Gleichzeitig frage ich bei Aufruf der Seite ab, ob das Feld on ist, nach dem Motto:
Wenn BESETZT = on, dann "Der Datensatz wird schon bearbeitet".
Wenn nicht, dann normal die Seite aufrufen.

Das obige funktioniert schon.

Nur der Teil, wo bei Aufruf der Seite das Feld auf "on" gestellt werden soll, noch nicht.
Es wird auch keine Fehlermeldung gezeigt.

Wenn Ihr da bitte mal drüber gucken könnt, ich sitz jetzt schon den ganzen Vormittag dran, und sehe den
Wald vor Bäumen nicht mehr.

Sollte mein Lösungsweg überhaupt dafür nicht der Richtige sein, lasst es mich auch Wissen,
ich bin immer noch blutiger Anfänger in php und für Hilfe immer dankbar.

LG
Heike

PHP:
<?php
//Objekt in der DB als BESETZT setzten, damit keine zwei Mitarbeiter gleichzeitig das Objekt bearbeiten können.

$dbh = mysql_connect($db_host, $db_user, $db_pass)
    or die("Keine Verbindung möglich: " . mysql_error());

mysql_select_db($db_name) or die("Auswahl der Datenbank fehlgeschlagen");
if (isset( $_POST['eintragen2'] ))
{
$TTG_NR = $_POST['TTG_NR'];


}
$abfrage = "SELECT * FROM stammdaten WHERE TTG_NR = '".$_POST['TTG_NR']."'";
if (isset( $_POST['eintragen2'] ))

{
$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
              SET
              `BESETZT`='on'
              WHERE
                  `TTG_NR`='$TTG_NR' ";
$update = mysql_query($aendern)or die(mysql_error());
}

?>
 

Duddle

Posting-Frequenz: 14µHz

Die Variable $abfrage wird schonmal nicht benutzt, das kann also raus. Dann können die beiden if-Unterscheidungen zusammengefasst und die Doppelung der $TTG_NR-Initialisierung entfernt werden, um es übersichtlicher zu machen:
PHP:
if (isset( $_POST['eintragen2'] )) {
  $TTG_NR = $_POST['TTG_NR'];
  $aendern = "UPDATE `stammdaten`
   SET
   `BESETZT`='on'
   WHERE
   `TTG_NR`='$TTG_NR' ";
  $update = mysql_query($aendern)or die(mysql_error());
}
Zuerst fragst du nicht ab, ob $_POST['TTG_NR'] überhaupt gesetzt ist. Das mag unwahrscheinlich sein wenn es im gleichen Formular mitgeschickt wird, aber eine entsprechende Überprüfung und mögliche Fehlerausgabe würde dir mehr verraten. Gleiches gilt für $update. Da dir mysql_query() nur ein FALSE ausgibt wenn ein Fehler auftritt, weißt du nicht ob das UPDATE irgendetwas verändert hat. Dafür kannst du einsetzen.

Hilfreich wird auch sein, wenn du dir Variablen testweise ausgeben lässt. Was steht z.B. in $aendern drin, bevor du es an den MySQL-Server schickst. Was passiert, wenn du diese Anfrage manuell per phpMyAdmin o.ä. abschickst. So grenzt du Schritt für Schritt die Fehlerquelle ein, bis du sie gefunden hast.

Syntaktisch sehe ich unmittelbar keinen Fehler, es liegt wohl an den übergebenen Daten. Oder an etwas externem, was nicht im Codeauszug sichtbar ist.

Sollte mein Lösungsweg überhaupt dafür nicht der Richtige sein, lasst es mich auch Wissen,
Du hast einen kritischen Abschnitt und willst ihn per Lock schützen, das ist ein üblicher Ansatz. Du darfst nur die Feinheiten nicht übersehen (z.B. ein Timeout für den Besitzer des Locks).


Duddle
 

strichcode

Nicht mehr ganz neu hier

Hallo Duddle,
danke, daß Du mir helfen möchtest.

Ich verstehe nicht allzuviel von der Sache, aber soviel schon mal:
Gebe ich
Code:
UPDATE `stammdaten`
   SET
   `BESETZT`='on'
   WHERE
   `TTG_NR`='09123456'
in phpMyAdmin ein, dann schreibt es brav ein "on" in das DB-Feld.

Ersetzte ich in meinem php-sccript
Code:
WHERE
   `TTG_NR`='$TTG_NR' ";

mit
Code:
   WHERE
   `TTG_NR`='09123456' ";

passiert wieder nichts.

Etwas stimmt also nicht mit meinem if, oder?

Und:
Zuerst fragst du nicht ab, ob $_POST['TTG_NR'] überhaupt gesetzt ist.

Ich dachte das tue ich, durch isset?

Falls der Fehler bei etwas externem, was nicht im codeauszug zu sehen ist, liegen sollte....
Ich will das ganze Script nicht hier posten, denn es ist 1400 Zeilen lang.
Wonach könnte ich den suchen?
 

Duddle

Posting-Frequenz: 14µHz

Wenn die Abfrage manuell funktioniert, aber nicht im Script, dann wird entweder das if übergangen oder es wird nicht übergangen und darin funktioniert etwas nicht (fehlende Verbindung zum MySQL-Server, ein Syntax-Fehler, usw). Überprüfen kannst du es mit ein paar Debugging-Ausgaben. Ein Beispiel:
PHP:
echo "vor dem if<br>";

if (isset( $_POST['eintragen2'] )) {
echo "im if<br>";

$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='on'
WHERE
`TTG_NR`='$TTG_NR' ";

echo "aendern: $aendern<br>";

$update = mysql_query($aendern)or die(mysql_error());
echo "update hat ".mysql_affected_rows()." zeilen veraendert <br>";
}

echo "nach dem if<br>";
Edit:
Ich dachte das tue ich, durch isset?
Nein, du prüfst $_POST['eintragen2'] nicht $_POST['TTG_NR'].


Duddle
 

strichcode

Nicht mehr ganz neu hier

Nein, du prüfst $_POST['eintragen2'] nicht $_POST['TTG_NR'].
Aha?!
Sollte ich dann so schreiben:
if (isset($TTG_NR)) {
echo "TTG_NR ist da!";
}
oder ist das quatsch?
Und:
Ich finde, das if wird übergangen:

vor dem if
nach dem if

sonst passiert nichts.

Viel weiter sind wir nicht, oder?
 

Duddle

Posting-Frequenz: 14µHz

Also weisst du jetzt, dass das if übersprungen wird. Es wird übersprungen, wenn $_POST['eintragen2'] nicht gesetzt wird. Also ist das Formular, was seine Daten an dieses Script schickt, inkorrekt oder es wird falsch ausgewertet. Überprüfe, ob das Formular ein Formular-Element mit Namen "eintragen2" hat. Überprüfe (z.B. mit FireBug) ob die Daten korrekt per POST übermittelt werden.


Duddle
 

Duddle

Posting-Frequenz: 14µHz

Geh auf die Seite mit dem Formular, aktivier FireBug, geh in den Netzwerk-Tab (notfalls aktivieren), dann schick das Formular ab. Du solltest alle entstehenden POST- und GET-Requests aufgelistet sehen. Den für das Formular schaust du dir dann genauer an.
Alternativ baust du dir in dein Script eine Ausgabe ein, ala:
PHP:
echo "POST hat: <pre>".print_r($_POST)."</pre>";


Duddle
 

strichcode

Nicht mehr ganz neu hier

Soo, ich habe beides gemacht:
Setze ich echo "Post hat.... bei "vor dem if"

PHP:
$dbh = mysql_connect($db_host, $db_user, $db_pass)
    or die("Keine Verbindung möglich: " . mysql_error());

mysql_select_db($db_name) or die("Auswahl der Datenbank fehlgeschlagen");
if (isset( $_POST['eintragen2'] ))
{
$TTG_NR = $_POST['TTG_NR'];
}

echo "vor dem if<br>";
echo "POST hat: <pre>".print_r($_POST)."</pre>";
if (isset( $_POST['eintragen2'] )) {
echo "im if<br>";

$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='on'
WHERE
`TTG_NR`='$TTG_NR' ";

echo "aendern: $aendern<br>";

$update = mysql_query($aendern)or die(mysql_error());
echo "update hat ".mysql_affected_rows()." zeilen veraendert <br>";
}

echo "nach dem if<br>";
erhalte ich:
vor dem if
Array ( [TTG_NR] => 09123456 ) POST hat:
1
nach dem if

Setze ich aber echo "Post hat..." bei "im if..."
Code:
$dbh = mysql_connect($db_host, $db_user, $db_pass)
    or die("Keine Verbindung möglich: " . mysql_error());

mysql_select_db($db_name) or die("Auswahl der Datenbank fehlgeschlagen");
if (isset( $_POST['eintragen2'] ))
{
$TTG_NR = $_POST['TTG_NR'];
}

echo "vor dem if<br>";

if (isset( $_POST['eintragen2'] )) {
echo "im if<br>";
echo "POST hat: <pre>".print_r($_POST)."</pre>";
$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='on'
WHERE
`TTG_NR`='$TTG_NR' ";

echo "aendern: $aendern<br>";

$update = mysql_query($aendern)or die(mysql_error());
echo "update hat ".mysql_affected_rows()." zeilen veraendert <br>";
}

echo "nach dem if<br>";

erhalte ich:
vor dem if
nach dem if

In beiden Fällen sagt Firebug:
Parameterapplication/x-www-form-urlencoded
TTG_NR09123456
Quelle
TTG_NR=09123456

Danke für Deine Geduld.
 

Duddle

Posting-Frequenz: 14µHz

Du solltest daraus ableiten können, dass im POST-Request nur die Variable TTG_NR übergeben wird. Um aber in das wichtige if zu kommen, überprüfst du das Vorhandensein der Variable eintragen2 im POST. Dein Formular schickt also nicht genügend/die falschen Daten mit.


Duddle
 

strichcode

Nicht mehr ganz neu hier

Ich hab's!
Die Lösung ist so simpel, daß ich mich es kaum traue zu sagen.
Der ganze If-Kram kann weg, denn es soll ja bei Aufruf der Seite das Besetzt gesetzt werden und nicht,
wenn man irgendwas abschickt.
Damit soll sicher gestellt werden, daß dieses Formular nur von einer Person gleichzeitig bearbeitet werden kann.

Ich entschuldige mich an dieser Stelle dann mal ganz dolle dafür das ich Deine Zeit umsonst in Anspruch genommen habe.

Einen Schritt weiter, den ich nun bin, stehe ich vor dem nächsten Problem: nämlich bei Abschicken des Formulars das Besetzt wieder
rückgängig zu machen.
PHP:
$dbh = mysql_connect($db_host, $db_user, $db_pass)
    or die("Keine Verbindung möglich: " . mysql_error());

mysql_select_db($db_name) or die("Auswahl der Datenbank fehlgeschlagen");

if (isset( $_POST['eintragen'] ))
{
    // Maskierende Slashes aus POST entfernen
    $_POST = get_magic_quotes_gpc() ? array_map( 'stripslashes', $_POST ) : $_POST;
   
    // Inhalte der Felder aus POST holen
    $TTG_NR = $_POST['TTG_NR'];   
    $BESETZT = $_POST['BESETZT'];   
//    usw. ganz viele Felder des Formulars

    $conID = mysql_connect( $db_host, $db_user, $db_pass ) or die( "Die Datenbank konnte nicht erreicht werden!" );
    if ($conID)
    {
        mysql_select_db( $db_name, $conID );
    }
}
$abfrage = "SELECT * FROM stammdaten WHERE TTG_NR = '".$_POST['TTG_NR']."'";
?><?php
if (isset( $_POST['eintragen'] ))
{
$TTG_NR = $_POST['TTG_NR'];
    $BESETZT = $_POST['BESETZT'];   
//usw. ganz viele Felder des Formulars

$sqlupdate = "UPDATE `stammdaten`
              SET
            `TTG_NR`='" .mysql_real_escape_string( $TTG_NR ). "',
//           usw. ganz viele Felder des Formulars
            `BESETZT`='ne'
              WHERE
                  `TTG_NR`='$TTG_NR' ";
$update = mysql_query($sqlupdate)or die(mysql_error());
header("Location: aufrufen.html");

Im Formular selbst gibt es
HTML:
<input type = "hidden" name="BESETZT" size = "13" value = "ne"/>
Firebug gibt die Parameter:
BESETZTne
TTG_NR09123456
und all die anderen aus.
Quelle:BESETZT=ne&TTG_NR=09123456 usw.
Alle Datenbankfelder werden wie gewünscht geändert, nur BESETZT nicht.
Was übersehe ich diesmal?
Und: nochmal Danke für Deine Geduld.
 

Duddle

Posting-Frequenz: 14µHz

Gleiches Prinzip wie vorher: lass dir $sqlupdate vor dem mysql_query() ausgeben, probier die Anfrage manuell per phpMyAdmin o.ä., sieh ob es da funktioniert. Wenn definitiv die neuen Daten übernommen werden, scheinst du ja zum UPDATE zu kommen, nur macht es eben nicht alles. Also muss der Fehler in der SQL-Anfrage selbst bzw. wie der Server sie verarbeitet liegen.


Duddle
 

strichcode

Nicht mehr ganz neu hier

Ich glaube, ich habe jetzt das Problem gefunden, bräuchte jetzt nur noch eine Lösung ;-)
Und ich hoffe, das jetzt erklären zu können, ohne das es allzu wirr klingt.

Weil:
Array ( [BESETZT] => ne [TTG_NR] => 09123456 => [eintragen] => Abschicken )
POST hat: 1
update hat 1 zeilen veraendert
und weil die Abfrage in phpmyadmin funktioniert,
habe ich mal den Teil ausgeklammert, der dafür sorgt das Besetzt auf "ON" gesetzt wird.
Dann hat der Update Besetzt auf "ne" zu stellen funktioniert.

Meine irre Theorie ist nun:
Bei Aufruf der Seite setzt er Besetzt auf "ON",
bei Abschicken des formulars macht er Besetzt auf "ne"
und dann wieder auf ON.

Ich habe diesen Teil:
PHP:
<?php
//Objekt in der DB als BESETZT setzten, damit keine zwei Mitarbeiter gleichzeitig das Objekt bearbeiten können.

$dbh = mysql_connect($db_host, $db_user, $db_pass)
    or die("Keine Verbindung möglich: " . mysql_error());

mysql_select_db($db_name) or die("Auswahl der Datenbank fehlgeschlagen");

$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='on'
WHERE
`TTG_NR`='$TTG_NR' ";


$update = mysql_query($aendern)or die(mysql_error());
echo "update hat ".mysql_affected_rows()." zeilen veraendert <br>";

?>
in meinem Formular stehen. Der muß da stehen, sonst habe ich die TTG-NR nicht. Wegen
<form action="<?php echo $_SERVER['PHP_SELF']; ?>

Vorher frage ich:
PHP:
$ergebnis = mysql_query($abfrage);
while ($daten = mysql_fetch_array( $ergebnis, MYSQL_ASSOC))
if  ($daten['BESETZT'] =='on'){
     echo '
<div>Dieses Objekt wird schon von einem anderen Mitarbeiter bearbeitet! Versuchen Sie es später noch einmal.
</div></body></html>
';}

else {echo '</div>
<!-- #content -->
<!-- hier beginnt das formular-->

Der Teil, der das Formular nun ausliest und das update macht,
PHP:
if (isset( $_POST['eintragen'] ))
{
$TTG_NR = $_POST['TTG_NR'];
    $BESETZT = $_POST['BESETZT'];  
//usw. ganz viele Felder des Formulars

$sqlupdate = "UPDATE `stammdaten`
              SET
            `TTG_NR`='" .mysql_real_escape_string( $TTG_NR ). "',
//           usw. ganz viele Felder des Formulars
            `BESETZT`='ne'
              WHERE
                  `TTG_NR`='$TTG_NR' ";
$update = mysql_query($sqlupdate)or die(mysql_error());
header("Location: aufrufen.html");

steht bevor das html los geht vor dem
<!DOCTYPE html .....

Also denke ich, das Besetzt-Feld wird erst "on", dann "ne", dann wieder "on" gesetzt.

Meine Versuche mit der Reihenfolge rumzuspielen haben keinen Erfolg gebracht.

Kannst Du mir sagen, ob ich mit meiner Vermutung richtig liege, und was ich machen könnte.
Danke für Deine Geduld.
 

Duddle

Posting-Frequenz: 14µHz

Ich kann deiner Reihenfolge gerade nicht 100%ig folgen. Der Workflow sollte so ablaufen:

1. Nutzer ruft Seite mit dem Formular auf, Seite prüft ob dieser Datensatz BESETZT ist.
2.a) Falls ja: eine Fehlermeldung.
2.b) Falls nein: der Datensatz wird als BESETZT markiert. Die Seite zeigt das Formular.
3. Beim Abschicken des Formulars (was du mit isset($_POST['eintragen']) erkennst) wird geprüft, ob es fehlerfrei ist.
4.a) Falls ja: der Datensatz wird als nicht mehr BESETZT markiert, die neuen Daten werden abgespeichert
4.b) Falls nein: die Seite zeigt nochmal das Formular, idealerweise mit den vorher eingetragenen/veränderten Daten. Dann zurück zu 3.

Wenn das funktioniert, ist dein Problem noch nicht komplett gelöst, aber dazu können wir danach kommen.


Duddle
 

strichcode

Nicht mehr ganz neu hier

Danke für's Mitdenken! Wenn ich mich genau an Deine Reihenfolge halte, funktioniert es.
Code:
if  ($daten['BESETZT'] =='on'){
     echo '
<div>Dieses Objekt wird schon von einem anderen Mitarbeiter bearbeitet! Versuchen Sie es später noch einmal.
</div></body></html>
';
mysql_close($dbh);}
else {
$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='on'
WHERE
`TTG_NR`='$TTG_NR' ";
echo "aendern: $aendern<br>";
$update = mysql_query($aendern)or die(mysql_error());
}

if (isset( $_POST['eintragen'] ))
{
//jetzt das Formular auslesen, updaten und dabei BESETZT auf "ne" stellen
{

Nochmal ein ganz DICKES DANKESCHÖN für Deine Geduld.
 

Duddle

Posting-Frequenz: 14µHz

Jetzt musst du nur noch einbauen was passiert, wenn ein Nutzer ein Formular editiert und dann essen geht oder sein PC abstürzt. Anders gesagt: du brauchst einen Timeout-Mechanismus für die Interaktion mit der Seite, sonst sammeln sich über die Zeit gesperrte Datensätze an.


Duddle
 

strichcode

Nicht mehr ganz neu hier

Stimmt!..... Ruft ein Mitarbeiter die Seite auf, bearbeitet sie aber nicht, sondern schließt einfach den Browser, ist das BESETZT ja noch auf "on".
Ich finde unter "timeout" nur Sachen über zu große Datenmengen, oder Scriptabbrüche,
hast Du mal ein paar Stichworte zum googlen für mich?
 

Duddle

Posting-Frequenz: 14µHz

Wie anfangs gesagt, du hast ein Lock implementiert und stößt jetzt auf ein mögliches Verhungern der teilnehmenden Prozesse/Nutzer.

Ein Lösungsansatz ist dieser: du hast für jeden (gesperrten) Datensatz eine "letzte Aktivität" als Zeitstempel. Beim Aufrufen prüft die Seite, ob der Datensatz bereits gesperrt ist (siehe oben: Schritt 1): falls ja, prüfst du zusätzlich, ob die letzte Aktivität länger als 30 Minuten her ist. Wenn ja, entsperre den Artikel. Die restliche Logik (oben als 2b bezeichnet) sperrt ihn dann gleich wieder.
Zusätzlich wird bei jeder Aktion des Nutzers (im gröbsten Fall nur das Setzen einer Sperre und das Abschicken des Formulars) der Zeitstempel aktualisiert.


Duddle
 

strichcode

Nicht mehr ganz neu hier

Hallo Duddle,
ich hatte noch andere Sachen auf dem Schreibtisch - bin aber noch dran ;-)

In der Datenbank ist ein timestamp-Feld AENDERDATUM, dort steht z.B.
2014-03-28 10:53:57

Dieses wollte ich benutzen, um den unteren code auszuführen (ab if).
Vorher lasse ich mir das Datum testweise einmal zeigen.

PHP:
$datefrei = "SELECT UNIX_TIMESTAMP (AENDERDATUM) FROM stammdaten WHERE TTG_NR = '".$_POST['TTG_NR']."'";
$datefreiergebnis = mysql_query($datefrei);
$stamp = $datefreiergebnis ['UNIX_TIMESTAMP (AENDERDATUM)'];
echo date("d.m.Y - H:i:s", $stamp);
if( time()-$stamp >= 60 ) {
$TTG_NR = $_POST['TTG_NR'];
$aendern = "UPDATE `stammdaten`
SET
`BESETZT`='ne'
WHERE
`TTG_NR`='$TTG_NR' ";
}
}

Davon mal abgesehen, daß ich noch gar nicht weiß, ob der untere Teil funktionieren wird, stehe ich schon vor folgendem Problem:

Strict Standards: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin' for 'CET/1.0/no DST' instead in /*/kurzformular.php on line 44
01.01.1970 - 01:00:00

Ich hab jetzt ne ganze weile hin und her gegooglet, aber ich verstehe das ganze nicht.
Muß ich das "2014-03-28 10:53:57" umwandeln in eine Zahl, auf die ich dann z.B. 60 Sekunden draufrechnen kann, um meine Abfrage auszuführen?
Wenn ja, was mache ich falsch?

Danke für Deine Geduld.
(meine ist bald am Ende ;-))) ) Wie oben schon mal gesagt, ich bin Anfänger und mir qualmt der Kopf. ;-)
 

Duddle

Posting-Frequenz: 14µHz

Die Warnung sagt ja aus, dass du entweder die Option date.timezone explizit setzen oder zumindest die Funktion aufrufen musst. Letztere kann dann einfach am Anfang des Scriptes stehen, also z.B.
PHP:
date_default_timezone_set("Europe/Berlin");
Dann wird er auch nicht mehr bei date() meckern.

Mehr direkte Fehler sehe ich jetzt aber nicht.


Duddle
 
Bilder bitte hier hochladen und danach über das Bild-Icon (Direktlink vorher kopieren) platzieren.
Antworten auf deine Fragen:
Neues Thema erstellen

Willkommen auf PSD-Tutorials.de

In unseren Foren vernetzt du dich mit anderen Personen, um dich rund um die Themen Fotografie, Grafik, Gestaltung, Bildbearbeitung und 3D auszutauschen. Außerdem schalten wir für dich regelmäßig kostenlose Inhalte frei. Liebe Grüße senden dir die PSD-Gründer Stefan und Matthias Petri aus Waren an der Müritz. Hier erfährst du mehr über uns.

Stefan und Matthias Petri von PSD-Tutorials.de

Nächster neuer Gratisinhalt

03
Stunden
:
:
25
Minuten
:
:
19
Sekunden

Flatrate für Tutorials, Assets, Vorlagen

Statistik des Forums

Themen
175.157
Beiträge
2.581.864
Mitglieder
67.223
Neuestes Mitglied
Desiree
Oben