vícenásobné uložení do databáze

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Bertram
Člen | 75
+
0
-

Zdravíčko,neznáte někdo způsob zamezení vícenásobného vložení údajů do databáze?
Pokud totiž omylem a nebo úmyslně poklepu odesílací tlačítko několikrát po sobě,
tak se záznam zduplikuje,nebo se vyhodí vyjímka jeli v databázi na nějakém slopci unikátní klíč.

O nutnosti přesměrování vím a doufám,že jsem to napsal správně.
Posuďte mám to takto:

// Mám pouze jedno odesílací tlačítko
// V dokumentaci v tomto případě doporučená volba
$form->addSubmit('odesli','ulož');
$form->onSubmit[] = callback($this,'formSubmitted');

// Zde jeho zpracování
function formSubmitted ($form)
{
  $trafo = ($form->values);
  $this->model->vlozit($trafo);
  $this->flashMessage('Transformátor uložen.');
  $this->redirect('Transformatory:vypis');
}

Je mi také jasné,že budu muset doplnit validaci tak či tak,jen bych potřeboval trochu nakopnout jak to s tou vlastní validací vlastně je.
Dohledal jsem si tyto varianty,jen v nich trochu tápu.

//varianta 1
//Tady to chápu tak,že si musím vytvořit vlastní třidu s metodou myValidátor
//Pokud mi vrátí true tak to neprojde
//Otázka zní: Kde má být tato třída definována?
$form = new Form();
$form->addText('name', 'Text:', 10)
    ->addRule('MyClass::myValidator', 'Value %d is not allowed!', 11)


//varianta 2
//U této variandy jsem se dočetl,že se jedná o anonymní funkci
//První $control je parametr předávaný funkci
//A ten druhý je už jenom operace s jeho hodnotou uvnitř funkce
// A nebo jsu vedle jak ta jedle?
$form->addText('oddNumber', 'Liché číslo')
     ->addRule($form::INTEGER)
     ->addRule(function (Nette\Forms\IFormControl $control) {
          return (bool) ($control->getValue() % 2);
     }, 'Musíte uvést liché číslo');


//varianta 3
//nemohl by mi někdo po lopatě vysvětlit co to ten callback je?
//opravte mě:
// 'MyApplication\Models\Users' - je cesta ke třídě User v Modelu
// 'isUsernameAvailable'        - je metoda v této třídě dotazující se databáze
$form->addText('username', 'Uživatelské jméno')
     ->addRule($form::FILLED, 'Vyplňte své uživatelské jméno')
     ->addRule(callback('MyApplication\Models\Users', 'isUsernameAvailable'),
                        'Toto uživatelské jméno je již registrováno');
dakota
Člen | 148
+
0
-

https://forum.nette.org/…iewtopic.php?…

Problém robi hlavne prehliadač Opera. Nešlo by ochranu proti viacnásobnému odoslaniu formulára implementovať priamo do Nette?

Bertram
Člen | 75
+
0
-

Děkuji za radu,jen tomu kódu nerozumím,tak mi to moc nepomohlo.
Nemohl by mi někdo objasnit ten poddotaz co se těch validátorů týče?

westrem
Člen | 398
+
0
-

Co sa tyka viacnasobneho odoslania, tak kolega uz odkazal na spravny thread, ja by som len pripomenul, ze dalsia moznost je zobrazit overlay effect s loading image, ktory zamedzi dalsim kliknutiam.

V pripade, ze sa naozaj nieco seklo, ide vecsinou takyto overlay vypnut pomocou esc.

Ku callbacku:

  1. callback je obecne pseudotyp v PHP a vetsinou ide o nejaku funkciu/metodu, ktoru je mozne zavolat
  2. to co mas sam napisane v kode tzn. callback( .. ) je interna funkcia nette, ktora ujednocuje zapis callbacku, kedze existuju 3 sposoby ako ho pisat

K variantam:
V podstate to co si popisal, su totozne moznosti, len zakazdym predavas callback inak

  1. odkazujes sa na triedu MyClass a jej staticku metodu myValidator. Umiestnenie triedy je lubovolne na tebe. Nette robot loader ju dohlada (ak ho mas spravne nastaveny). Dolezite je aby existovala a aby sa dala zavolat. Tiez treba mat na zreteli, ze ako argument sa jej predava IFormComtrol a nie samotna hodnota.
  2. Toto je closure, resp. anonymna funkcia, funguje to od PHP 5.3 takze sa uisti, ze ho mas na hostingu. Tam ako pises, nie su dva parametry ale len jeden a to ten IFormControl
  3. Zase raz len iny zapis callbacku, principialne to iste. MyApplication\Models\Users vsak nie je cesta ale nazov triedy spolu s namespaces, v tomto pripade to ani ne je full qualified, pretoze je to odkazovane relativne.

V principe teda mozes mat ako validator hocico co sa da zavolat – staticku metodu, metodu nejakeho objektu, funkciu alebo anonymnu funkciu (closure).

Dufam, ze je to uz jasnejsie.

Bertram
Člen | 75
+
0
-

Díky ka radu,ale ještě bych tě poprosil mě trochu nakopnout.
Jak funkuje ten callback jen tuším,protože bohužel neumím anglicky a překladač mi moc nepomohl.
Když vezmu tu první variantu,tak nemůžu přijít na to jakým způsobem mám ten parametr získat a předat.

Funkce která by tento parametr mohla přijímat by mohla vypadat např takto:

public static function overPolozku($ozn)
  {
    $radek = dibi::fetch('SELECT [id] FROM [trafa] WHERE [ozn]=%s', $ozn);
     return (bool) $radek;
  }
Nemohl by jsi mi prosím napsat,jak by měla být ta validace formulována?
Jak už jsem psal,nevím,kde ten parametr napsat a jak ho získat.
zkoušel jsem různé varianty na různých místech,ale bez úspěchu.

edit:Zkrátka potřebuji ověřit,zda daný název,který se zadá ve formuláři už není uložen v databázi.

Editoval Bertram (20. 10. 2010 15:28)

westrem
Člen | 398
+
0
-
public static function overPolozku(IFormControl $ozn)
{
    return (bool) dibi::fetchSingle('SELECT COUNT(*) FROM [trafa] WHERE [ozn]=%s', $ozn->getValue());
}

Ako som uz spominal a upozornoval, do callbacku sa predava IFormControl nie hodnota sama, preto musis na ziskanie hodnoty volat getValue().

Bertram
Člen | 75
+
0
-

Dík za pomoc,už jsem to rozchodil.

Jenom jsem tam musel vyhodit to IFormControl

Jinak mám totiž tuto chybu:

Argument 1 passed to Pokus::overPolozku() must be an instance of IFormControl, instance of Nette\Forms\TextInput given

Což mě právě pořád dokola vrací k otázce validačního pravidla a k tomu jak zde docílím toho,
že budu předávat argument IFormControl.

ověřovací metoda:

public static function overPolozku($control)
  {
    return !(bool) dibi::fetchSingle('SELECT COUNT(*) FROM [trafa] WHERE [ozn]=%s', $control->getvalue());
  }
validační pravidlo:
$form->addText('ozn','Název:')
         ->addRule(Form::FILLED, 'Zadejte název!')
         ->addRule('Pokus::overPolozku','Tento transformátor je již evidován');
Nemá tedy tady být někde uvedeno jaký argument předávám do ověřovací metody?
voda
Člen | 561
+
0
-

Argument 1 passed to Pokus::overPolozku() must be an instance of IFormControl, instance of Nette\Forms\TextInput given

Chybí ti tam akorát namespace, jinak to je správně:

public static function overPolozku(\Nette\Forms\IFormControl $control){}
westrem
Člen | 398
+
0
-

Pardon, no nebolo mi jasne aku verziu Nette pouzivas a mal som za to, ze ak tu s NS tak si ho budes vediet doplnit, ospravedlnujem sa.

Bertram
Člen | 75
+
0
-

Tady se není zač omlouvat,moc jsi mi pomohl a navíc jsem to měl asi uvést.
Moje situace se má tak,že se neučím jen Nette ale PHP vůbec.

Moje zdroje jsou pouze knihy a internet a to ještě pouze česky psané.
A pochopit o co vlastně jde,bez toho aby mi to někdo vysvětlil bývá někdy pěkně velký ořech
a tak si to čtu většinou pořád dokola a doufám že mi to docvakne.

Potřebuji si nějakým způsobem přivlastnit správné programátorské návyky,tak to zkouším s Nette,
což neznamená,že ovládám PHP.

westrem
Člen | 398
+
0
-

No som rad, ze som pomohol :)

Kazdopadne, ak sa ucis aj PHP, Nette moze byt zo zaciatku tazky oriesok v niektorych pripadoch, nie preto, ze by bolo zle napisane, ale skor preto, ze uz pouziva hodne pokrocilych technik a sam som pri citani zdrojakov musel niektore pasaze citat opakovane aby som stravil ich myslienku.

Je to vsak zaroven dobra prirucka ako sa naucit pisat veci cistejsie a lepsie, uz len preto, ze sa na vyvoji podiela aj hlas komunity a za nou je David, ktory v tomto sakra vie co robi.

Kedze vravis, ze ako zdroj mas najme ceske veci, mozno by som ti odporucil serial na linuxsofte – je sice uz starsieho data ale co som kukal prebera sa tam uz PHP 5ka a veci ako Namespaces a closures su aj tak novinky v PHP 5.3, pre teba je asi dolezitejsie plne podchytit PHP a potom zvysne novinky.