Internet Windows Android

Generatorul generează în php cum funcționează. Generarea de numere aleatoare PHP

În acest articol, vom explora generatoarele, care oferă o modalitate ușoară de a implementa iteratori simpli, fără costurile și complexitatea interfeței Iterator.

Cum funcționează generatoarele?

Potrivit Wikipedia, generatorul „foarte asemănător cu o funcție care returnează un tablou în care generatorul are parametri, îl puteți denumi și genera o secvență de valori”... Un generator este practic ca o funcție, dar în loc să returneze o valoare, oferă cât de multe valori este necesar. Este similar cu o funcție, dar acționează ca un iterator.

Generatorii folosesc cuvântul cheie randament în loc de returnare. Acționează în mod similar pentru a reveni, returnează valoarea funcției de apelare, dar în loc să elimine funcția din stivă, randamentul își salvează starea. Această funcție vă permite să continuați de unde era când a fost apelată din nou. De fapt, nu puteți returna o valoare a generatorului, deși puteți utiliza o valoare non-returnare pentru a termina execuția acestuia.

Manualul PHP spune: „Când se apelează o funcție generator, returnează un obiect care poate fi mutat.” Este un obiect al unei clase interioare a generatorului și implementează interfața iteratorului în același mod. Prin iterația asupra acestui obiect, PHP apelează generatorul de fiecare dată când are nevoie de o valoare. Această stare este păstrată numai atunci când este necesară următoarea valoare.

Ieșirea codului de mai sus va fi:

Generatorul a început

0

1

Oferă 2

Oferă 3

Afișat 4

Generatorul s-a epuizat

Primul nostru generator

Generatoarele nu sunt un concept nou și există deja în limbi precum C #, Python, JavaScript și Ruby și sunt de obicei identificate prin utilizarea lor. Randament cuvânt cheie. Mai jos este un exemplu în Python:

Def file_lines (nume fișier): fișier = deschis (nume fișier) pentru linie în fișier: randament linie fișier.close () pentru linie în fișier_linii („somefile”): .............

Să suprascriem generatorul Python în PHP. (Rețineți că ambele fragmente nu efectuează niciun fel de verificare a erorilor.)

Funcția generator deschide fișierul și apoi citește fiecare linie a fișierului după cum este necesar. De fiecare dată când este apelat generatorul, acesta continuă de unde a rămas. Nu începe de la început, deoarece starea sa a fost salvată atunci când acțiunea a fost confirmată. După ce toate liniile au fost citite, generatorul este pur și simplu oprit și ciclul se termină.

Returnarea cheilor

Iteratorii PHP sunt compuși din perechi cheie / valoare. În exemplul nostru, numai valoarea a fost returnată și, prin urmare, tastele erau numerice (tastele numerice sunt implicite). Dacă doriți să returnați o pereche asociativă, pur și simplu schimbați randamentul pentru a include cheia utilizând sintaxa matricei.

$ linie; ...) foreach (file_lines ("somefile") ca $ cheie => $ linie) (.............)?>

Introducerea unei valori

randamentul nu numai că returnează valori, dar poate primi și valori din exterior. Acest lucru se face apelând metoda send () a generatorului pe un obiect cu o valoare, dacă doriți să treceți și o valoare. Această valoare poate fi apoi utilizată în calcule sau alte lucruri.

trimite („opri”); ) ecou „($ v) n”; )?>

Ieșirea va fi după cum urmează:

Conservarea memoriei cu generatoare

Generatoarele sunt la îndemână pentru calcularea seturilor mari și, dacă nu doriți să alocați memorie pentru toate rezultatele în același timp sau când nu știți, veți avea nevoie de toate rezultatele. Datorită modului în care rezultatele sunt procesate, cantitatea de memorie poate fi redusă la minimum prin alocarea memoriei doar pentru rezultatul curent.

Imaginați-vă o funcție file () care returnează toate liniile dintr-un fișier ca matrice. Prin manipularea unui punct de referință simplu (scară) pentru fișier () și demo-ul nostru al funcției file_lines (), fiecare folosind aceleași fișiere text aleatoare de 100 de paragrafe folosind Lipsum, a arătat că funcția file () utilizează de până la 110 ori mai multă memorie decât generatorul ...

Odată cu introducerea Generatorilor, PHP a pus un instrument puternic în mâinile dezvoltatorilor. Acum putem scrie iteratori rapid, economisind multă memorie în acest proces. Cu acest tutorial, sper că ai obținut suficient pentru a începe să le folosești singur în proiectele tale.

Când conduci o mașină, viteza nu este totul. Dar în WEB totul este decis de viteză. Cu cât aplicația dvs. este mai rapidă, cu atât este mai bună experiența utilizatorului. Ok, acest articol este despre generatoare în PHP, deci de ce vorbim despre viteză? După cum veți vedea în scurt timp, generatoarele fac o mare diferență în ceea ce privește viteza aplicației și consumul de memorie.

Ce sunt generatoarele PHP?

Adăugat în PHP în versiunea 5.5 Generatoarele sunt funcții care oferă un mecanism simplu pentru a face looping prin date fără a fi nevoie să creați o serie de date în memorie. Încă nu sunteți sigur despre ce este vorba? Atunci să aruncăm o privire Generatoare PHPÎn acțiune.

Creați un fișier generator_test.php cu următorul conținut:


$ array =;
pentru ($ i = 0; $ i< $max; $i++) {
$ array = $ i;
}
returnează $ array;
}

Foreach (getRange (15) ca $ range) (
ecou "Date (interval $)
";
}

Apoi, în folderul în care avem acest fișier, deschideți consola și scrieți următoarele

Http: // localhost: 8000 / generator_test.php

Rezultatul va fi așa:

Date 1
Date 2
….
Date 15

Codul de mai sus este destul de simplu. Cu toate acestea, să facem o mică modificare:


ecou "Date (interval $)
";
}

Acum gama de numere generate este cuprinsă între 0 și constantă PHP_INT_MAX, care este cel mai mare întreg pe care îl poate reprezenta interpretul PHP... După aceea, reveniți la browser și actualizați pagina. Cu toate acestea, de data aceasta, în loc de text simplu, primim un mesaj că volumul a fost depășit. memorie disponibilă, în urma căruia scriptul a fost terminat anormal.

Ce păcat - u PHP fara memorie! Primul lucru care îmi vine în minte este să editați setarea. memory_limit în php.ini... Dar să ne întrebăm - este chiar atât de eficient? Vrem cu adevărat un singur script care să ocupe toată memoria disponibilă?

Folosim generatoare

Să scriem aceeași funcție ca mai sus, să o numim cu aceeași valoare PHP_INT_MAXși fugi din nou. Dar de data aceasta noi să creăm o funcție generator.

Funcția getRange ($ max = 10) (
pentru ($ i = 1; $ i< $max; $i++) {
randament $ i;
}
}

Foreach (getRange (PHP_INT_MAX) ca $ range) (
ecou "Date (interval $)
";
}

Definirea unei funcții getRange de data aceasta, doar repetăm ​​valorile și generăm o ieșire. Cuvânt cheie Randament asemănător cu instrucțiunile întoarcere prin aceea că returnează o valoare dintr-o funcție, dar singura diferență este aceea Randament returnează o valoare numai atunci când este necesar și nu încearcă să se potrivească întreaga matrice de date într-o singură dată. Accesând browserul, ar trebui să vedeți datele afișate pe pagină. Acordați atenție faptului că generatoarele în PHP pot fi utilizate numai din interiorul unei funcții.

De ce sunt necesare generatoare?

Din când în când, astfel de sarcini apar atunci când trebuie să procesăm cantități mari de date (de exemplu, fișiere jurnal), să efectuăm calcule pe eșantioane mari din baza de date etc. Și nu vrem în niciun caz ca aceste operații să ocupe toată memoria disponibilă, așa că ar trebui să încercăm să păstrăm memoria cât mai mult posibil. Datele nu trebuie să fie mari - Generatoare PHP eficace indiferent de dimensiunea datelor. Și nu uitați că scopul nostru este de a face aplicația rapidă și în același timp, astfel încât să consume cât mai puțină memorie.

Returnarea cheilor

Există momente în care trebuie să returnăm nu doar o valoare, ci o pereche cheie-valoare. Când folosim generatoare, putem genera perechi cheie-valoare după cum urmează.

Funcția getRange ($ max = 10) (
pentru ($ i = 0; $ i< $max; $i++) {
$ valoare = $ i * mt_rand ();
randament $ i => $ valoare;
}
}
?>

Putem folosi această funcție în același mod ca o matrice simplă:

Foreach (getRange (PHP_INT_MAX) ca $ cheie => $ valoare) (
ecou „Cheia (cheia $) este (valoarea $)”;
}

Trimiterea de valori către generatoare

Generatorii pot lua, de asemenea, valori. Prin aceasta înțelegem că generatoarele ne permit să inserăm valori, care pot fi o aparență a unei comenzi sau altceva. De exemplu, putem trimite o valoare către generatorul nostru care semnalează necesitatea de a opri execuția sau de a modifica ieșirea. Mai jos este un exemplu de cod:

Funcția getRange ($ max = 10) (
pentru ($ i = 1; $ i< $max; $i++) {
$ inject = randament $ i;
if ($ inject === "stop") return;
}
}

$ generator = getRange (PHP_INT_MAX);

Foreach ($ generator ca $ range) (
if ($ range === 10000) (
// trimiteți un mesaj generatorului
$ generator -> send ("stop");
}
print "Valoare (interval $)
";
}

Rețineți că folosind instrucțiunea întoarcere v funcții generator va avea ca rezultat o ieșire imediată din această funcție.

În cele din urmă, aș dori să subliniez că generatoarele oferă o îmbunătățire semnificativă a performanței pe care nu o putem ignora. De cele mai multe ori, nu este nevoie să avem servere puternice pentru a ne executa codul - trebuie doar să facem o mică refactorizare. Și generatoarele sunt un instrument foarte util pe care ar trebui să îl folosim mai des fără a le folosi în exces.

Apropo, despre generatoare Intru în detaliu în cursul meu. Există exemple și sarcini care vă vor ajuta să asimilați mai bine materialul.

Și acum luăm o funcție de generare a parolelor gata făcută și scriem un script pentru a recupera sau a crea o nouă parolă pentru utilizatorii site-ului dvs.

Script de recuperare a parolei

Cum este scris de obicei un script?

Ca întotdeauna, este elaborată o schemă pas cu pas, pe care trebuie să o facem în etape. Totul se întâmplă într-un singur fișier, reminder.php

1. Rulați scriptul numai dacă există o anumită variabilă, de exemplu $ action;

2. Pentru a începe procesul de generare a unei parole, utilizatorul specifică Adresa de e-mail$ _POST [`ema'l`]; Pentru a simplifica codul, atribuim valoare dată variabilă $ email.

3. Verificați cu expresii obisnuite toate caracterele pentru a se asigura că utilizatorul a specificat corect adresa de e-mail. Dacă nu, afișați o eroare, terminați scriptul. Dacă totul este corect, să mergem mai departe.

4. Căutăm în baza de date, în cazul nostru în tabelul utilizatorilor pentru un utilizator cu aceeași adresă poștală. Dacă nu, vom emite o eroare că nu există o astfel de adresă în baza de date și terminăm scriptul.

5. Există un utilizator cu o astfel de adresă în baza de date, continuați și lansați funcția de a genera o nouă parolă. De asemenea, la adresa de e-mail, obținem un ID de utilizator unic din baza de date și îl scriem în variabila $ id;

Reg.ru: domenii și găzduire

Cel mai mare registrator și furnizor de găzduire din Rusia.

Peste 2 milioane de nume de domenii în serviciu.

Promovare, mail pentru domeniu, soluții de afaceri.

Peste 700 de mii de clienți din întreaga lume și-au făcut deja alegerea.

Cadrul Bootstrap: aspect rapid și receptiv

Un tutorial video pas cu pas despre elementele de bază ale aspectului receptiv în cadrul Bootstrap.

Învață să tipești ușor, rapid și eficient folosind un instrument puternic și practic.

Aspect pentru comandă și pentru a fi plătit.

* Plasați mouse-ul pentru a întrerupe derularea.

Inapoi inainte

Generarea de șiruri aleatorii în PHP

În această scurtă postare, vă voi arăta cum puteți genera un șir aleatoriu utilizând PHP.

O sarcină similară poate apărea într-o varietate de situații, de exemplu:

Generarea unei parole aleatorii dintr-un set predefinit de caractere;

Generarea unui nume aleatoriu pentru un fișier sau folder (pentru a le ascunde și proteja);

Crearea unui identificator unic temporar pentru un proces;

Utilizarea unui șir aleatoriu ca „material sursă” pentru un script mai complex etc.

Există și alte utilizări pentru șirurile aleatorii cu care poți deveni creativ.

În PHP nu există nicio funcție specială care să îndeplinească sarcina care ne interesează, așa că trebuie să scrieți un astfel de instrument în funcție de nevoile dvs.

Mai jos este una dintre opțiunile pentru rezolvarea acestei probleme.

// Funcția ia 2 parametri: lungimea șirului aleatoriu și caracterele implicate în funcția de formare random_string ($ str_length, $ str_characters) ($ str_characters = array (0,1,2,3,4,5, 6,7,8, 9, „a”, „b”, „c”, „d”, „e”, „f”, „g”, „h”, „i”, „j”, „k "," l "," m "," n "," o "," p "," q "," r "," s "," t "," u "," v "," w ", „x”, „y”, „z”, „A”, „B”, „C”, „D”, „E”, „F”, „G”, „H”, „I”, „J "," K "," L "," M "," N "," O "," P "," Q "," R "," S "," T "," U "," V ", „W”, „X”, „Y”, „Z”); // Funcția poate genera un șir aleatoriu folosind alfabetul chirilic // $ str_characters = array (0,1,2,3,4,5,6 , 7,8,9, "a", "b", "c", "g", "d", "e", "g", "z", "i", "k", "l" , "m", "n", "o", "p", "p", "s", "t", "y", "f", "x", "c", "h", " w "," u "," e "," u "," i "); // Returnează fals dacă primul parametru este zero sau nu este întreg dacă (! is_int ($ str_length) || $ str_length< 0) { return false; } // Подсчитываем реальное количество символов, участвующих в формировании случайной строки и вычитаем 1 $characters_length = count($str_characters) - 1; // Объявляем переменную для хранения итогового результата $string = ""; // Формируем случайную строку в цикле for ($i = $str_length; $i >0; $ i--) ($ string. = $ str_characters;) // Returnează rezultatul returnează $ string; )

Deoarece materialul este destinat începătorilor, voi explica cum funcționează această funcție.

Funcția de generare a unui șir aleatoriu în sine ia doi parametri. Primul este numărul de caractere pe care vrem să le vedem în șirul rezultat. Al doilea este direct o serie de caractere pe care dorim să le folosim atunci când generăm.

Deoarece execuția funcției nu are sens dacă lungimea șirului rezultat este zero sau negativă și va fi spartă dacă se specifică un număr care nu este întreg, asigurăm aceste situații și returnăm fals.

Dacă primul parametru este corect, atunci numărăm numărul de caractere care participă la formarea șirului folosind funcția count () și scădem unul din numărul rezultat. De ce facem asta? Voi răspunde la această întrebare puțin mai târziu, dar deocamdată să trecem la funcție.

Prin declararea unei variabile $ string pentru a stoca rezultatul final, începem să generăm o linie aleatorie într-o buclă pentru.

Ca valoare inițială a contorului $ i bucla reprezintă numărul de caractere pe care vrem să le vedem în șirul aleatoriu ($ str_length).

Apoi vine condiția ca bucla să fie executată atâta timp cât valoarea contorului este mai mare decât zero.

În cele din urmă, după fiecare iterație a buclei, diminuăm valoarea contorului cu una folosind operatorul de decrement "-".

Astfel, bucla va efectua câte iterații dorim pentru a obține numărul de caractere din șirul final.

Ei bine, acum să privim corpul buclei și să revenim la întrebarea de ce am scăzut unul din numărul total de caractere din variabilă. $ str_caractere.

După cum puteți vedea, formăm linia finală prin adăugarea secvențială a variabilei $ string câte un caracter pentru fiecare trecere prin buclă.

Să aruncăm o privire mai atentă.

Folosim funcția mt_rand ()și treceți-i doi parametri - zero și aceeași variabilă redusă cu unul $ caractere_lungime... Funcţie mt_rand () ne permite să generăm pur și simplu un număr aleatoriu într-un interval dat (adică de la zero la $ caractere_lungime).

Punctul utilizării acestei funcții este că, cu ajutorul său, creăm un număr aleatoriu care este utilizat ca index pentru matrice. $ str_caractere.

Indexul indică ce caracter este din matrice $ str_caractere vrem să primim.

Aici ajungem la punctul cheie. Dacă am primit primul element folosind o construcție de genul

$ str_caractere;

atunci ultimul element ar putea fi obținut scriind următoarele (la urma urmei, avem 62 de elemente în matrice):

$ str_caractere;

Acest lucru ar fi destul de logic, dar, din păcate, nu este adevărat.

De fapt, primul articol este accesibil prin

$ str_caractere;

și 62 element (ultimul) prin

$ str_caractere;

Puteți verifica acest lucru prin simpla afișare a acestor valori.

Acum devine complet clar de ce am scăzut unul din 62. Numai pentru ca intervalul indicilor noștri să fie de la 0 la 61. Acesta este ceea ce ne va oferi formarea corectă a unui șir aleatoriu fără probabilitatea de a ne referi accidental la un element inexistent cu un indice de 62.

Asta e tot. Returnarea unei valori folosind operatorul întoarcere- și funcția noastră este gata.

Rămâne să-l apelăm și să trecem ca parametru numărul dorit de caractere din șirul nostru aleatoriu, de exemplu:

Echo random_string (16, $ str_characters);

Ca rezultat, obținem ceva complet incoerent, cum ar fi:

ATq4Lh9PNEm8cCxp

Scopul a fost atins, iar acum ne putem aplica creativ funcția acolo unde este necesar.

Desigur, funcția noastră este universală și funcționează excelent și cu limba rusă. În codul de mai sus, puteți vedea o altă variantă a matricei $ str_caractere(este comentat) care conține caractere chirilice.

Pentru a verifica acest lucru, putem comenta prima matrice $ str_caractere(cu caractere latine) și decomentați al doilea.

Acum, dacă actualizăm pagina, vom obține ceva de genul:

Ju4d70y779care5

În acest fel, puteți utiliza orice simboluri doriți. Pentru a face acest lucru, le puteți adăuga fie la o matrice existentă, fie creați una nouă.

Și, în sfârșit, o remarcă care poate fi utilă.

Sunt sigur că, ca utilizator, ați dat peste parole generate aleatoriu, în care este greu de înțeles ce este acest simbol:

Fie litera mică „l”, fie numărul „1”;
- fie „c” rusesc, fie „c” englezesc;
- fie „y” rusesc, fie „y” englezesc;
- fie zero, fie litera „o” (din nou, rusă sau engleză);
- etc.

Prin urmare, dacă tu însuți generezi un șir pentru alți utilizatori, ar trebui să te asiguri că este ușor de înțeles pentru ei. Imaginați-vă că sunteți în locul altei persoane și întrebați-vă: „Ce este asta?”, „Este o literă sau un număr, la naiba?”

Vă aduc la cunoștință soluția mea pentru generarea html în PHP. Sarcina pare a fi banală, dar aș vrea să fie extensibilă, scurtă, dar în același timp cu funcționalitate bună. Nu părea să fie rău.

Trebuie să spun imediat (așa cum mulți cred în comentarii) că sarcina nu a fost de a scrie un motor de șabloane (dintre care există deja multe) și de a nu înlocui motorul de șabloane JavaScript. Știu perfect că adevăratul mod este de a separa html și date. Dar am avut nevoie să scriu html în clase, să creez componente cadru, cum ar fi CGridView în yii, merită să pun html în astfel de locuri în fișiere separate tu decizi.

Scopul principal este de a scăpa de html în clase și funcții.

Un exemplu simplu, un buton obișnuit:

CHtml :: create () -> p () -> a (array ("href" => "http://habrahabr.ru", "class" => "btn")) -> text ("Accesați" ) -> render ();
Rezultat:

Mergi la

Nimic dificil, ar putea fi limitat la asta, dar am vrut bucle:
$ arr = array ("1" => "First", "2" => "Second"); CHtml :: create () -> select ($ options) -> each (CHtml :: plainArray ($ arr, "value", "text")) -> option ("array (" value "=> $ data-> valoare) ") -> text (" $ date-> text ") -> end () -> endEach ()
Aici a fost necesar să se apeleze funcția plainArray (), care transformă tabloul în forma:
$ arr = array (array ("value" => "1", "text" => "First"), array ("value" => "2", "text" => "Second"));
Etichetele din buclă pot conține funcții sau șiruri cu expresii eval, orice imbricare, de exemplu cu un tabel:

$ coloane = array (array ("id" => "NAME", "label" => "Name"), array ("id" => "AGE", "label" => "Age")); $ date = array (array ("NAME" => "Peter", "AGE" => 29), array ("NAME" => "Vasily", "AGE" => 32)); CHtml :: create () -> table () -> thead () -> tr () -> fiecare ($ coloane) -> th () -> text (funcție ($ coloană) (returnează $ coloană ["etichetă") ];)) -> end () -> endEach () -> end () -> end () -> tbody () -> each ($ data) -> tr () -> each ($ coloane) -> td () -> text (funcție ($ rând, $ coloană) (returnează $ rând [$ coloană ["id"]];)) -> end () -> endEach () -> end () -> endEach ( ) -> render ();

Etichetele neînchise sunt închise automat.

Clasa poate fi extinsă pentru a fi utilizată în formulare. Puteți să o extindeți prin injecție de moștenire sau dependență, pentru modul în care vor fi afișate fiecare etichetă și atributele acesteia, este utilizată o funcție, astfel încât să puteți înlocui cu ușurință acest comportament.

Clasa CMyHtml extinde CHtml (funcția publică a ($ options = array ()) ($ implicit = array ("href" => "javascript: void (0)"); returnare părinte :: a (array_replace ($ implicit, $ opțiuni) ));))

Clasa CForm (private $ _lastLabel = ""; funcție publică __construct (model CModel $, CHtml $ html = nul) ($ this -> _ model = $ model; $ this -> _ html = $ html ?: CHtml :: create ();) funcție publică __call ($ method, $ ps) ($ options = $ ps? $ ps: array (); if ($ method === "label") ($ this -> _ lastLabel = isset ($ opțiuni ["pentru"])? $ this -> _ model-> getLabel ($ options ["for"]): "";) if ($ method === "text" && $ this -> _ lastLabel) ( $ options = $ options?: $ this -> _ lastLabel; $ this -> _ lastLabel = "";) $ this -> _ html -> $ method ($ options); returnează $ this;))

Soluția în sine poate fi vizualizată și încercată la