Autor Zpráva
majja01
Profil
Dobrý den,
dělám takový jednoduchý e-shop který nepotřebuje registraci (budu ukládat do databáze ip)
zkončil jsem u funkce která kontroluje zda je ip v databázi a podle toho se rozhodne jestli přidat do seznamu k objednání nebo registraci a přidání.
Jenže nevím v jaké formě to má být .
mám script který podle tru nebo false vykonává přidání nebo registraci+přidání
$uzjeuzivatel = true;
  if ($uzjeuzivatel) {
   // tady je kod pro přidání zboží do databáze  
  }
  else {    
 // tady  pro registraci a přidání zboží
  }


?>
ale před tím kodem musí ještě být nějáká funkce která zjistí zda byl uživatel již zaregistrován.
Jednoduše řečeno potřebuju funkci na prohledání databáze která by dávala bud true nebo flase do prommené $uzjeuzivatel
Doufám že jste to pochopily
diky majja01
juriad
Profil
majja01:
Věz, že IP adresa není unikátní (často je sdílená v paneláku či vesnici). Co se stane, když na eshop přijdou dva lidé se stejnou IP adresou a budou chtít nakoupit? Budou si nejspíš přepisovat údaje a košík pod rukama.
Měl bys vymyslet lepší způsob (cookies).

Není nutné se podepisovat a není nutné dělat pravopisné chyby (pochopily, chybějící čárky)
Micruss
Profil
jestli to máš podle IP tedy tak takhle

$ip = $_SERVER['REMOTE_ADDR'];
$najdi_uziv = mysql_query("SELECT * FROM tvoje_tabulka WHERE ip = '$ip'");
if(mysql_num_rows($najdi_uziv)!=0) $uzjeuzivatel=true; else $uzjeuzivatel=false; 

ale kontrolovat uživatele podle ip je blbost jak už psal juriad
Jan Tvrdík
Profil
Micruss:
Doplním, že uvedené řešení není atomické, protože mezi ověřením, zda je uživatel již „registrovaný“ a operací, která na tom závisí, může proběhnout další registrace.
Amunak
Profil
Jan Tvrdík:
To mě přivádí na myšlenku, jak vlastně udělat atomickou registraci? Jak to řeší servery, kde k tomuto problému skutečně může dojít? Může se stát, že se dva lidé ve stejnou dobu pokusí zaregistrovat (účet u Googlu). A vyberou si stejné jméno. Může se stát, že dojde ke konfliktu až při běhu skriptu. Pokud je na sloupci v databázi primární klíč (nebo je unikátní), vyhodí chybu sama databáze, a s tím už se nějak dá pracovat. Jde to udělat nějak lépe?
Taps
Profil
Amunak:
pro inspiraci: http://doc.nette.org/cs/atomicity
Jan Tvrdík
Profil
Amunak:
Můžeš použít například zámky nad určitými tabulkami databáze. Případně to můžeš zkusit, nechat selhat na unikátním indexu a zpracovat korektně tu vzniklou chybu.
Amunak
Profil
Jan Tvrdík:
Zámek mě napadl, ale ten taky zabrání v registraci třeba další stovce uživatelů, která by s tím jinak neměla problém.

Taps:
Vím, že to Nette umí, ale snad nikde jsem se nedočetl, co se tedy vlastně stane, když dojde ke konfliktu. Funkce prostě vyhodí výjimku?
majja01
Profil
juriad:
promiňte za pravopis bylo to psáno rychle
Micruss:
díky ale použiji tedy cookies jak říkal juriad
Amunak, Jan Tvrdík:
atomickou?


Použiju tedy cookies četl jsem si o tom na linuxsoft.cz
co jsem tam pochopil bylo jak přidávat.
<?
SetCookie ("nazev_cookie", "hodnota", time()+10*60);
echo "Tato stránka Vám poslala cookie!";
?> 
ale hlavně bych chtěl vědět co mám dát do hodnoty cookies? nebo je to jedno?
mohl bych udělat například toto?
]<?
SetCookie ("uzivatel", "$_GET["jmeno"]", time()+10*60);
?>
a jak mám tedy zjistit zda již uživatel v cookies byl a jestli má program pokračovat v přidávání zboží?
edit:
a můž ještě to zboží psát taky do cookies?
Abych nemusel pužít databázi? Pak by se jenom vymazalo po dokončení objednávky ne?
juriad
Profil
majja01:
Timi cookies jsem myslel SESSION (cookies jsou jen fyzický prostředek jak toho dosáhnout; přečti si o tom něco. V kostce: na začátek každého souboru přidej session_start. Ta funkce se postará o to, že každý uživatel (určený podle cookies, do které ukládá náhodně vygenerované ID platné omezenou dobu) dostane svoje pole $_SESSION, které můžeš přímo číst a měnit.

Session může obsahovat veškerá data (třeba idéčka a počty položek v košíku), což v případě, že uživatel není registrován je asi nejvhodnější varianta.
Nebo, pokud je uživatel registrován, bude session obsahovat jen skutečné ID uživatele a veškerá data budou v databázi.


Demonstrace přidávání položky do košíku.
Zkus si to v několika prohlížečích zároveň (každý košík bude samostatně).
Netestoval jsem to.

kosik.php:
<?php
session_start();
if(!isset($_SESSION['kosik'])) {
  $_SESSION['kosik'] = array();
}
print_r($_SESSION['kosik']);
?>
<form action="pridej_polozku.php" method="post">
<input type="text" name="polozka">
<input type="submit" value="Přidej položku">
</form>

pridej_polozku.php:
<?php
session_start();
if(!empty($_POST['polozka'])) {
  $_SESSION['kosik'][] = $_POST['polozka'];
}
header("Location: kosik.php");
exit;
Jan Tvrdík
Profil
Amunak:
Zámek mě napadl, ale ten taky zabrání v registraci třeba další stovce uživatelů, která by s tím jinak neměla problém.
To je velmi hypotetická situace, reálně se ti nestává, že by se během 1 sekundy registrovalo 100 lidí zároveň. Ale jinak ano, zámek ti způsobí, že operace neproběhne paralelně, ale sériově.

ale snad nikde jsem se nedočetl, co se tedy vlastně stane, když dojde ke konfliktu. Funkce prostě vyhodí výjimku?
Když se pokusíš získat exkluzivní zámek nad objektem, který je už uzamčen, tak se skript zastaví a čeká, až bude zámek uvolněn a bude si ho tak moci získat pro sebe. Většina implementací zároveň přidává nějaký timeout, tzn. že když se čeká příliš dlouho, tak se operace prohlásí za neúspěšnou (např. flock vrátí FALSE).

majja01:
atomickou?
Viz např. php.vrana.cz/atomicita-operaci.php.
Amunak
Profil
Jan Tvrdík:
Děkuji, tohle je dost poučné. Měl jsem v hlavě, že když nejde získat zámek, skript se přeruší (vyhodí se výjimka nebo tak něco).
majja01
Profil
juriad:
aha takže vůbec nemusím ukládat nějaké ůdaje o uživatelích stačí prostě uložit idéčka zboží a ty pak vyčtu z databáze.
Jestli jsem to dobře pochopil, tak u každého zboží budu mít formulář který přidá zboží do session?
A ty pak vypíšu pomocí print_r ?
Amunak, Jan Tvrdík:
Nechápu o čem se tu bavíte ;-)
juriad
Profil
majja01:
Ano, každý produkt u sebe bude mít formulář (pokud se bude přidávat produkt přes $_POST), nebo klidně i odkaz
<a href="pridej_polozku.php?polozka=123">Přidat do košíku</a> (musíš změnit přístup na z $_POST na $_GET).
Produkty v košíku si vypíšeš jakýmkoli způsobem, který znáš, třeba do tabulky. $_SESSION['kosik'] obsahuje úplně obyčejné pole. Já jsem použil print_r jen jako demonstraci principu.

Teoreticky nemusíš uživatele a košíky ukládat do databáze vůbec, ale session se automaticky zruší po několika minutách (výchozí nastavení je tuším 1440 sekund -- lze nastavit, hledej). V databázi ale naopak data zůstávají neomezeně dlouho, pokud jednou uživatel uloží něco do košíku, tak to v něm zůstane i když obchod už nikdy nenavštíví. Proto se oba přístupy kombinují a spouští se pravidelně čištění databáze od takových zastaralých dat (košíků).

Amunak a Jan Tvrdík se baví v podstatě o tom, že když máš posloupnost příkazů:
$dostupne = zjisti_zda_je_zbozi_dostupne();
if($dostupne) {
  odecti_jednicku_od_dostupneho_zbozi();
  proved_objednavku();
}
tak se může stát, že skončíš s více objednávkami než máš dostupného zboží z důvodu, že několik uživatelů zároveň klikne objednat. Všem se zkontroluje, zda je dostupné, což bude, a pak se za všechny odečte jednička a vytvoří objednávka.
Je to šíleně nepravděpodobné a u málo navštěvovaného obchodu se to "nikdy" nestane.
majja01
Profil
juriad:
Udělal jsem toto:
do detail.php (to je detail zboží) jsem dal toto:

<form method="post" style="width:300px; float:left;" action="additem.php">
        <input style="width:50px;" placeholder="ks"  id="spinner" name="ks" />
        <input type="hidden" value="<? echo $vyrobek["id"];?>" name="id">
        <input class="button" type="submit" value="přidat do košíku">
    </form> 
do additem.php toto:

<?
session_start();
if(!empty($_POST['id'])) {
  $_SESSION['kosik'][] = $_POST['id'];
  
}
header("Location: objednavka.php");
exit;

?>
tady bych s echtěl zeptat jestli jde v session kosik dát dvě hodnoty id a ks?
a na seriálu linuxsoft.cz je ještě příkaz 
session_register("promenna");
 ten se tam dávat nemusí?
 
a v objednavka.php mám
<?php
session_start();
if(!isset($_SESSION['kosik'])) {
  $_SESSION['kosik'] = array();
}
print_r($_SESSION['kosik']);
?>
vypíše mi to toto Array ( [0] => 1 ) vím že v té hranaté závorce je pořadí a ta 1 je id
takže to funguje

asi bych to mohl zapsal do databáze ale nevím jak udělat unikátní id uživatele?
nejlepší by bylo abych nastavil čas zrušení na nulu tím by se to zrušilo jen když zavřu prohlížeč nebo pokud bych dal session_destroy();
ale nevím jestli to jde nastavit na hostingu endora :-(
juriad
Profil
majja01:
Linuxsoft je sice kvalitní zdroj, ale je poněkud starší, session-register už dávno není třeba.
Dokonce dokumentace povídá: This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.

S tím košíkem si dělej co chceš. Klidně může ten additem.php vypadat takto:
<?php
session_start();
if(!empty($_POST['id']) && isset($_POST['pocet']) && is_numeric($_POST['pocet'])) {
  $id = $_POST['id'];
  $ pocet = (int) $_POST['pocet'];
  $_SESSION['kosik'][$id] = $pocet; # klíčem v poli je id produktu; hodnotou je počet
}
header("Location: objednavka.php");
exit;
A do formuláře pro přidání do košíku přidáš ještě jeden input s name="pocet".
majja01
Profil
juriad:
moc díky
těd už to funguje parádně :D
jenom bych potřeboval aby se z toho array Array ( [0] => 1 [1] => 5 [5] => 4 [11] => 3 )
udělali 2 promenné abych je mohl vyhledat v databázi.
Toť poslední otázka :D
juriad
Profil
$ids = array_keys($_SESSION['kosik']);
if(count($ids)>0) {
  $sql = "SELECT * FROM produkt WHERE id IN (" . implode(', ', $ids) . ")";
  ... položení dotazu do databáze ...
  while ($row = ...) {
    $id = $row['id'];
    $pocet = $_SESSION['kosik'][$id];
    echo ...
  }
}
majja01
Profil
juriad:
aha tak to není poslední otázka udělal jsem toto:
<?  mysql_connect("127.0.0.1", "root", "");
mysql_select_db("mak"); 
mysql_query("SET CHARACTER SET utf8");
mysql_set_charset('utf8');
session_start();
$ids = array_keys($_SESSION['kosik']);
if(count($ids)>0) {
  $sql = mysql_query("SELECT * FROM zbozi WHERE id = '$ids'");
  while ($vyrobek=MySQL_Fetch_Array($sql))
   {
    $id = $vyrobek['id'];
    $ks = $_SESSION['kosik'][$id];
    echo $vyrobek["name"];
  }
}
?>
ale nic to nevypíše ani žádnou chybu. zkoušel jsem mysql_error(); taky nic
juriad
Profil
majja01:
Ta má konstrukce s IN a implode má nějaký význam :) Uprav svůj 8. řádek.
Pokud $ids bude obsahovat víc produktů napřiklad array(1,2,3,5), tak se sestaví sql dotaz s podmínkou "... id IN (1, 2, 3, 5)"
majja01
Profil
juriad:
jo ale to skončí chybou Warning: mysql_fetch_array() expects parameter 1 to be resource, string given in D:\phpvirtual\mak\objednavka.php on line 29
juriad
Profil
Každý holt nazýváme $sql něco jiného: já dotaz, ty výsledek dotazu.
  $sql = "SELECT * FROM zbozi WHERE id IN (" . implode(', ', $ids) . ")";
  $vysledek = mysql_query($sql);
  while ($vyrobek=MySQL_Fetch_Array($vysledek))
majja01
Profil
juriad:
aha :D
fakt moc díky už to funguje

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: