Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
04.04.2008, 01:24
LeJean



Nabend zusammen.

Meine Situation: Ich programmiere gerade - eigentlich rein spaßeshalber - mal wieder ein bisschen PHP. Momentan eine recht einfache Klasse, die mit "User" bezeichnet ist.
Diese Klasse hat neben den diversen Attributen und dem Konstruktor auch Funktionen zur Fehlerbehandlung und eine Funktion, um einen neuen Benutzer zu registrieren.
Sprich: Wenn ich zur Laufzeit eine Instanz der Klasse erzeuge, so möchte ich bei entsprechendem Aufruf des Konstruktors einen Gastuser haben und bei Gelegenheit eine Registrierung oder ein Login durchführen. Das läuft auch genau so, wie ich das möchte. Nur bei der Methode zum Registrieren ergibt sich folgendes Problem:

Ich schreibe im PseudoCode:
PHP-Quellcode:<?php
function registerUser(..., $shortLogin, ...) {
  
// Benutzereingaben prüfen
  // bei Fehlern: Fehlerbehandlung und Abbruch

  
mysql_query('SELECT COUNT(*) FROM user WHERE shortLogin LIKE "'.$shortLogin.'";');
  
// oder alternativ SELECT * FROM... und dann ein mysql_num_rows

  // Anzahl der gefundenen Datensätze prüfen
  // bei > 0 Fehlerbehandlung und Abbruch (!)

  // diverse andere Überprüfungen
  
  
echo 'TESTAUSGABE<br>';
  
mysql_query('INSERT INTO user (.....) VALUES (.....);');

  
// diverse Attribute mit Werten belegen
  // Fkt beenden
}
?>
Das ist ja so weit auch nichts ungewöhnliches. Der "tolle" Effekt ist jetzt aber der folgende:

Sind alle Benutzereingaben korrekt und passieren die Prüfung, komm ich zum Überprüfen, ob ein Benutzer mit dem entsprechenden Namen schon existiert (Zeile 6). Allerdings liefert diese SQL-Abfrage immer 1. Auch wenn der Benutzer vorher definitiv nicht existierte. Da bei einer Datensatzanzahl > 0 (s.o.) die Routine an dieser Stelle abgebrochen wird, folgt auch die Ausgabe "TESTAUSGABE" (Zeile 14) korrekterweise nicht mehr.

Wenn ich vor die Testausgabe ein "return;" einfüge, dann tritt dieser Effekt nicht auf, sondern das Programm terminiert so wie es soll - die erste SQL-Abfrage gibt auch dann den korrekten Wert zurück.

Das bedeutet, dass das 2. Query offensichtlich vor dem ersten stattgefunden hat. Warum ist das der Fall?
Meine böse Vermutung ist, dass PHP implizit beim Parsen mit prepared Statements o.ä. arbeitet und die dann in meinem Fall in der falschen Reihenfolge ausführt (INSERTs vor SELECTs?). Eine Transaktion nutze ich nicht, und möchte ich auch nicht nutzen - mal ganz abgesehen davon, dass das System gerade auf MyISAM und nicht innoDB läuft.
Trotz allem muss aber doch eine Datenkonsistenz garantiert werden können. Kann ja nicht sein, dass ich für alles Transaktionen nutzen muss um diesen Phantomeffekt zu umgehen.

MfG, Jean

--


Dieser Beitrag wurde am 04.04.2008 um 01:27 von LeJean bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
001
04.04.2008, 09:08
Alcapone



PHP-Quellcode:<?php
mysql_query
('SELECT COUNT(*) FROM user WHERE shortLogin LIKE "'.$shortLogin.'";');
?>
Nimm das vorletzte ";" weg, das gehört da nicht rein. Und ich würde an deiner Stelle kein LIKE verwenden sondern ein =
Quellcode:WHERE shortLogin = "'.$shortLogin.'" So siehts richtig aus:

PHP-Quellcode:<?php
mysql_query
("SELECT COUNT(*) FROM user WHERE shortLogin = '".$shortLogin."'");
?>
SQL erwartet den String SELECT COUNT(*) FROM user WHERE shortLogin = 'foobar'

wichtig ist, das der gesuchte string in ' gesetzt wird.

PS: Sag mir, obs funktioniert hat.

--

"Everything, that can go wrong, will go wrong" Murphy's Law


Dieser Beitrag wurde am 04.04.2008 um 11:48 von Alcapone bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
002
04.04.2008, 10:55
LeJean



Äh sorry... das hat damit so ca. garnix zu tun. Und ich bin btw auch kein mySQL-Anfänger - du hast das Problem nicht begriffen.
Der String ist in Anführungszeichen, das müssen nicht unbedingt Hochkommata sein. (Mal ganz abgesehen davon, dass ich in PHP alle Strings in Singlequotes schreibe.. und deshalb im SQL-Statement die normalen Anführungszeichen genutzt habe)
In deinem Query sind an einer Stelle übrigens zwei Anführungszeichen vertauscht.

Das Problem ist ein ganz anderes. Die SQL-Statements sind richtig. Ich hab nur eben rausgefunden, dass man eine Tabelle besser nie "user" nennt, da das bekanntlich ein reserviertes Wort in mySQL ist. Hätte ich natürlich eigentlich auch gleich merken müssen. Also bleiben mir jetzt die Möglichkeiten: Tabelle umbenennen oder in allen Statements in Backticks schreiben.

Edit: Okay... das wär ja eigentlich ne Erklärung gewesen - aber ich hab die Tabelle umbenannt, die Backticks eingefügt, in allen Statements den DB-Namen vor die Tabelle geschrieben... aber das hat alles nix geholfen - das Problem ist und bleibt dasselbe.
Selbst wenn ich ganz am Anfang der Methode ein "SELECT * FROM ums_users" ausführe und ausgeben lasse, dann steht da der neue Eintrag schon mit bei, obwohl das an dieser Stelle garnicht sein kann.

--


Dieser Beitrag wurde am 04.04.2008 um 11:08 von LeJean bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
003
04.04.2008, 11:20
LeJean



(Neuer Post wg. Problemstatus)

Habs jetzt. Mir ist grad aufgefallen, dass ich das Script garnicht im Browser ausführen muss, um es zu testen. Immer wenn ich wieder Werte geändert hab und die File zum testen gespeichert hab, stand der neue Wert in der Datenbank.

Das lag daran, dass mein wundervolles Eclipse mit PHPEclipse das Script immer schon selbstständig ausgeführt hat. Kommt gut, wenn ich normalerweise den PHP Browser in Eclipse nicht nutze und der minimiert ist.

Tja, hat sich damit wohl erledigt. Trotzdem danke ;)

--

zum Seitenanfang zum Seitenende Profil || Suche
004
04.04.2008, 11:32
hausi



Wenn wir gerade bei Backticks und Doublequotes sind: Nach SQL 2003 Standard müssen strings immer in single quotes geschrieben werden. Double quotes sind für Feld- und Tabellen-Namen in Unicode vorbehalten. Wenn du also irgendwann mal eine Standardkonforme DB (sprich: PostgreSQL) verwenden willst, dann müsstest du alle SQL Statements umschreiben. Der Backtick ist übrigens nichtmal ein reserviertes Zeichen (siehe SQL 2003 BNF Grammar).

Und zum Problem: Mach dir am besten einen query-wrapper, der im Fehlerfall (mysql_query gibt false zurück) mysql_error() ausgibt. Zumindest während der Entwicklung.

BTW: MySQL 5.0 gibt bei deinem Query keinen Fehler zurück, sondern liefert das erwartete Resultat.

--

zum Seitenanfang zum Seitenende Profil || Suche
005
04.04.2008, 11:46
LeJean



Dass mySQL nicht Standardkonform ist, ist ja bekannt.. ist momentan aber ohnehin nix ernstes was ich hier schreibe.
Nen Query-Wrapper hab ich im Grunde hier. Der "code" oben ist ja nur Pseudocode, weil ich keine 200 Zeilen pasten wollte. Geht ja ums Prinzip..

--


Dieser Beitrag wurde am 04.04.2008 um 11:46 von LeJean bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche