# PHP in JavaScript-Funktion ausführen



## Eiszwerg (11. Juni 2005)

```
function Freigeben () {
  <?
  include("vars.php");
  mysql_connect ($server,$user,$pw) or die ("Es besteht keine DB Verbindung :o(");
  $dbanfrage = "UPDATE $table1 SET safe='0' WHERE id='$id'";
  $result = mysql_db_query ($db, $dbanfrage) or die (mysql_error());
  ?>
}
```

Ich stelle mir vor, dass ich mittels <body OnUnload="Freigeben()"> den Wert "safe" in der Datenbank auf "0" setzen kann, wenn man die Seite verlässt.
Kann das klappen?
Momentan läuft's nicht wirklich rund, aber der Fehler kann ja auch woanders liegen.
Also meine Frage: Ist obiger Code funktional oder wird der php-Code unabhängig vom Rest im Vorraus interpretiert?


----------



## hpvw (11. Juni 2005)

Eiszwerg hat gesagt.:
			
		

> Kann das klappen?


Nein. Da PHP-Skripte nur ausgeführt werden, wenn der Server eine Anfrage empfängt. Wenn ich meinen Browser schließe oder Deine Seite verlasse, wird mein Browser keine weitere Anfrage an Deinen Server senden.

Der gängige Workaround ist, bei jeder Anfrage (=jedem Seitenaufruf) einen Timestamp zu speichern und davon auszugehen, dass der User nicht mehr auf der Seite ist, wenn eine bestimmte Zeit vergangen ist.

Gruß hpvw


----------



## Eiszwerg (12. Juni 2005)

Nun, die Pronlematik lässt sich mit dem Workaround aber nicht lösen.
Es geht um eine DB, bei der es vorkommen kann, dass mehrere User auf ein und denselben Datensatz zugreifen. Dies soll natürlich nicht möglich sein und so muss dieser beim ersten Aufruf gesperrt werden und auch wieder freigegeben werden, wenn dieser erste User ihn verlässt.
OnUnload ist aber sowieso ein Denkfehler für dieses Vorhaben, wie mir mittlerweile aufgefallen ist.


----------



## Sven Mintel (12. Juni 2005)

Für dieses Vorhaben bräuchtest du solch diziplinierte User, welche, sobald sie fertig sind, dies vermelden, bspw. per Logout-Button.

Für gewöhnlich ist diese Disziplin nicht zu erwarten


----------



## hpvw (12. Juni 2005)

Ich denke, gerade die Problematik lässt sich so lösen.
Eine andere Möglichkeit wäre höchstens, dass der User explizit angibt, dass er mit der Bearbeitung fertig ist, was natürlich automatisch passiert, wenn er Speichern klickt oder "manuell", wenn er Abbrechen klickt.
Die beiden Ansätze lassen sich natürlich kombinieren:

*Du benötigst eine Tabelle, in der Du die LOCKs verwaltest:*
ID (int), LOCKStart (datetime), LOCKUserID (int), LOCKDatensatzID(int), LastChangeOfDatensatz (datetime), LOCKActive (boolean/enum)

*Fälle/Abläufe*

*User 1 wählt bestimmten Datensatz zur Bearbeitung.*
-> LOCK prüfen, es ist kein LOCK aktiv und restl. Bed. egal.
-> LOCK auf diesen Datensatz setzen, mit UserID/SessionID und Zeitstempel der Anfrage


*User 2 will diesen Datensatz vor [Zeitstempell + x] bearbeiten*
-> LOCK prüfen, es ist nicht "kein LOCK" und nicht ein LOCK auf User 2 und LOCK ist nicht abgelaufen.
-> Meldung: "Dieser Datensatz wird von User 1 bearbeitet und steht spätestens um [Zeitstempel + x] wieder zur Bearbeitung zur Verfügung."


*User 2 will diesen Datensatz nach [Zeitstempell + x] bearbeiten*
-> LOCK prüfen, es ist nicht "kein LOCK" und nicht ein LOCK auf User 2, aber LOCK ist abgelaufen.
-> eigenen LOCK setzen, LOCK von User 1 inaktiv setzen, User 1 hat es verpennt


*User 1 klickt Abbrechen:*
-> LOCK auf inaktiv setzen


*User 1 klickt Speichern vor [Zeitstempel + x]:*
-> LOCK prüfen, es ist der LOCK, der in der UserSession gespeichert ist, er ist noch nicht abgelaufen.
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK auf inaktiv setzen


*User 1 klickt Speichern nach [Zeitstempel + x], keiner war in der Zwischenzeit am Datensatz:*
-> LOCK prüfen, letzter ist der LOCK, der in der UserSession gespeichert ist, er ist abgelaufen, macht aber nix
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK auf inaktiv setzen


*User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit den Datensatz geändert:*
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist inaktiv
-> LastChange des Datensatz mit LastChange aus dem eigenen LOCK vergleichen. (LastChange > als LastChange im LOCK)
-> Meldung: "Du warst zu langsam, der Datensatz wurde von User 2 geändert", Weiterleitung zur Bearbeitungsausgangsseite -> weiter mit Ablauf 1


*User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit den Datensatz bearbeiten wollen, aber abgebrochen:*
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist inaktiv
-> LastChange des Datensatz mit LastChange aus dem eigenen LOCK vergleichen. (LastChange < als LastChange im LOCK)
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK ist bereits inaktiv


*User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit angefangen, den Datensatz zu bearbeiten und ist noch dabei (oder hat ohne Abbrechen zu drücken aufgehört):*
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist aktiv
-> Meldung: "Du warst zu langsam, User 2 bearbeitet jetzt den Datensatz"
*ACHTUNG:*

Die LOCKs werden nicht gelöscht, sondern nur inaktiv gesetzt.
Es ist eine sinnvolle Größenordnung für x zu finden.
Jeder der beschriebenen Absätze muss als eine Transaktion ausgeführt werden.
Weiterhin musst Du Dir überlegen, ob Du dem User nur die Zeit x vom ersten "ich will bearbeiten" bis zum speichern geben willst, oder aber, ob die Anfangszeit des LOCK bei jedem Seitenaufruf (z.B: einer Vorschau) aktualisiert wird. Ich habe oben den ersten Fall beschrieben, da es bei einer Aktualisierung nicht möglich ist, dem User 2 eine sinnvolle Zeit zu nennen, wann er wieder kommen kann.
*Eine kleine Unanehmlichkeit ergibt sich in folgendem Fall:*
User 1 holt sich einen LOCK, User 2 "klaut" diesen LOCK nach [Zeitstempel LOCK User 1 + x], schließt aber einfach seinen Browser, trödelt selbst oder geht von der Bearbeiten-Seite ohne Abbrechen weg. User 1 ist Beamter und klickt erst nach [Zeitstempel LOCK User 2 + x] auf Speichern. Er könnte nun eigentlich gefahrlos Speichern, wird jedoch, da der LOCK von User 2 noch aktiv (aber obwohl dieser LOCK abgelaufen) ist, auf die Bearbeiten-Start-Seite weitergeleitet ohne zu speichern (Kommt zu Schritt 1). Hier wird dann ein neuer LOCK auf User 1 gesetzt und der LOCK von User 2 inaktiv gesetzt.
Wer so langsam ist, hat es dann aber auch nicht anders verdient und muss die Eingaben wiederholen.

Ich hoffe ich habe jetzt nichts vergessen.

Wenn Du zuviel Zeit hast, kannst Du das natürlich auch um LOCK-Reservierungen erweitern 

Gruß hpvw


----------



## Sven Mintel (12. Juni 2005)

hpvw hat gesagt.:
			
		

> User 1 ist Beamter und klickt erst nach [Zeitstempel LOCK User 2 + x] auf Speichern


:suspekt: der war gut

Man könnte eine UserID in dem Lock speichern.

Per JS sendet man in Intervallen eine Anfrage an ein PHP-Skript, welches den Zeitstempel aktualisiert(natürlich nur, wenn es der betreffende User ist).

So kann man schon mal ermitteln, ob das Fenster noch da ist.

Um zu vermeiden, dass ein Beamter grad mal seine wohlverdiente 3h-Mittagspause macht, und das Fenster offen lässt...was die DB für die anderen blockieren würde, könnte man nach einem best. Zeitraum der Inaktivität(bspw. per mousemove-Überwachung) einen alert() loslassen, welcher bestätigt werden muss.

Wenn er nicht bestätigt wird, fliegt er halt raus.


----------



## hpvw (12. Juni 2005)

Sven Mintel hat gesagt.:
			
		

> Man könnte eine UserID in dem Lock speichern.


 Hab ich doch  (LOCKUserID)



			
				Sven Mintel hat gesagt.:
			
		

> Per JS sendet man in Intervallen eine Anfrage an ein PHP-Skript, welches den Zeitstempel aktualisiert(natürlich nur, wenn es der betreffende User ist).


Ein echter Vorteil für User mit JavaScript.



			
				Sven Mintel hat gesagt.:
			
		

> Um zu vermeiden, dass ein Beamter grad mal seine wohlverdiente 3h-Mittagspause macht, und das Fenster offen lässt...


Hoffentlich hat er wenigstens die Heizung ausgemacht.



			
				Sven Mintel hat gesagt.:
			
		

> was die DB für die anderen blockieren würde, könnte man nach einem best. Zeitraum der Inaktivität(bspw. per mousemove-Überwachung) einen alert() loslassen, welcher bestätigt werden muss.


Das könnte dem Beamten zwar einen Herzinfarkt bescheren, ist aber eine Interessante Möglichkeit zur Anwesenheitskontrolle.

Aber wie willst Du mit JS eine Anfrage schicken, ohne die Seite neu zu laden?

Gruß hpvw


----------



## Sven Mintel (12. Juni 2005)

hpvw hat gesagt.:
			
		

> Das könnte dem Beamten zwar einen Herzinfarkt bescheren.



Naja...das spart dann immerhin noch Steuergelder(im Erfolgsfall) 



			
				hpvw hat gesagt.:
			
		

> Aber wie willst Du mit JS eine Anfrage schicken, ohne die Seite neu zu laden?



Per XMLHttpRequest,...googel mal ein bisschen danach herum, ist ne interessante Sache.
Wird derzeit unterstützt von IE,Gecko,Opera8 und Safari.

Die nächste Version unserer Boardsoftware wird damit z.B. verstärkt arbeiten.


----------



## Eiszwerg (12. Juni 2005)

Also erstmal vielen lieben Dank für die Anregungen!
Mittlerweile bin ich so verwirrt, dass ich die momentan 8 User wohl einfach ündlich daraufhinweisen werde, dass der Speicherknopf zu drücken ist, um die Sperre aufzuheben und NICHT "zurück" oder "ALT+F4" zu benutzen.
Da die Herren Kollegen sehr diszipliniert sind, wird das wohl schon werden.

Trotzdem noch einen herzlichen Dank an die "Mitdenker"!


----------



## Shipstar (24. Februar 2009)

Guten Tag allemann,
auch wenn ich weiß, das dieser Thread nicht mehr der neuste ist, stelle ich hier meine frage anstatt einen neuen Thread zu eröffnen.

Meine Frage..
Unszwar..
hatte ich ebenfalls vor..einen PHP Datensatz mittel Javascript auszuführen.


```
function _cmd_kiss(args) {
    window.location.href = 'db.php'
    displayMessage(null, '>> NICKNAME küsst NICKNAME zärtlich. ', null, false, 0);
}
```

So führe ich ja nun die db.php aus.
Leider öffnet sich dabei immer wieder eine neue Seite oder halt ein neues POPUP.
Ich hatte schond ie Idee per JS, das sich diese seite in 2 sekunden wieder schliesst, was dennoch lästig ist.
Gibt es eine möglichkeit, eine Datei (PHP) auszuführen, OHNE das Öffnen einer weiteren Seite?

Ich bitte um eure Hilfe!!


----------



## Sven Mintel (24. Februar 2009)

Moin,

die Frage ist, ob die db.php einfach nur aufgerufen werden soll, oder ob du in JS auch Informationen darüber benötigst über das, was in der db.php vor sich geht.


----------



## Shipstar (24. Februar 2009)

In der DB.php,
wird eigentlich nur eine Verbindung mit dem MySQL Server aufgebaut und ein Datensatz eingefügt.

Mehr passiert dort nicht.


----------



## Sven Mintel (24. Februar 2009)

Dann probiers mal so:
	
	
	



```
function _cmd_kiss(args) {
    var db=new Image();db.src="db.php?"+new Date().getTime();
    displayMessage(null, '>> NICKNAME küsst NICKNAME zärtlich. ', null, false, 0);
}
```


----------



## ddd (31. Dezember 2009)

Du kannst das script Zeitversetzt starten:
window.setTimeout("Allertfunction()", 1000000);

Der zweite wert sind die Millisekunden, bis geprüft wird


----------

