Alt om Statisk søkeord

I dag skal vi lære å bruke det statiske søkeordet i PHP. Vi skal gå over det grunnleggende og bygge noen eksempler. Det er på tide å legge til dette interessante språkfunksjonen til din webutviklingstaske med triks.


1 Et hurtigeksempel

La oss holde med et raskt eksempel først, for å se effekten av å bruke det statiske søkeordet.

Tenk deg å skrive en funksjon som husker hvor mange ganger totalt den har blitt kalt. Hvis du ikke er kjent med det statiske søkeordet, kan du ty til å bruke noen globale variabler:

 $ call_me_count = 0; funksjon call_me () global $ call_me_count; $ Call_me_count ++; ekko "Du ringte meg $ call_me_count ganger 
\ n "; // output => Du ringte meg 1 ganger call_me (); // output => Du ringte meg 2 ganger call_me (); // output => Du ringte meg 3 ganger call_me (); // output => Du ringte meg 4 ganger call_me ();

Bare fordi dette fungerer, betyr det ikke at du skal skrive kode på denne måten. Generelt sett blir globale variabler frynst på. Det er ikke en god ide å ha globale variabler flytende rundt, at noen funksjoner bare bruker privat.

Skriv inn det statiske søkeordet. Samme kode kan omskrives slik:

 funksjon call_me () // en statisk variabel statisk $ call_me_count = 0; $ Call_me_count ++; ekko "Du ringte meg $ call_me_count ganger 
\ n "; // output => Du ringte meg 1 ganger call_me (); // output => Du ringte meg 2 ganger call_me (); // output => Du ringte meg 3 ganger call_me (); // output => Du ringte meg 4 ganger call_me ();

Samme resultat, ikke flere globale variabler. Men hvordan fungerer dette nøyaktig?

Normalt blir alle lokale variabler inne i en funksjon ødelagt når funksjonen returnerer. De "statiske" søkeordene lar PHP vite å holde variabelen i live. Så neste gang funksjonen kalles, beholdes verdien inni variabelen.


2 Gyldige opprinnelige verdier

Som det var tidligere eksempel, da vi tilordnet verdien av 0 til variabelen, utførte den faktisk ikke en oppgaveoppgave. Det angir bare startverdien for variabelen. Det kan høres ut som det samme, men det er en liten forskjell. Variabelen kan bare initialiseres til en fast verdi, og ikke et uttrykk.

La oss se noen eksempler på gyldige og ugyldige startverdier. Først, la oss se på tall:

 funksjon foo () // gyldig statisk $ a = 9; // forårsaker parse feil statisk $ a = sqrt (81); // gyldig statisk $ a = 3,14; // forårsaker parse feil statisk $ a = pi (); // forårsaker parse feil statisk $ a = 1 + 3; 

Som du kan se, er ikke engang grunnleggende matteoperasjoner tillatt. Alt du kan tilordne er faste numre.

Vi kan også tildele strenge:

 funksjon foo () // gyldig statisk $ a = "; // gyldig statisk $ a = 'hei'; // forårsaker parse feil statisk $ a = strtoupper ('hallo'); // forårsaker parse feil statisk $ a = 'Hei Verden'; 

Igjen, det må være faste stenger, og ikke engang grunnleggende sammenkobling er tillatt.

Booleaner, Arrays og Constants vil også fungere:

 define ("SOME_CONSTANT", 789); funksjon foo () // gyldig statisk $ a = array (1,2,3); // gyldig statisk $ a = SOME_CONSTANT; // gyldig statisk $ a = array (1,2, 'tre', array ('foo' => 'bar')); // gyldig statisk $ a = true; 

3 Bygg en alternativ () -funksjon

Nå som vi vet hvordan statiske variabler i funksjonene virker, la oss bygge noe nytt med det.

Her er en enkel HTML-side med et enkelt bord i det:

    Mitt bord    
ID Navn Kategori
1 eple Frukt
2 Gulrot Grønnsak
3 Hund Dyr
4 Stekeovn Appliance

Resultatet er:


La oss legge til noen css, og gjøre radene alternativ farge:

    Mitt bord     
ID Navn Kategori
1 eple Frukt
2 Gulrot Grønnsak
3 Hund Dyr
4 Stekeovn Appliance

Nå ser det slik ut:


Hvis dataene kommer fra en database, og tabellraderne ble utført i en loop, må du legge til noe kode for å kunne angi de vekslende CSS-klassene til hver rad. De fleste ville bare gå videre og skape en variabel i den kretsen, legge til en betinget eller ternær uttalelse for å holde vekslende verdien.

Imidlertid skal vi bygge en mer elegant og gjenbrukbar løsning. Vi skal lage en funksjon som heter alternativ () som bruker begrepet statiske variabler.

 funksjonen alternativ ($ a, $ b) statisk $ alt = false; // reversere verdien av alt (sann <=> false) $ alt =! $ alt; hvis ($ alt) return $ a; // returnere først verdi annet return $ b; // retur andre verdi // Eksempel Bruk: // output: odd echo alternate ('odd', 'even'); // output: jevn ekko alternate ('odd', 'even'); // output: odd echo alternate ('odd', 'even');

Vi kaller funksjonen med to argumenter. Hver gang det kalles, returnerer det tilbake en av argumentene på en alternerende måte. Den oppnår dette ved å holde en boolsk verdi i en statisk variabel kalt $ alt. Hver gang det flipper disse variablene, må du bestemme hvilken av de to argumentene som skal returneres.

Så la oss bruke det på vår side ved å sette alt sammen:

  false) $ alt =! $ alt; hvis ($ alt) return $ a; // returnere først verdi annet return $ b; // retur andre verdi $ rows = array (array (1, 'Apple', 'Fruit'), array (2, 'Gulrot', 'Vegetabilsk'), array (3, 'Dog', 'Animal') , array (4, 'Ovn', 'Appliance')); ?>    Mitt bord     
ID Navn Kategori
', $ rad); ?>

Og det endelige resultatet er det samme:



4 Forbedre vår alternative () funksjon

Funksjonen vi opprettet fungerer bra, hvis vi bruker det bare på ett sted i våre skript. Det er imidlertid et lite problem med det. Hvis vi bruker det på flere steder, eller i nestede løkker, kan det ikke returnere verdiene i den rekkefølgen vi hadde til hensikt. La oss se denne koden for å demonstrere dette problemet:

 // en ekkosammenstilling ('a', 'b'). "
\ n "; // b echo alternate ('a', 'b')."
\ n "; // en ekkosammenstilling ('a', 'b')."
\ n "; // selv // (den andre verdien returneres først!) Ekko alternativt ('merkelig', 'jevn')."
\ n "; // odd echo alternate ('odd', 'even')."
\ n "; // bar // (samme problem) ekko alternativt ('foo', 'bar')."
\ n "; // a // (forrige gang det var også et) ekkos alternativt ('a', 'b')."
\ N ";

Vår funksjon må være oppmerksom på at den blir kalt fra forskjellige steder, og sørg for å returnere verdiene tilsvarende. Vi kan oppnå dette ved å legge til en valgfri siste parameter, for å tildele et ID-nummer. Og vi sender en unik ID fra hvert annet sted vi kaller det fra, for å unngå disse konfliktene:

 funksjonen alternativ ($ a, $ b, $ id = 0) statisk $ alt = array (); hvis (! isset ($ alt [$ id])) $ alt [$ id] = false;  $ alt [$ id] =! $ alt [$ id]; hvis ($ alt [$ id]) return $ a;  ellers return $ b;  // et ekkos alternativt ('a', 'b', 1). "
\ n "; // b echo alternate ('a', 'b', 1)."
\ n "; // et ekko alternativt ('a', 'b', 1)."
\ n "; // odd echo alternate ('odd', 'even', 2)."
\ n "; / / selv ekkosammenstilling ('odd', 'even', 2)."
\ n "; // foo echo alternate ('foo', 'bar', 3)."
\ n "; // b echo alternate ('a', 'b', 1)."
\ N ";

Denne gangen bruker vi en matrise som en statisk variabel. Den vil bære en unik boolesk verdi for hvert annet ID-nummer som ble bestått. Dette gjør det mulig å returnere verdiene i riktig rekkefølge.


5 statiske klassemedlemmer

Det "statiske" søkeordet brukes ikke bare innenfor funksjoner. Det er faktisk ganske vanlig i objektorientert programmering. Det kan være statiske medlemmer og metoder. Først skal vi se på hvordan statiske medlemmer jobber.

Her er syntaksen:

 klasse Foo // et statisk medlem statisk statisk $ a = 0; // et normalt medlem offentlig $ b = 0; offentlig funksjonslinje () // tilgang til det statiske medlem selv: $ a; selv :: $ a ++; selv: $ a = 3; // vanlig medlem: $ this-> b; $ Dette-> b ++; $ this-> b = 3;  // tilgang til det statiske medlemmet // fra utenfor Foo :: $ a; Foo :: $ a ++; Foo :: $ a = 3; $ obj = ny Foo (); // tilgang til det normale medlemmet $ obj-> b; $ Obj-> b ++; $ obj-> b = 3;

Legg merke til hvordan vi brukte søkeordet «selv ::» foran den statiske variabelen for å få tilgang til den i klassen, i stedet for «$ dette». Også, når det brukes i det ytre omfanget, trenger vi ikke å opprette en forekomst av objektet før vi får tilgang til de statiske variablene. Vanlige klassemedlemmer kan imidlertid bare nås etter at vi har opprettet en forekomst av dem.


6 En klasse som teller seg selv

Husk vårt første eksempel hvor vi hadde en funksjon som holdt telle på hvor mange ganger det ble kalt? La oss nå bruke det samme prinsippet til å objektere orienterte programmering.

Denne klassen vil ha muligheten til å telle hvor mange ganger totalt den har blitt opprettet:

 klasse Foo // vår forekomst teller offentlig statisk $ counter = 0; // for å fungere som en autoincrement ID offentlig $ id = 0; // Konstruktørfunksjonen offentlig funksjon __construct () // increment counter selv :: $ counter ++; // lagre det samme nummeret // som ID for dette objektet $ this-> id = self :: $ counter;  // output: 0 echo Foo :: $ teller. "\ N
"; $ a = ny Foo (); // output: 1 echo Foo :: $ counter." \ n
"; $ b = ny Foo (); // output: 2 echo Foo :: $ counter." \ n
"; $ c = ny Foo (); // output: 3 echo Foo :: $ counter." \ n
"; // output: 2 echo $ b-> id;

Hver gang et nytt objekt blir opprettet, kalles konstruktørfunksjonen som standard. Denne funksjonen inneholder kode for å angi telleren og id-nummeret for den forekomsten av objektet. Så, hvis et objekt ble opprettet for tredje gang, vil objektet ha et ID på 3, som bare er spesifikt for objektet. Telleren vil fortsette å gå som flere objekter fortsetter å bli skapt.

Vær oppmerksom på at vanlige klassemedlemmer finnes hver for seg på hver gjenstand. De statiske medlemmene eksisterer imidlertid bare en gang globalt.


7 Statiske klassemetoder

Ikke bare medlemmer, men også metoder for en klasse kan gjøres "statisk".

 klasse Foo // noter statisk søkeord offentlig statisk funksjon hallo () echo "Hello World"; 

Og slik kan du ringe dem:

 Foo :: hei (); // skriver Hello World

Legg merke til hvordan syntaksen ligner på å få tilgang til statiske medlemmer, ved å bruke dobbelt kolon (: :).

Inne i en statisk metode kan en klasse referere til seg selv ved hjelp av «selv» søkeordet, og få tilgang til statiske medlemmer på denne måten:

 klasse Foo offentlig statisk $ call_me_count = 0; offentlig statisk funksjon call_me () self :: $ call_me_count ++; ekko "Du ringte meg" .self :: $ call_me_count. "ganger 
\ n "; // output => Du ringte meg 1 ganger Foo :: call_me (); // output => Du ringte meg 2 ganger Foo :: call_me (); // output => Du ringte meg 3 ganger Foo :: call_me (); // output => Du ringte meg 4 ganger Foo :: call_me ();

8 Singleton-mønsteret

En 'Singleton' er en klasse som bare kan eksistere som en enkelt objekt forekomst. Den inneholder også en statisk referanse til denne forekomsten.

Det kan bli tydeligere ved å se på koden:

 klasse Foo // for å inneholde en forekomst av Foo private static $ instance; // gjør konstruktør privat, så det kan ikke kalles fra utenfor privat funksjon __construct ()  // singleton-metoden offentlig statisk funksjon getInstance () // hvis forekomsten ikke eksisterer ennå, opprett den hvis (! isset (selv :: $ eksempel)) $ c = __CLASS__; selv :: $ instance = new $ c;  // returnere det eneste eksemplet returnerer selv: $ instance;  // kloning er ikke tillatt offentlig funksjon __clone () trigger_error ('Kloning er ikke tillatt.', E_USER_ERROR); 

Dette er skjelettstrukturen. Du kan selvfølgelig legge til flere metoder og medlem, eller bare utvide klassen.

Når vi kaller getInstance () -metoden, skjer to ting.

 $ var = Foo :: getInstance ();

Først, hvis det ikke er noen Foo-objekt, blir en opprettet og tildelt Foo :: $ instance. Så, når det er det objektet, blir det returnert, så $ var blir det objektet. Hvis du ringer det flere ganger, hver gang du får det samme nøyaktige objektet; en ny forekomst blir ikke opprettet.

 $ var = Foo :: getInstance (); $ var2 = Foo :: getInstance (); // $ var og $ var2 refererer til det samme eksakte objektet

Siden vi gjorde metoden __construct () privat, kan vi ikke opprette nye forekomster av dette objektet.

 // dette vil kaste en feil $ var = ny Foo ();

9 En Singleton CurrentUser Class

Nå er det på tide å bygge et mer konkret eksempel med Singleton Pattern.

Tenk deg at du har en brukerklasse med ulike metoder:

 klassen bruker offentlig $ id; offentlig $ navn; offentlig $ e-post; offentlig funksjon load_user ($ id) // hent fra db // ... offentlig funksjon update_user ($ info) // oppdatering db med gitt $ info array // ... offentlig funksjon comment_count () // beregne antall kommentarer // ...

Vi har en metode for å hente en bruker etter ID fra databasen. Så det kan brukes slik:

 $ user = ny bruker (); $ Bruker-> load_user ($ user_id); // nå kan jeg se navnet, og andre ting echo $ user-> navn; echo $ user-> comment_count ();

Forestill deg nå at når en bruker er logget inn, lagrer du deres ID i økten. Og neste gang de laster inn en side, må du slå opp det id og opprette det tilhørende $ brukerobjektet for den brukeren igjen, hvis du ønsker å få tilgang til medlemmene og metodene til objektet.

Men på grunn av problemer med variabel omfang, må du enten gjøre $ brukerobjektet globalt, eller fortsette å initialisere det fra forskjellige funksjoner / metoder i skriptet. Her er hvor en singleton-klasse kan komme til nytte:

 klasse CurrentUser utvider bruker private static $ instance; privat funksjon __construct () // sørg for å ringe foreldreconstructor foreldre :: __ construct ();  offentlig statisk funksjon getInstance () // initialiser hvis (! isset (self :: $ instance)) // finnes økt? hvis (! $ _ SESSION ['user_id']) return false;  $ c = __CLASS__; selv :: $ instance = new $ c; selv :: $ eksempel-> load_user ($ _ SESJON [ 'user_id']);  returner selv: $ instance;  offentlig funksjon __clone () trigger_error ('Kloning er ikke tillatt.', E_USER_ERROR); 

Nå kan vi få tilgang til CurrentUser-klassen fra alle steder i vår søknad:

 $ user = CurrentUser :: getInstance (); hvis (! $ bruker) echo "Du er ikke logget inn!";  ellers echo Velkommen tilbake $ bruker-> navn ";

Så i vår kode behøvde vi ikke å bekymre oss for å håndtere økten. Vi kan rett og slett forsøke å få forekomsten av CurrentUser-objektet og bruke det akkurat som alle brukerobjekter, da det utvider funksjonaliteten.


Konklusjon

Jeg håper du likte denne opplæringen og lærte av det. Ser deg neste gang!