Tom: Kleines Ratespiel zu MySQL, Update und mysql_affected_rows()

Hello,

habe da ein kleines Ratespiel:

Gegeben sind

eine MySQL-Tabelle:

  
CREATE TABLE `login` (  
	`id` INT(11) NOT NULL AUTO_INCREMENT,  
	`lastclick` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
	`createdate` DATETIME NOT NULL,  
	`sessionstart` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',  
	`session` VARCHAR(50) NOT NULL,  
	`lastupdate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',  
	`nickname` VARCHAR(50) NOT NULL,  
	`lastname` VARCHAR(50) NOT NULL,  
	`password` VARCHAR(50) NOT NULL,  
	`firstname` VARCHAR(50) NOT NULL,  
	`email` VARCHAR(50) NOT NULL,  
	`status` INT(11) NOT NULL DEFAULT '0',  
	`level` INT(11) NOT NULL DEFAULT '0',  
	PRIMARY KEY (`id`),  
	UNIQUE INDEX `nickname` (`nickname`)  
)  
COLLATE='utf8_general_ci'  
ENGINE=MyISAM  
AUTO_INCREMENT=3;  

eine Login-Funktion (vereinfacht dargestellt; Passwort wird noch verschlüsselt, usw):

  
function login()  
{  
    $con = get_db_con(true);  
	  
	if (!$con) return false;  
	  
	$qry_login = "update `login`  
        set  
			session = '" . session_id() . "',  
            lastclick = now(),  
            sessionstart = now(),  
        where  
            nickname = '" . mysqli_real_escape_string($con, $_POST['data']['nickname'])."' and  
            password = '" . mysqli_real_escape_string($con, $_POST['data']['password'])."' and  
            status > 0";  
  
    if (mysqli_affected_rows($con) == 1)  
    {  
       $_SESSION['nickname'] = $_POST['data']['nickname'];  
	   $_SESSION['sess_start'] = get_time();  
	   $_SESSION['lastclick'] = get_time();  
  
       return 'Angemeldet als ' . htmlspecialchars($_SESSION['nickname']);  
    }  
    	  
    return false;  
}  

und eine Funktion zur Anmeldekontrolle:

  
function is_logged()  
{  
    $con = get_db_con(true);  
  
	if (!$con) return false;  
  
	$qry_is_logged = "  
        update `login`  
        set  
			lastclick = now(),  
        where  
            session = '" . session_id() . "' and  
            (now() - lastclick < " . SESS_MAXTIME . ")";  
  
    if (mysqli_affected_rows($con) === 1)  
    {  
		$_SESSION['lastclick'] = get_time();  
		return 'Is_logged(), Angemeldet als ' . htmlspecialchars($_SESSION['nickname']);  
    }  
 	  
    return false;			  
}  
  

Nun die Preisfrage:

Warum liefert die "is_logged()"-Funktion (allermeistens) kein Ergebnis, wenn man sie im selben Script aufruft, obwohl der User ja nun "angemeldet" ist?

Ich habe daran leider ganz schön lange geknabbert, aber die Lösung ist ganz verblüffend einfach. Mal sehen, ob jemand von Euch bis morgen darauf kommt ;-)

Als Preis dürfen die ersten Drei an der nächsten "SELF-Week" in der Odertaler Sägemühle kostenlos teilnehmen und auf meine Kosten Weizenbier saufen ;-)

Liebe Grüße aus dem schönen Oberharz

Tom vom Berg

--
 ☻_
/▌
/ \ Nur selber lernen macht schlau
http://restaurant-zur-kleinen-kapelle.de
  1. Hello,

    habe da ein kleines Ratespiel:

    Warum liefert die "is_logged()"-Funktion (allermeistens) kein Ergebnis, wenn man sie im selben Script aufruft, obwohl der User ja nun "angemeldet" ist?

    weil Du Dich nicht entscheiden kannst, ob Du sie in Großbuchstaben oder in Versalien schreiben sollst?;)

    Als Preis dürfen die ersten Drei an der nächsten "SELF-Week" in der Odertaler Sägemühle kostenlos teilnehmen und auf meine Kosten Weizenbier saufen ;-)

    Nein danke, ich betrink' mich fast ausschliesslich mit piemontesischem Rotwein aus den Lagen Serralunga d’Alba und La Morra. (Daran kannst Du auch erkennen, daß mein Geschmack viel entwickelter ist als meine PHP-Kenntnisse...)

  2. Hi,

    $qry_login = "update login
            set
    session = '" . session_id() . "',
                lastclick = now(),
                sessionstart = now(),
            where
                nickname = '" . mysqli_real_escape_string($con, $_POST['data']['nickname'])."' and
                password = '" . mysqli_real_escape_string($con, $_POST['data']['password'])."' and
                status > 0";

    if (mysqli_affected_rows($con) == 1)

      
    Zwischen Ablegen des SQL-Statements in einem String und Aufruf der affected\_rows sollte das SQL-Statement noch ausgeführt werden.  
      
    Dito bei der zweiten Funktion.  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
    1. Hallo,

      sollte das SQL-Statement noch ausgeführt werden.

      seh ich auch so.
      Klassischer Fall von doofem Computer, der nur das macht, was man ihm sagt...

      Gruß
      Kalk

    2. Hello,

      Zwischen Ablegen des SQL-Statements in einem String und Aufruf der affected_rows sollte das SQL-Statement noch ausgeführt werden.

      Sorry, die Zeolen sind - warum auch immer - irgendwie auf dem Weg vom Poster zum Forum verloren gegangen. Selbstverständlich werden die Statements auch ausgeführt.

      Tut mir wirklich leid. Das war nicht das Problem.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://restaurant-zur-kleinen-kapelle.de
  3. Moin,

    [Spaghetti-Code]

    Als Preis dürfen die ersten Drei an der nächsten "SELF-Week" in der Odertaler Sägemühle kostenlos teilnehmen und auf meine Kosten Weizenbier saufen ;-)

    Grappa wäre angebrachter.

    SCNR ;)

  4. und eine Funktion zur Anmeldekontrolle:

    function is_logged()
    {
        $con = get_db_con(true);

    if (!$con) return false;

    $qry_is_logged = "
            update login
            set
    lastclick = now(),
            where
                session = '" . session_id() . "' and
                (now() - lastclick < " . SESS_MAXTIME . ")";

    if (mysqli_affected_rows($con) === 1)
        {
    $_SESSION['lastclick'] = get_time();
    return 'Is_logged(), Angemeldet als ' . htmlspecialchars($_SESSION['nickname']);
        }

    return false;
    }

    
    >   
    >   
    > Warum liefert die "is\_logged()"-Funktion (allermeistens) kein Ergebnis, wenn man sie im selben Script aufruft, obwohl der User ja nun "angemeldet" ist?  
    >   
    
    man sollte die Query, ide so schön in $qry\_is\_logged definiert wird, halt auch noch irgendwann ausführen....
    
    1. Hello,

      man sollte die Query, ide so schön in $qry_is_logged definiert wird, halt auch noch irgendwann ausführen....

      Sorry, natürlich wird sie ausgeführt. Das ist vermutlich beim Einkürzen des Overheads mit verloren gegangen.

        
      function is_logged()  
      {  
          $con = get_db_con(true);  
        
      	if (!$con) return false;  
        
      	$qry_is_logged = "  
              update `login`  
              set  
      	    lastclick = now(),  
      	    clickcount = clickcount +1  
              where  
                  session = '" . session_id() . "' and  
                  (now() - lastclick < " . SESS_MAXTIME . ")";  
        
      	$res = mysqli_query($con, $qry_is_logged);		  
        
          if (mysqli_affected_rows($con) === 1)  
          {  
      		$_SESSION['lastclick'] = get_time();  
      		return htmlspecialchars($_SESSION['nickname']);  
          }  
      	elseif (mysqli_affected_rows($con) === -1)  
      	{  
      		return 'Is_logged(): Fehler im Update-Statement';  
      	}  
       	  
          return false;			  
      }  
      
      

      Der vorerst letzte Stand sieht inzwischen so aus w.o. und funktioniert einwandfrei.

      Erklärung zum eigentlichen Rätsel unter https://forum.selfhtml.org/?t=216221&m=1482242

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://restaurant-zur-kleinen-kapelle.de
  5. Tach!

    Warum liefert die "is_logged()"-Funktion (allermeistens) kein Ergebnis, wenn man sie im selben Script aufruft, obwohl der User ja nun "angemeldet" ist?

    Wenn das aller relevante Code ist und du nicht zu viel gekürzt hast, ...

    Ich habe daran leider ganz schön lange geknabbert, aber die Lösung ist ganz verblüffend einfach.

    ... dann sieht man auf den ersten Blick, dass etwas nicht stimmt, wenn man eine IDE (wie PhpStorm) verwendet. Die zeigt nämlich an, dass die Variablen $qry_login und $qry_is_logged geschrieben aber nicht genutzt werden. Außerdem, dass für zwei Funktionen und eine Konstante die Definition fehlt, aber die wirst du ja bei dir drin haben.

    dedlfix.

    1. hi,

      ... dann sieht man auf den ersten Blick, dass etwas nicht stimmt, wenn man eine IDE (wie PhpStorm) verwendet.

      Sorry, vor der IDE kommt eine klitzekleine Überlegung, die mit dem DB-Design einer Login-Tabelle beginnen könnte. So frage ich mich, wozu das Passwort da rein soll und noch einige andere Felder, deren Daten mit Sicherheit schon woanders rumliegen.

      Hotti

      1. Hello,

        Sorry, vor der IDEE kommt eine klitzekleine Überlegung, die mit dem DB-Design einer Login-Tabelle beginnen könnte. So frage ich mich, wozu das Passwort da rein soll und noch einige andere Felder, deren Daten mit Sicherheit schon woanders rumliegen.

        Die Login-Tabelle ist im Sinne eines schlanken Entwurfes schon ganz gut so.

        Selbstverständlich kann man, insbesondere, wenn eine Historie über Datenänderungen gewünscht wird, auch mehrere Tabellen daraus machen. Das ist aber nicht unbedingt notwendig für ein einfaches System.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://restaurant-zur-kleinen-kapelle.de
        1. hi,

          Selbstverständlich kann man, insbesondere, wenn eine Historie über Datenänderungen gewünscht wird, auch mehrere Tabellen daraus machen. Das ist aber nicht unbedingt notwendig für ein einfaches System.

          Ich ahne Schreckliches: Du speicherst die Login's in der Benutzertabelle ;)

          Nagut, nachdem ich mir mal das DB-Design von xt-Commerz antun musste, bringt mich nichts mehr aus der Fassung.

          Hotti

    2. Hello,

      Warum liefert die "is_logged()"-Funktion (allermeistens) kein Ergebnis, wenn man sie im selben Script aufruft, obwohl der User ja nun "angemeldet" ist?

      Wenn das aller relevante Code ist und du nicht zu viel gekürzt hast, ...

      Ich habe daran leider ganz schön lange geknabbert, aber die Lösung ist ganz verblüffend einfach.

      ... dann sieht man auf den ersten Blick, dass etwas nicht stimmt, wenn man eine IDE (wie PhpStorm) verwendet. Die zeigt nämlich an, dass die Variablen $qry_login und $qry_is_logged geschrieben aber nicht genutzt werden. Außerdem, dass für zwei Funktionen und eine Konstante die Definition fehlt, aber die wirst du ja bei dir drin haben.

      Du bist schon ziemlich nah dran.

      Die Konstanten sind selbstverständlich vorhanden und die Funktion für die Datenbankverbindung auch. Da liegt auch nicht der Fehler. Es ist ein logischer Fehler.

      Wenn der User sich mittels "login()" gerade angemeldet hat und dann im selben Script nur kurze Zeit später "is_logged()" aufgerufen wird, dann ändert das Update-Statement in der is_logged()-Funktion nichts mehr im Datensatz, da die Daten gleich bleiben, es sei denn, dass gerade ein Sekundensprung stattgefunden hat...

      Das führt dazu, das keine Zeile der Datenbank verändert wurde, also mysqli_affected-rows() eine 0 als Ergebnis liefert.

      Um diesem Missstand entgegen zu wirken und die Programmierung nicht zu kompliziert machen zu müssen, habe ich die Spalte updatecount eingeführt, die bei jedem Update um eins hochgezählt wird. Das garantiert die Änderung und mysqli_affected_rows() ist wieder zufrieden.

      updatecount wird für den konkurrierenden Betrieb ohnehin benötigt, da man bei verbindungslosem (zustansdlosem) Betrieb so am einfachsten feststellen kann, ob zwischen dem Lesen eines Datensatzes und dem Zurückschreiben der geänderten Daten eine Änderung stattgefunden hat. Die Splate ist also keinesfalls überflüssig.

      Ich werde, wenn daran interesse besteht, das "Login-Modul" gerne hier veröffentlichen, wenn es fertig ist. Ein paar Details müssen noch eingebaut werden.

      Aber: kleine Ursache, lange Suche, bis die kleine Birne endlich geglüht hat :-)

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://restaurant-zur-kleinen-kapelle.de
  6. Hallo,

    nur mal ne kleine Frage:

    return 'Is_logged(), Angemeldet als ' . htmlspecialchars($_SESSION['nickname']);

    Das ist jetzt nur ein Rückgabestring? Is_logged() soll nicht wirklich ein Funktion aufrufen, richtig?

    Dann gibt's da noch mysqli_affected_rows($con) === 1, wo ich schon mal Probleme mit hatte und aus den 3= dann 2= gemacht habe: mysqli_affected_rows($con) == 1

    Wie führst Du deine SQL-Anweisungen aus? Ich sehe zwar einen Query "$qry_is_logged=..." aber keine Ausführung.

    Gruss
    Mike

    1. Hello,

      Dann gibt's da noch mysqli_affected_rows($con) === 1, wo ich schon mal Probleme mit hatte und aus den 3= dann 2= gemacht habe: mysqli_affected_rows($con) == 1

      Genau das mysqli_affectoed_rows() bereitet den Kummer bei MySQL's UPDATE.

      siehe weiteren Thread.

      Wie führst Du deine SQL-Anweisungen aus? Ich sehe zwar einen Query "$qry_is_logged=..." aber keine Ausführung.

      Die Zeile ~~~php

      $res = mysqli_query($con, $qry_is_logged);

        
      war beim Einkürzen verloren gegangen.  
        
      siehe <https://forum.selfhtml.org/?t=216221&m=1482245>  
        
        
        
        
        
      Liebe Grüße aus dem schönen Oberharz  
        
        
      Tom vom Berg  
      ![](http://selfhtml.bitworks.de/Virencheck.gif)  
        
      
      -- 
       ☻\_  
      /▌  
      / \ Nur selber lernen macht schlau  
      <http://restaurant-zur-kleinen-kapelle.de>