Ajattelin toteuttaa erääseen pieneen projektiin onlinerin, jonka toiminta perustuu siihen, että kun käyttäjä kirjautuu, lisätään käyttäjän nimimerkki myslitauluun josta voidaan php:lla listata taulusta käyttäjät jotka ovat online (1 kenttä, joka sisältää nickin, perusavain on se kenttä)
kun käyttäjä poistuu painamalla nappia, niin käyttäjän nimimerkki poistetaan myslitaulusta jonne se kirjautuessa lisättiin.
mainittakoon vielä tähän väliin: kun kirjaudutaan, luodaan keksi (cookie) käyttäjän nimimerkistä (eli jos käyttäjän nimimerkki on 'Sepelinaama' niin keksin nimi on 'Sepelinaama') jonka voimassaoloaika on 10min.
sitten itse ongelmaan... mitä, jos käyttäjä ei painakkaa "Logout" nappia, vaan sulkee selaimen? silloin myslitauluun jää käyttäjän nimimerkki, josta se listataan, joten käyttäjä olisi silloin online, vaikka on esim. lähtenyt illan viettoon. Joten, kyseisen käyttäjän keksin voimassaoloaika kun loppuu, pitäisi saada poistettua hänen nimimerkki myslitaulusta. Kuinka toteuttaa tämä näin, vai onko asiaan olemassa yksinkertaisempi/parempi/siistimpi ratkaisu?
Kiitos jo etukäteen!
Juuri tämän takia onlinerit yleensä toimivatkin periaatteella, että haetaan kannasta kaikki, jotka ovat ladanneet sivun esim. viimeisen 15 min. aikana. Ei oikeastaan tule mieleen muuta kuin laittaa ajastetusti tyhjentymään sieltä myslitaulusta ne nimet, jotka eivät ole esim. 15 minuuttiin sivuja ladanneet.
Kun lisäät uuden käyttäjän tauluun, niin tarkastat samalla aikaleimat taulusta kaikkien käyttäjien osalta sekä tuhoat ne jotka ovat aikarajan ulkopuolella (esim. käyttäjän viimeisen 5 minuutin sisällä = 300 sekunti => tuhoat kaikki sellaiset käyttäjät joiden viimeisin käyttöleima on suurempi kuin 300 sekuntia).
Itse käyttäisin triggereitä tai ajastettuja proseduureja tuollaisessa (ajastettu toiminto minuutin välein). Perus-SQL menee myös.
ajv kirjoitti:
Juuri tämän takia onlinerit yleensä toimivatkin periaatteella, että haetaan kannasta kaikki, jotka ovat ladanneet sivun esim. viimeisen 15 min. aikana. Ei oikeastaan tule mieleen muuta kuin laittaa ajastetusti tyhjentymään sieltä myslitaulusta ne nimet, jotka eivät ole esim. 15 minuuttiin sivuja ladanneet.
Kiitos, pitää kokeilla.
Sitten vielä kysyisin, kuinka parhaiten toteuttaa tuo esim. 15 min raja?
Laitat tietysti mysliin date();:lla ajan, jolloin viimeksi ladattiin, ja onlineri vertaa noita aikoja kävijöillä nykyiseen aikaan.
Oma ajatukseni.
date() ei taida soveltua tähän tarkoitukseen. Parempi on käyttää time() funktiota. Jokaisen sivulatauksen yhteydessä myslitauluun päivitetään nickin aikaleima, joka hankitaan time() funktiolla. Tämän jälkeen voidaan verrata silloista time() leimaa nykyiseen time() leimaan. Kyseessä on siis laskutoimitus nykyinen miinus vanha. jos tulos on yli 300 -> poistetaan taulusta kyseinen rivi.
Kun on MySQL:stä kyse, kannattaa aika tallentaa standardin mukaisena aikaleimana sinne kantaan, vaikka sitä käytettäisiinkin unix-aikaleimana. Tämä siksi, että se on standardi tapa, ja esim. kannan muuttaminen toiseen muotoon helpottuu huomattavasti, kun voidaan käyttää tietokantojen omia työkaluja. Sitten kuten MasaVista tuossa jo sanoi:
SELECT id, tunnus, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(last_load) AS idle FROM kayttajat HAVING idle < 300
Asiahan etenee..
CREATE TABLE kayttajat
(
tunnus VARCHAR(15) PRIMARY KEY NOT NULL,
aika DATE NOT NULL
);
select tunnus, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(aika) AS idle FROM kayttajat;
+----------+------------+
| tunnus | idle |
+----------+------------+
| sepeli | 1109236529 |
| sepi | 1109236529 |
| KuinKala | 1109236529 |
+----------+------------+
Idlen pienenminen kestää tosin "hieman" aikaa :D eli missä muodossa pitäisi syöttää tuo 'aika' kenttään menevä aika josta lasketaan idle? vai olenko kenties ihan hakoteillä?
select tunnus, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(aika) AS idle FROM kayttajat HAVING idle < 300;
-lause ei tietenkään tulosta yhtään riviä, koska kaikilla idle on sadan miljoonan luokkaa...
Eli mitä/missä muodossa pitää siis syöttää 'AIKA' kenttään?
INSERT INTO kayttajat (tunnus,aika) VALUES ('KuinKala','AIKA');
Idea on selvillä kuitenkin.. Sivun latauksen yhteydessä (kun esim KuinKala on sisällä) päivitetään 'aika' kenttää, josta sitten lasketaan onko idle < 300, jonka perusteella luokitellaan KuinKala online/offline tilaan, kun sivu jossa onliner on, ladataan.
vaihda DATE:n tilalle TIMESTAMP
CREATE TABLE kayttajat ( tunnus VARCHAR(15) PRIMARY KEY NOT NULL, aika TIMESTAMP(14) NOT NULL, ); Sitten nykyhetkeen viitataan NOW()-funktiolla: INSERT INTO kayttajat (tunnus,aika) VALUES ('KuinKala',NOW()); Tämän voi lisätä myös hakuun, vaikka käsittääkseni UNIX_TIMESTAMP():n pitäisi ilman argumentteja palauttaa tämä hetki. select tunnus, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(aika) AS idle FROM kayttajat;
Vilkaise myös päivitetty koodivinkkini.
Asia etenee episode 2.
No nyttenpä se "toimii":
CREATE TABLE kayttajat ( tunnus VARCHAR(15) PRIMARY KEY NOT NULL, aika TIMESTAMP(14) NOT NULL );
Syötellään pari käyttäjää:
INSERT INTO kayttajat (tunnus,aika) VALUES ('KuinKala',NOW()); INSERT INTO kayttajat (tunnus,aika) VALUES ('sepelinaama',NOW());
Kun sitten tarkistelee henkilöitä kenen idle on pienempi kuin -300 (eli 5min) lauseella:
SELECT tunnus, UNIX_TIMESTAMP(aika) - UNIX_TIMESTAMP(NOW()) AS idle FROM kayttajat HAVING idle > -300;
niin se kyllä palauttaa aivan oikein juuri syötetyt käyttäjät (tiedän, hassusti päin haeskelen idleä negatiivisella luvulla):
+-------------+-------------+ | tunnus | idle | +-------------+-------------+ | sepelinaama | -11 | | KuinKala | -3 | +-------------+-------------+
Mysli kyllä on kiva ja lopettaa käyttäjien kertomisen kun idle on pienempi kuin -300.. Mutta PHP ei siihen suostu kunnialla. PHP kyllälistaa onlinessa olevat käyttäjät, eli keiden idle on suurempi kuin -300, mutta poks.. Kun käyttäjän idle meneekin pienemmäksi kuin -300, se näyttää jostain ihmeen syystä käyttäjät edelleen onlinessä olijoiksi. Missä/kenessä vika?
Tässä vielä PHP -koodi:
<?php $palvelin = ""; $tunnus = ""; $salasana = ""; $tietokanta = ""; $yhteys = mysql_connect($palvelin,$tunnus,$salasana) or die("Yhdistäminen ei onnistunut"); mysql_select_db($tietokanta) or die ("Virhe"); $kysely = mysql_query( "SELECT tunnus, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(aika) AS idle FROM kayttajat HAVING idle > -300" ,$yhteys); if(mysql_num_rows($kysely) == 0){ echo "<i>Ei ketään online</i>"; } else { echo "<b>Online:</b><br><br>"; for($i = 0; $i < mysql_num_rows($kysely); $i++){ $online = mysql_result($kysely, $i, 0); echo "$online<br>"; } } mysql_close($yhteys); ?>
En tajua tuota...jotta päästäisiin idlessä negatiivisiin arvoihin, niin nykyajan pitäisi olla pienempi kuin tietokannassa olevan aikaleiman. Käytännössä mahdotonta(?).
Ehkä oikea lause olisi tämä:
SELECT tunnus, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(aika) AS idle FROM kayttajat HAVING idle < 300
Niin ja jos et tuolla idle-ajalla tee mitään, voi tietenkin hakea myös ihan
SELECT tunnus FROM kayttajat WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(aika) < 300
Aihe on jo aika vanha, joten et voi enää vastata siihen.