Vad man kan förvänta sig från PHP 5.5

Den första PHP 5,5 alpha har publicerats offentligt. Efter att ha haft tid att testa och experimentera med det, kan vi nu ge dig en djup överblick över vad vi ska se fram emot!


Installation

Om du vill följa med den här artikeln måste du installera PHP 5.5 för dig själv. Du kan hitta länken till källknippen här. Dessutom, om du behöver binärfilen i Windows kan du ta den från samma sida.

När du har hämtat källkoden, extrahera allt i en mapp och navigera till det med ditt favoritprogram. Du kan installera PHP till var du vill, men för enkelhets skyld kommer jag att skapa en katalog i roten till min enhet, kallad PHP5.5. Om du vill skapa en ny mapp och sedan göra din användare ägaren till den nämnda mappen skriver du in följande i din terminal:

 sudo mkdir /PHP5.5 sudo chown användarnamn /PHP5.5

Därefter måste du bestämma vilka tillägg och funktioner du vill installera med din kopia av PHP. Eftersom det här är en Alpha-version, som endast är avsedd för testning, kommer jag inte att oroa mig för att den ska fungera fullt ut. För denna handledning kommer jag bara att installera cURL, men det kan finnas andra saker som du vill lägga till, till exempel MySQL eller zip-support. För att visa en fullständig lista över konfigurationsalternativ, kör:

 ./ konfigurera -h

Förutom alternativet att installera cURL finns det två andra egenskaper som vi behöver ange: prefix och med-config-fil-path alternativ. Dessa två egenskaper ställer in platsen för PHP-installationen och .ini fil, respektive. Så i terminalen skriver du:

 ./ configure --prefix = / PHP5.5 - med-config-file-path = / PHP5.5 - med-curl = ext / curl gör gör installera

Den första raden konfigurerar PHP med cURL, och ställer in platsen i den mapp som vi gjort tidigare. De två följande raderna bygger PHP och flyttar filerna till den angivna katalogen. Nästa steg är att kopiera provet php.ini filen till PHP-mappen. För att göra detta kör du:

 cp php.ini-utveckling /PHP5.5/php.ini

Du ska nu ha allt installerat korrekt. Det enklaste sättet att testa den här nya versionen är att köra den inbyggda webbservern. Navigera till bin mapp inuti PHP5.5 katalog (cd /PHP5.5/bin) och typ ./ php -t / Path / To / Directory -S 0.0.0.0:4444.

  • De -t alternativet ställer in serverns rotkatalog (dvs den plats där du ska placera dina PHP-filer)
  • De -S egenskapen anger IP-adressen och portnumret där servern ska binda till. Använder sig av 0.0.0.0 för IP-adressen berättar servern att lyssna på alla IP-adresser (t ex localhost, 127.0.0.1, 192.168.0.100 etc.).

Om allt går bra bör du hälsas med ett meddelande som säger att servern lyssnar på den angivna IP / porten, och den kommer att berätta om dokumentroten där den serveras. Vi kan nu börja leka med de nya funktionerna!


generatorer

Generatorer tillåter dig att skapa anpassade funktioner, som behåller tillståndet mellan körningar.

Det största tillägget till PHP 5.5 måste vara generatorer. Generatorer tillåter dig att skapa anpassade funktioner, som behåller tillståndet mellan körningar. Det fungerar av ett nytt sökord, kallat avkastning, som kan användas i en funktion för både inmatning och utmatning av data.

I huvudsak, när funktionen kommer till en rad som innehåller avkastningskommandot, kommer PHP att frysa funktionens utförande och gå tillbaka till att köra resten av programmet. När du ringer till att funktionen fortsätter - antingen genom att säga att den ska gå vidare eller genom att skicka den - kommer PHP att gå tillbaka till funktionen och hämta upp var den slutade, behålla värdena för lokala variabler som definierades upp till där.

Det här kanske låter lite coolt först, men om du tänker på det, öppnar detta dörrar till många intressanta designalternativ. För det första simulerar det effekterna av andra programmeringsspråk som har "Lazy Evaluation", som Haskell. Detta ensam låter dig definiera oändliga dataset och modellmatematiska funktioner efter deras faktiska definition. Dessutom behöver du inte skapa så många globala variabler. om en variabel endast är avsedd för en specifik funktion kan du inkludera den i en generator och saker som räknare händer automatiskt av generatorn själv i form av det returnerade objektets nyckel.

Jo det är nog teori för nu. låt oss ta en titt på en generator i åtgärd. För att starta, navigera till dokumentrotten du definierade när du kör PHP-servern och skapa en fil som heter "index.php". Öppna nu filen och skriv in följande:

 funktion fibonacci () $ a = 0; $ b = 1; medan (sant) $ a = $ a + $ b; $ b = $ a - $ b; ge ut $ a; 

Detta är "Hello World" -funktionen i oändliga dataset. Det är en funktion som kommer att mata ut alla fibonacci-nummer. För att använda generatorn är allt du behöver göra typ:

 $ fib = fibonacci (); $ Fib-> ström (); $ Fib-> nästa (); $ Fib-> ström (); // ... 

Vad som händer här är att vi gör $ fib ett generatorobjekt, och då har du tillgång till de underliggande kommandona, som nuvarande() och Nästa(). De nuvarande() funktionen returnerar nuvärdet av generatorn; det här är värdet av vad du gav i funktionen - i vårt fall, $ a. Du kan ringa denna funktion flera gånger och du kommer alltid att få samma värde, eftersom nuvarande() funktionen berättar inte generatorn att fortsätta utvärdera sin kod. Det är där Nästa() funktionen kommer in Nästa() används för att frigöra iseratorn och fortsätta med funktionen. Eftersom vår funktion är inuti en oändlig medan loop, det kommer bara att frysa igen nästa avkastning kommando, och vi kan få nästa värde med ett annat samtal till nuvarande().

Fördelarna med generatorer är att de lokala variablerna är beständiga.

Om du behövde göra någonting som detta tidigare, skulle du behöva lägga någon form av för loop som förberäknar värdena i en array och stoppar efter ett visst antal iterationer (t ex 100), för att inte överbelasta PHP. Fördelarna med generatorer är att de lokala variablerna är beständiga, och du kan bara skriva vad funktionen ska göra, som tillhörde hur det ska göra det. Vad jag menar med detta är att du bara skriver uppgiften och oroar dig inte för globala variabler, och hur många iterationer ska utföras.

Den andra vägen avkastning kan användas är att ta emot data. Det fungerar på samma sätt som tidigare: när funktionen kommer i linje med avkastning sökord, det kommer att sluta, men istället för att läsa data med nuvarande(), Vi kommer att ge den data med skicka() fungera. Här är ett exempel på detta i åtgärd:

 funktion logger () $ log_num = 1; medan (sann) $ f = utbyte; echo "Log #". $ log_num ++. ":". $ F;  $ logger = Logger (); för ($ i = 0; $ i<10; $i++) $logger->skicka ($ i * 2); 

Detta är en enkel generator för att visa ett loggmeddelande. Alla generatorer startar i pausat tillstånd. ett samtal till skicka (eller ens nuvarande) startar generatorn och fortsätter tills den träffar a avkastning kommando. De skicka Kommando kommer sedan att mata in den skickade data och fortsätta att bearbeta funktionen tills den kommer till nästa avkastning. Varje efterföljande samtal till skicka kommer att behandla en slinga; det kommer att mata in den skickade data till $ f, och fortsätt sedan tills det slingrar tillbaka till nästa avkastning.

Så varför inte bara detta till en vanlig funktion? Tja, du kan, men då skulle du antingen behöva en separat global variabel för att hålla reda på loggnumret, eller du skulle behöva skapa en anpassad klass.

Tänk inte på generatorer som ett sätt att göra någonting som aldrig var möjligt, utan snarare som ett verktyg för att göra saker snabbare och effektivare.

Till och med oändliga uppsättningar var möjliga, men det skulle behöva uppdatera listan från början varje gång (dvs. gå igenom matematiken tills den kommer till det aktuella indexet) eller lagra all dess data inom globala variabler. Med generatorer är koden mycket renare och mer exakt.


Listor i för varje uttalanden

Nästa uppdatering som jag tyckte var ganska hjälpsam är möjligheten att bryta en nestad array i en lokal variabel i en för varje påstående. De lista konstruera har funnits en stund (sedan PHP4); det kartlägger en lista över variabler i en array. Så istället för att skriva något som:

 $ data = array ("John", "Smith", "032-234-4923"); $ fName = $ data [0]; $ lName = $ data [1]; $ cell = $ data [2];

Du kan bara skriva:

 $ data = array ("John", "Smith", "032-234-4923"); lista ($ fName, $ lName, $ cell) = $ data;

Det enda problemet var att om du hade en uppsättning arrays (en nestad array) av information du ville kartlägga, kunde du inte cykla genom dem med en för varje slinga. Istället skulle du behöva tilldela för varje resultera i en lokal variabel och kartlägg sedan den med a lista konstruera bara inuti slingan.

Från version 5.5 kan du klippa ut mitten och rensa upp din kod. Här är ett exempel på den gamla vägen, mot den nya:

 // - Old Method - // foreach ($ parentArr som $ childArr) list ($ one, $ two) = $ childArr; // Fortsätt med loop // - Ny metod - // foreach ($ parentArr som lista ($ one, $ two)) // Fortsätt med loop

Den gamla vägen verkar inte som för mycket besvär, men det är rörigt och gör koden mindre läsbar.


Easy Password API

På min Macs inbyggda grafikkort kunde jag gå igenom över 200 miljoner hashar en sekund!

Nu kräver den en liten kunskap om hash och kryptering att uppskatta fullt ut.

Det enklaste sättet att ha ett lösenord i PHP har varit att använda något som MD5 eller en SHA-algoritm. Problemet med hashfunktioner som dessa är att de är otroligt lätta att beräkna. De är inte användbara längre för säkerhet. Numera borde de bara användas för att verifiera en fils integritet. Jag installerade en GPU-hasher på min dator för att testa denna anspråk. På min Macs inbyggda grafikkort kunde jag gå igenom över 200 miljoner hashar en sekund! Om du var dedikerad och investerat i en överst på rad med flera grafikkort setup, kan du eventuellt gå igenom miljarder hashar en sekund.

Tekniken för dessa metoder var inte tänkt att vara sist.

Så hur fixar du detta problem? Svaret är att du ställer en justerbar belastning på algoritmen. Vad jag menar med detta är att du gör det svårt att bearbeta. Inte att det ska ta några sekunder per hash, eftersom det skulle förstöra användarens upplevelse. Men föreställ dig att du gjorde det ta en halv sekund att generera. Då skulle en användare sannolikt inte ens inser förseningen, men någon som försöker att bruteforce skulle behöva springa igenom miljontals försök - om inte mer - och alla halv sekunder skulle lägga upp i årtionden och århundradena. Vad sägs om problemet med att datorer blir snabbare över tiden? Det är här den "justerbara" delen kommer in: varje så ofta skulle du öka komplexiteten för att skapa en hash. På så vis kan du se till att det alltid tar samma tid. Detta är vad utvecklarna av PHP försöker uppmuntra människor att göra.

Det nya PHP-biblioteket är ett häftande "arbetsflöde" där människor enkelt kan kryptera, verifiera och uppgradera hash och deras respektive komplexiteter över tiden. Det skickas för närvarande endast med bcrypt-algoritmen, men PHP-teamet har lagt till ett alternativ med namnet standard som du kan använda. Den uppdaterar automatiskt din hash till den säkraste algoritmen när de lägger till nya.

Det sätt som bcrypt fungerar är att det kör ditt lösenord genom blowfish-kryptering x antal gånger, men istället för att använda blowfish med en nyckel så att du kan vända den senare, passerar den tidigare körningen som nyckeln till nästa iteration. Enligt Wikipedia kör det ditt lösenord genom 2 till x belopp. Det är den del som du kan anpassa. Säg, just nu vill du använda en kostnadsnivå på 5: bcrypt kör din hash 2 till 5, eller 32 gånger. Detta kan verka som ett lågt antal, men eftersom kostnadsparametern justerar funktionen exponentialt, om du ändrade den till 15, skulle funktionen köra den genom 32768 gånger. Standardkostnadsnivån är 10, men det kan konfigureras i källkoden.

Med teorin ur vägen, låt oss ta en titt på ett komplett exempel.

 $ pass = "Secret_Password"; $ hash = password_hash ($ pass, PASSWORD_BCRYPT, array ('cost' => 12, 'salt' => "twenty.two.letter.salt")); om password_verify ($ pass, $ hash)) if (password_needs_rehash ($ hash, PASSWORD_DEFAULT, array ('kostnad' => 15))) $ hash = password_hash ($ pass, PASSWORD_DEFAULT, array 15));  // Gör något med hash här. 

De password_hash funktionen accepterar tre parametrar: ordet till hash, en konstant för hashingalgoritmen och en valfri lista med inställningar, som inkluderar salt och kostnad. Nästa funktion, password_verify, ser till att en sträng matchar hasen efter kryptering, och slutligen password_needs_rehash funktionen säkerställer att en hash följer de angivna parametrarna. Till exempel, i vårt fall ställer vi in ​​hashkostnaden till tolv, men här anger vi 15, så funktionen kommer att återvända Sann, vilket betyder att det måste återhämtas.

Du kanske har märkt det, i password_verify och password_needs_rehash funktioner, du behöver inte ange den hashingmetod som används, saltet eller kostnaden. Detta beror på att dessa detaljer är prepended till hashsträngen.

Salter används för att förhindra att hasar förkomputeras till regnbordsbordet.

Anledningen till att det är okej att bunta kostnaden och saltet tillsammans med hasen och inte hålla det hemligt, beror på hur systemet sätter sina styrkor ihop. Kostnaden behöver inte vara hemlig, eftersom det är meningen att det är ett nummer som ger en tillräckligt stor belastning på servern. Vad jag menar med det här är det, även om någon får din hash och bestämmer att din kostnadsnivå kräver 1/2 sekund att beräkna, kommer han att veta vilken nivå som bruteforce på, men det kommer att ta honom för lång tid att knäcka (t.ex. årtionden ).

Salter används för att förhindra att hasar förkomputeras till ett regnbordsbord.

Ett regnbordsbord är i grunden en nyckelvärdesaffär med en ordbok med ord med motsvarande korv som deras nycklar.

Allt man behöver göra är att förklara tillräckligt vanliga ord - eller, värre, alla strängmöjligheter - och sedan kan de slå upp ordet för en given hash direkt. Här är ett exempel på hur salter kan vara till hjälp: låt oss säga att ditt lösenord är ordet "lösenord". Normalt är detta ett ganska vanligt ord; det skulle troligen vara i deras regnbordsbord. Vad ett salt gör är att det lägger till en slumpmässig sträng till ditt lösenord; så, istället för att ha "lösenord", är det verkligen hashing "passwordRandomSalt524% # $ &." Detta är betydligt mindre sannolikt att vara förberäknad.

Så varför är salter vanligtvis ansedda som privata uppgifter? Traditionellt, med saker som MD5 och liknande, när någon vet ditt salt, kan de återvända till att utföra sina bruteforce-tekniker, förutom att de kommer att lägga till ditt salt till slutet. Det betyder, istället för att bruteforce din slumpmässiga lösenordssträng, de bruteforcing ett mycket kortare standard lösenord och bara lägga till saltet. Men lyckligtvis, eftersom vi har kostnadsfaktorinställningen, skulle det ta för lång tid att beräkna varje hash över med det nya saltet.

Att återskapa: salter säkerställer att förkomprimering av en hash inte kan användas igen på en annan hash, och kostnadsparametern ser till att det inte är möjligt att beräkna varje hash från början. Båda behövs, men ingen av dem måste vara hemliga.

Det är därför som funktionen fäster dem på hasen.

Kom ihåg att det spelar ingen roll vad ditt salt är, så länge det är unikt.

Nu, om du förstod vad saltet gör, då borde du veta att det är bättre att låta funktionen slumpmässigt generera en än att skriva in ditt eget ord. Även om den här funktionen tillhandahålls, vill du inte att alla dina haschar ska ha samma salt. Om de gör det, om någon lyckades bryta sig in i din databas, var det bara att beräkna bordet en gång. Eftersom de kommer att ha salt- och kostnadsnivå kan det ta en stund, men med tillräckligt med datorer, när de har bearbetat det, kommer de ha låst upp alla dina haschar. Som sådan är det mycket bättre att inte tilldela en och istället låta PHP slumpmässigt generera en.


cURL-tillägg

Hittills fanns det inget enkelt sätt att skicka mail via SMTP.

cURL är ett annat område där PHP-teamet har lagt till några spännande nya tillägg och uppdateringar. Från version 5.5 har vi nu stöd för FTP-direktiven, direktiv för att ställa in cookies, direktiv för SSL och konton och direktiver för bland annat SMTP och RTSP-protokoll. Det skulle ta för lång tid att diskutera dem alla, men för att se hela listan kan du se på sidan NYHETER.

Jag vill dock prata om en uppsättning speciellt som intresserade mig mest: SMTP-uppsättningen direktiv. Hittills fanns det inget enkelt sätt att skicka mail via SMTP. Du skulle antingen behöva ändra serverens sendmail-program för att skicka meddelanden via en SMTP-server, eller du måste ladda ner ett tredje part bibliotek - vilket inte är det bästa alternativet. Med de nya CURL-direktiven kan du prata direkt med en SMTP-server, till exempel Gmail, på bara några korta rader.

För att bättre förstå hur koden fungerar är det värt att lära sig lite om SMTP-protokollet. Vad som händer är att ditt skript ansluter till mail-servern, mail-servern bekräftar din anslutning och returnerar dig till sin information (t ex domän, programvara). Du måste då svara på servern med din adress. Att vara ett chattigt (men artigt) protokoll, hälsar SMTP dig så att du vet att den mottogs.

Vid denna tidpunkt är du redo att skicka kommandon. De kommandon som behövs är MAIL FROM och den RCPT TO; dessa kartor direkt till cURL-direktiven, CURLOPT_MAIL_FROM och CURLOPT_MAIL_RCPT, respektive. Du har bara en från adress, men du kan ange flera till adresser. När detta är klart kan du bara ringa kommandot, DATA, och börja skicka det aktuella meddelandet och meddelandehuvudet. För att avsluta överföringen måste du skicka en tom linje, följd av en period, följt av en annan blank linje. Dessa två sista delar (dvs DATA-kommandot och slutsekvensen) tas hand om av cURL, så vi behöver inte oroa oss för det.

Så, i PHP, allt vi behöver göra är att ange posten från och till riktlinjer och sedan skicka det aktuella meddelandet - allt inom cURL. För att göra saker verkligen enkla, ska jag skapa en klass som heter Gmail, som kommer att acceptera ett användarnamn / lösenord och meddelandedetaljerna, och det kommer att skicka e-postmeddelanden via ditt Gmail-konto.

Jag klistrar in hela klassen nedan, och sedan går vi igenom den linjen för rad, eftersom det mesta är kokkärl.

 klass Gmail privat $ mail; privat $ email; privat $ pass allmän funktion __construct ($ email, $ pass) $ this-> email = $ email; $ this-> pass = $ pass;  privat funktion mailGen () $ from = yield; $ till = utbyte; $ subject = yield; $ body = yield; utbyte "FRÅN: <" . $from . ">\ n "; ge" till: <" . $to . ">\ n "; ge" Datum: ". datum (" r ")." \ n "; ge" Ämne: ". $ ämne." \ n "; ge ut" \ n "; ge $ body; yield" ";  public function getLine () $ resp = $ this-> mail-> current (); $ this-> mail-> next (); returnera $ resp; public function send ($ till, $ ämne, $ body) $ this-> mail = $ this-> mailGen (); $ this-> mail-> send ($ this-> email); $ this-> mail-> send ($ till); $ this-> mail- > skicka ($ ämne); $ this-> mail-> send ($ body); $ ch = curl_init ("smtps: //smtp.gmail.com: 465"); curl_setopt ($ ch, CURLOPT_MAIL_FROM, "<" . $this->email. ">"); curl_setopt ($ ch, CURLOPT_MAIL_RCPT, array ("<" . $to . ">")); curl_setopt ($ ch, CURLOPT_USERNAME, $ this-> email); curl_setopt ($ ch, CURLOPT_PASSWORD, $ this-> passera); curl_setopt ($ ch, CURLOPT_USE_SSL, CURLUSESSL_ALL); // curl_setopt ($ ch, CURLOPT_VERBOSE , true), valfritt om du vill se transaktionen curl_setopt ($ ch, CURLOPT_READFUNCTION, array ($ this, "getLine")), returnera curl_exec ($ ch);

Förhoppningsvis var din reaktion på den här koden något i linje med "Wow, det är kort för ett komplett SMTP-genomförande!" Bara om det verkar komplicerat går vi över det. Vi börjar med att definiera tre privata variabler: en för meddelandegeneratorn, en för att lagra användarens e-post och en för att lagra sitt lösenord. Därefter har vi konstruktören, som lagrar e-post och lösenord för senare; Det här är så att vi kan skicka flera e-postmeddelanden utan att skriva in det här varje gång. De mailGen funktionen är en PHP 5.5-generator, som används för att utmata meddelandet enligt e-postprotokollet direkt i cURL. Anledningen till att detta behövs är att kommandot som används i cURL för att mata in data är avsett att läsa från en fil, linje för rad. Så, istället för att ha en extra variabel för att komma ihåg vilken linje vi hade, använde jag en generator som sparar sin position.

Nästa funktion används för att cykla genom generatorn. Vi kan inte ange generatorn direkt i cURL; Vi behöver en mellanhand. cURL fortsätter att ringa denna funktion tills det kommer till en tom linje. Därför returnerar den sista raden i generatorn en blank sträng.

Den sista funktionen i klassen är den som binder samman allt. Vi initierar först generatorn till den privata variabel som definierats tidigare. Därefter skickar vi generatorn all information som krävs och skapar en ny cURL-variabel. Vi har redan diskuterat CURLOPT_MAIL_FROM och CURLOPT_MAIL_RCPT; de kartlägger till motsvarande SMTP-kommandon. CURLOPT_MAIL_RCPT är en matris så att du kan ange flera adresser. Därefter måste vi lägga till credentials för att logga in på GMail. Jag lämnade det verbose alternativet där; uncomment det, om du vill se hela SMTP-transaktionen. De sista två raderna ställer bara in funktionen där CURL ska hämta data för meddelandet, och sedan returnerar vi resultaten.

Det är ett bra par linjer, men inget alltför komplicerat. För att använda denna funktion, skapa en ny instans av denna klass och ring sändningsfunktionen. Här är ett exempel på att skicka två e-postmeddelanden med följande:

 $ gmail = ny Gmail ("[email protected]", "lösenord"); $ gmail-> skicka ("[email protected]", "Subject of email", "Hello Guy, \ n Vad händer."); $ gmail-> send ("[email protected]", "Different Subject", "Viktigt meddelande.");

Bitar och Bobs

För att slutföra denna artikel kommer jag att gå över några av de mindre uppdateringarna till PHP 5.5.

En ganska cool sak är det extra stöd för konstant sträng / sträng-dereferencing. Vad det här betyder är att du kan komma åt enskilda tecken i en statisk sträng, som om strängen var en rad tecken. Ett snabbt exempel på detta är följande:

 echo "Hello World" [1]; // den här raden kommer att echo "e" echo ["one", "two", "three"] [2]; // denna echos "tre"

Därefter har vi till sist nyckelord. Detta läggs till i slutet av ett försök / fångstblock; vad det gör är att instruera PHP att, oavsett om försöket eller fångsten heter, vill du bearbeta till sist sektion. Det här är bra för situationer, när du vill hantera resultatet av ett försök / fångstutdrag. I stället för att upprepa kod i båda kan du bara sätta den "riskabla" delen i försök / fångstblocket och all behandling i slutligen blocket.

En annan användning som föreslagits av skaparen som bästa praxis är att sätta all uppringningskod i slutligen blocket. Detta kommer att se till att du exempelvis inte försöker stänga samma ström flera gånger (t ex koden kraschade och gick in i fångblocket efter stängning redan och du försöker stänga den igen).

Det sista som är värt att nämna är hur MySQL-tillägget kommer att avlägsnas i den här nya utgåvan. Du bör konvertera din kod till antingen mysqli eller PDO förlängningar istället. Även om det sedan länge anses vara ett antimönster, är det trevligt för PHP-laget att officiellt avlägsna det.

Medan det verkligen finns fler uppdateringar att gräva in, visar artiklarna i den här artikeln vad jag tycker är det viktigaste och spännande.


Slutsats

Tack för att du läser; Jag hoppas du har lärt dig lite! Som alltid, om du har några kommentarer eller frågor, hoppa in i konversationen nedan, och låt oss prata!