Astăzi vom învăța cum să folosim cuvântul cheie "static" din PHP. Vom trece peste elementele de bază și vom construi câteva exemple. Este timpul să adăugați această caracteristică interesantă a limbajului dvs. în punga de dezvoltare web a trucurilor.
Să rămânem mai întâi cu un exemplu rapid, pentru a vedea efectul utilizării cuvântului cheie static.
Imaginați-vă scrierea unei funcții care își amintește de câte ori a fost numită total. Dacă nu sunteți familiarizat cu cuvântul cheie "static", puteți recurge la utilizarea unei anumite variabile globale:
$ call_me_count = 0; funcția call_me () global $ call_me_count; $ Call_me_count ++; echo "Mi-ai sunat $ call_me_count times
\ n "; // output => M-ai sunat de 1 ori call_me (); // output => Mi-ai sunat de 2 ori call_me (); // output => Mi-ai sunat de 3 ori call_me (); => Mi-ai sunat de 4 ori call_me ();
Doar pentru că acest lucru nu înseamnă că trebuie să scrieți codul în acest fel. În general, variabilele globale sunt încruntate. Nu este o idee bună să avem variabile globale în jurul valorii de variabile, că unele funcții utilizează numai privat.
Acum introduceți cuvântul cheie "static". Același cod poate fi rescris astfel:
funcția call_me () // statică variabilă statică $ call_me_count = 0; $ Call_me_count ++; echo "Mi-ai sunat $ call_me_count times
\ n "; // output => M-ai sunat de 1 ori call_me (); // output => Mi-ai sunat de 2 ori call_me (); // output => Mi-ai sunat de 3 ori call_me (); => Mi-ai sunat de 4 ori call_me ();
Același rezultat, nu mai există variabile globale. Dar cum funcționează exact acest lucru?
În mod normal, toate variabilele locale din interiorul unei funcții se distrug odată ce funcția revine. Cuvintele cheie "statice" permit PHP să țină variabila în viață. Deci, data viitoare când se numește funcția, valoarea din interiorul variabilei este reținută.
După cum am văzut în exemplul anterior, când am atribuit valoarea 0 la variabila, nu a executat o instrucțiune de atribuire. Setați numai valoarea inițială pentru variabila. Aceasta poate părea același lucru, dar există o mică diferență. Variabila poate fi inițializată doar la o valoare fixă, și nu la o expresie.
Să vedem câteva exemple de valori inițiale valide și nevalide. În primul rând, să ne uităm la numere:
funcția foo () // validă statică $ a = 9; // cauzează eroarea de analiză statică $ a = sqrt (81); // valabil static $ a = 3,14; // cauzează eroarea de analiză statică $ a = pi (); // cauzează eroarea de analiză statică $ a = 1 + 3;
După cum puteți vedea, nu sunt permise nici măcar operațiile matematice de bază. Tot ce puteți atribui este numere fixe.
De asemenea, putem atribui șiruri de caractere:
() // statică validă $ a = "; // validă statică $ a = 'hello'; // cauzează parse error static $ a = strtoupper ('hello'); // cauzează eroare de analiză statică $ a = 'Salut Lume';
Din nou, trebuie să fie fixate șiruri de caractere și nu este permisă nici o concatenare de bază.
Booleani, Arrays and Constante vor funcționa și:
definiți ("SOME_CONSTANT", 789); funcția foo () // validă statică $ a = array (1,2,3); // static valid $ a = SOME_CONSTANT; // valabil static $ a = array (1,2, 'trei', array ('foo' => 'bar')); // static valid $ a = true;
Acum, când știm cum funcționează variabilele statice din interiorul funcțiilor, să construim ceva util cu el.
Aici este o pagină HTML simplă, cu un tabel simplu în ea:
Tabelul meu
ID-ul | Nume | Categorie |
---|---|---|
1 | măr | fruct |
2 | Morcov | Vegetal |
3 | Câine | Animal |
4 | Cuptor | Aparat |
Rezultatul este:
Acum, să adăugăm câteva css-uri și să facem culorile alternative:
Tabelul meu
ID-ul | Nume | Categorie |
---|---|---|
1 | măr | fruct |
2 | Morcov | Vegetal |
3 | Câine | Animal |
4 | Cuptor | Aparat |
Acum se arată astfel:
Dacă datele proveneau dintr-o bază de date și rândurile de tabelă au fost trimise într-o buclă, va trebui să adăugați un anumit cod pentru a putea seta acele clase CSS alternante la fiecare rând. Majoritatea oamenilor ar merge mai departe și să creeze o variabilă în acea buclă, să adauge o declarație condiționată sau ternară pentru a-și menține alternativ valoarea.
Cu toate acestea, vom construi o soluție mai elegantă și reutilizabilă. Vom crea o funcție numită alternativă () care utilizează conceptul de variabile statice.
funcția alternativă ($ a, $ b) static $ alt = false; // inversează valoarea lui alt (true <=> fals) $ alt =! $ alt; dacă ($ alt) returnați $ a; // întoarce prima valoare altceva return $ b; // returnați a doua valoare // Exemplu de utilizare: // output: odd echo alternate ('odd', 'even'); // output: chiar și echo alternate ('odd', 'even'); // output: odd echo alternate ("ciudat", "echivalent");
Se numește funcția cu două argumente. De fiecare dată când se cheamă, ea întoarce unul din argumente într-un mod alternativ. Aceasta realizează acest lucru păstrând o valoare booleană într-o variabilă statică numită $ alt. De fiecare dată când se răstoarnă această valoare variabile, pentru a determina care dintre cele două argumente să se întoarcă.
Deci, hai să folosim asta în pagina noastră, punând-o împreună:
fals) $ alt =! $ alt; dacă ($ alt) returnați $ a; // întoarce prima valoare altceva return $ b; // întoarce a doua valoare $ rows = array (array (1, 'Apple', 'Fruit'), array (2, 'Carrot', 'Vegetable' , array (4, "Cuptor", "Aparat")); ?>Tabelul meu
ID-ul | Nume | Categorie |
---|---|---|
', $ row); ?> |
Și rezultatul final este același:
Funcția pe care am creat-o funcționează bine, dacă o folosim doar într-un singur loc în scenariile noastre. Cu toate acestea, există o mică problemă. Dacă îl folosim în mai multe locuri sau în bucle imbricate, este posibil să nu întoarcem valorile în ordinea dorită. Să vedem acest cod pentru a demonstra această problemă:
/ / echo alternate ('a', 'b'). "
\ n "; // b echo alternativă (" a "," b ")."
\ n "; // a echo alternate (" a "," b ")."
\ n "; // // // (a doua valoare este returnată mai întâi!) echo alternate ('odd', 'even')."
\ n "; // odd echo alternate (" odd "," even ")."
\ n "; // bar // (aceeași problemă) echo alternate (" foo "," bar ")."
\ n "; // a // (ultima dată a fost" a ") echo alternate (" a "," b ")."
\ N ";
Funcția noastră trebuie să fie conștientă de faptul că este chemată din locuri diferite și să vă asigurați că veți reveni în consecință. Putem realiza acest lucru prin adăugarea unui ultim parametru opțional, pentru a atribui un număr de identificare. Și vom transmite un ID unic de la fiecare loc diferit pe care îl numim, pentru a evita aceste conflicte:
funcția alternativă ($ a, $ b, $ id = 0) statică $ alt = array (); dacă (! isset ($ alt [$ id])) $ $ [$ id] = false; $ alt [$ id] = $ $ [$ id]; dacă ($ alt [$ id]) return $ a; altceva return $ b; // a echo alternativă ('a', 'b', 1). "
\ n "; // b echo alternativă ('a', 'b', 1)."
\ n "; / / echo alternate ('a', 'b', 1)."
\ n "; // odd echo alternate (" ciudat "," chiar ", 2)."
\ n "; // chiar echo alternativă (" ciudat "," chiar ", 2)."
\ n "; // foo echo alternate (" foo "," bar ", 3)."
\ n "; // b echo alternativă ('a', 'b', 1)."
\ N ";
De data aceasta folosim o matrice ca variabilă statică. Acesta va avea o valoare booleană unică pentru fiecare număr de identificare diferit care a fost trecut. Acest lucru îi permite să returneze valorile în ordinea corectă.
Cuvântul "static" nu este folosit numai în interiorul funcțiilor. De fapt, este destul de obișnuită în programarea orientată obiect. Pot exista membri statici și metode. Mai întâi vom examina modul în care funcționează membrii statici.
Iată sintaxa:
clasa Foo // un membru static public static $ a = 0; // un membru public normal $ b = 0; funcția publică funcțională () // accesarea elementului static self :: $ a; auto :: $ a ++; auto :: $ a = 3; // membru normal: $ this-> b; $ This-> b ++; $ this-> b = 3; // accesarea membrului static // din afara Foo :: $ a; Foo :: $ a ++; Foo :: $ a = 3; $ obj = nou Foo (); // accesarea membrului normal $ obj-> b; $ Obj-> b ++; $ obj-> b = 3;
Rețineți modul în care am folosit cuvântul cheie "self" în fața variabilei statice pentru accesarea acestuia în cadrul clasei, și nu "$ this". De asemenea, atunci când este utilizat în domeniul exterior, nu este nevoie să creați o instanță a obiectului înainte de a putea accesa variabilele statice. Cu toate acestea, membrii claselor obișnuite pot fi accesați numai după ce am creat o instanță a acestora.
Amintiți-vă primul exemplu în care am avut o funcție care a ținut cont de câte ori a fost numită? Acum, să aplicăm același principiu programării orientate obiect.
Această clasă va avea capacitatea de a conta de câte ori total a fost creat:
clasa Foo // instanța noastră contra statică publică $ contra = 0; // să funcționeze ca ID de autoincrement public $ id = 0; // funcția constructorului funcția publică __construct () // increment counter self :: $ counter ++; // Salveaza acelasi numar // ca id-ul acestui obiect $ this-> id = self :: $ counter; // ieșire: 0 echo Foo :: $ counter. „\ N
"$ a = nou Foo (); / / output: 1 echo Foo :: $ counter"
"$ b = nou Foo (); / / output: 2 echo Foo :: $ counter"
"$ c = nou Foo (); / / output: 3 echo Foo :: $ counter"
"; // ieșire: 2 echo $ b-> id;
De fiecare dată când este creat un obiect nou, funcția constructor se numește implicit. Această funcție conține cod pentru setarea contorului și numărul de identificare pentru acea instanță a obiectului. Deci, dacă un obiect a fost creat pentru a treia oară, acel obiect va avea un id de 3, care este specific numai acelui obiect. Contorul va continua să meargă în sus pe măsură ce mai multe obiecte continuă să se creeze.
Rețineți că membrii obișnuiți de clasă există separat pentru fiecare obiect. Cu toate acestea, membrii statici există doar o dată la nivel global.
Nu doar membrii, ci și metodele unei clase pot fi făcute "statice".
clasa Foo // notați cuvântul cheie static funcția statică publică hello () echo "Hello World";
Și așa le puteți numi:
Foo :: alo (); // imprimă Hello World
Rețineți cum este similară sintaxa cu accesarea membrilor statici, utilizând dublu colon (: :).
În interiorul unei metode statice, o clasă se poate referi la ea însăși utilizând cuvântul cheie "auto" și accesează membrii statici în felul următor:
clasa Foo public static $ call_me_count = 0; funcția publică statică call_me () self :: $ call_me_count ++; echo "M-ai sunat" .self :: $ call_me_count. "ori
\ n "; // output => M-ai sunat de 1 ori Foo :: call_me (); // output => M-ai sunat de 2 ori Foo :: call_me (); // output => M-ai sunat de 3 ori Foo :: call_me (); // output => Mi-ai sunat de 4 ori Foo :: call_me ();
Un "Singleton" este o clasă care poate exista doar ca o instanță a unui singur obiect. De asemenea, conține o referință statică la această instanță.
S-ar putea să devină mai clară, uitându-te la cod:
clasa Foo // pentru a conține o instanță a instanței Foo private statice $; // constructor privat, deci nu poate fi apelat din afara functiei private __construct () // metoda singleton functionala statica publica getInstance () // daca instanta nu exista inca, creeaza-o daca (! esteset (auto :: $ instanță)) $ c = __CLASS__; auto :: $ instanță = nou $ c; // returnați singura instanță returnare auto :: $ instanță; // clonarea nu este permisă funcția publică __clone () trigger_error ('Clonarea nu este permisă', E_USER_ERROR);
Aceasta este structura scheletului. Puteți adăuga, desigur, mai multe metode și membri sau pur și simplu extindeți clasa.
Atunci când numim metoda getInstance (), se întâmplă două lucruri.
$ var = Foo :: getInstance ();
Mai întâi, dacă nu există niciun obiect Foo, unul este creat și atribuit instanței Foo :: $. Apoi, odată ce există acel obiect, acesta este returnat, deci $ var devine acel obiect. Dacă îl numiți de mai multe ori, de fiecare dată când veți obține același obiect exact; nu va fi creată o nouă instanță.
$ var = Foo :: getInstance (); $ var2 = Foo :: getInstance (); // $ var și $ var2 se referă la același obiect exact
Din moment ce am făcut metoda __construct () privată, nu putem crea instanțe noi ale acestui obiect.
// aceasta va arunca o eroare $ var = new Foo ();
Acum este momentul să construim un exemplu mai concret cu Modelul Singleton.
Imaginați-vă că aveți o clasă de utilizatori cu diferite metode:
utilizator de clasă public $ id; nume public $; public $ email; funcția publică load_user ($ id) // preluare din db // ... funcția publică update_user ($ info) // actualizarea db cu data $ $ array // ... funcția publică comment_count () // calcula numărul comentarii // ...
Avem o metodă de preluare a unui utilizator prin id din baza de date. Deci, ar putea fi folosit astfel:
$ user = utilizator nou (); $ User-> load_user ($ user_id); // acum pot vedea numele și alte lucruri echo $ user-> name; echo $ user-> comment_count ();
Acum, imaginați-vă că, odată ce un utilizator este conectat, stocați id-ul în sesiune. Iar data viitoare când se încarcă o pagină, trebuie să căutați acel id și să creați din nou obiectul $ user pentru acel utilizator, dacă doriți să accesați membrii și metodele acelui obiect.
Dar, datorită problemelor de domeniu variabil, va trebui fie să faceți obiectul utilizator global global, fie să-l inițializați din diferite funcții / metode în cadrul scriptului. Iată în cazul în care o clasă singleton poate veni la îndemână:
clasa CurrentUser extinde User static static instance $; funcția privată __construct () // asigurați-vă că ați apelat parent parent constructor :: __ construct (); funcția statică publică getInstance () // inițializați dacă (! isset (self :: $ instance)) // există sesiunea? dacă ! $ _ SESSION ['user_id']) return false; $ c = __CLASS__; auto :: $ instanță = nou $ c; auto :: $ instance-> load_user ($ _ SESSION [ 'user_id']); întoarcere de sine :: $ instanță; funcția publică __clone () trigger_error ("Clonarea nu este permisă", E_USER_ERROR);
Acum putem accesa clasa CurrentUser de oriunde din aplicația noastră:
$ user = CurrentUser :: getInstance (); dacă (! $ user) echo "Nu sunteți autentificat!"; altceva echo Welcome back $ user-> name ";
Deci, în codul nostru nu am avut de ce să ne facem griji în legătură cu sesiunea. Putem pur și simplu să încercăm să obținem instanța obiectului CurrentUser și să îl folosim la fel ca orice obiect al utilizatorului, deoarece își extinde funcționalitatea.
Sper că v-ați bucurat de acest tutorial și ați învățat de la el. Ne vedem data viitoare!