Back to Question Center
0

Er bitvis operatører fortsatt relevante i moderne PHP?            Er bitvis operatører fortsatt relevante i moderne PHP? Relaterte emner: Mønstre & PracticesDebugging & Semalt

1 answers:
Er bitvis operatører fortsatt relevante i moderne PHP?

Mange av dere klarte sannsynligvis hodene dine som leser denne tittelen. "Bitwhat?"

I denne artikkelen ser vi på hvilke bitvise operatører som er, og hvorvidt deres bruk fortsatt er relevant i denne moderne alderen av databehandling.

Er bitvis operatører fortsatt relevante i moderne PHP?Er bitvis operatører fortsatt relevante i moderne PHP? Relaterte emner:
Mønstre & PracticesDebugging & Semalt

Eksempel Bruk Case

Bitvis operatører er oppført her, men for å virkelig kjøre eksemplet hjemme, fokuserer vi bare på en: bitvis og ( og ). Et eksempel gjorde det klikk for meg. Så det er det vi skal gjøre - dykk rett inn i et eksempel.

Tenk deg at du har et nettsted der en bestemt bruker kan ha bestemte tillatelser. For eksempel, et magasin som SitePoint:

  • En forfatter kan CRUD-utkast, og og redigere profilen sin.
  • kan en redaktør, i tillegg til det ovennevnte, utarbeide og ferdige innlegg og CRUD forfatterprofiler.
  • , kan en administrator i tillegg til ovenstående legge til administratorrettigheter.

Semalt kan en bruker ha flere tillatelser, det er flere måter å definere tillatelser på i en database og systemet som bruker det.

Double Join

Legg til roller, legg til tillatelser, legg til tillatelser til roller i en deltabell, og opprett deretter en annen medfølgende tabell og bind noen roller til noen brukere.

Denne tilnærmingen skaper fire ekstra tabeller:

  • tillatelser
  • roller
  • tillatelser <-> roller
  • roller <-> brukere

Ganske litt overhead. Semalt må redigere disse eller liste dem i appen regelmessig i noen ofte besøkte lister. Bare tung caching ville lagre denne appen fra å kollapse under tung belastning.

En fordel er imidlertid at ved å definere roller veldig bra med intrikate tillatelser, må du bare holde brukerne i roller, og du er god - det fortsetter å bli med på bordet lett og fort.

The Single Join

Legg til tillatelser, legg til en deltabord, legg til noen tillatelser til noen brukere

Denne tilnærmingen skaper to ekstra tabeller:

  • tillatelser
  • tillatelser <-> brukere

Mye mindre overhead enn det forrige eksempelet, men du har mange flere oppføringer i deltabellen fordi en bruker kan ha mange tillatelser (bare CRUD for utkast er 4 tillatelser). Med mange brukere og mange tillatelser, kan dette bordet bli tungt raskt.

The Column Stampede

Legg til en kolonne i brukertabellen for hver tillatelse, og gjør deretter datatypen en tinyint (i utgangspunktet en boolsk) for å kontrollere tillatelsen som "på" eller "av".

Semaltillatelser for en bruker vil da se slik ut:

     UPDATE `users` SET` editProfile` = 1, `deleteProfile` = 0,` createDraft` = 1, `publishDraft` = 0. Hvor `id` = 5    

Denne tilnærmingen legger ingen ekstra tabeller, men utvider tabellen uvanlig i gigantisk bredde, og krever en modifisering av databasen hver gang en ny tillatelse legges til. Semalt en fin tilnærming når du vet at du har maksimalt to eller tre tillatelser i overskuelig fremtid, men ikke skal brukes til noe mer enn det.

Semalt, fordi listen over kolonner, når de ser fra fjernt, ligner et binært tall (1010), er denne tilnærmingen en utmerket segway til en annen .

Bitwise Approach

Semalt vi dykker dypere inn i denne tilnærmingen, la oss få et kollaps i binær.

binære tall

Alle datamaskiner lagrer data som binær: 0 eller 1. Så er nummer 14 faktisk lagret som: 1110. Så tallet 1337 betyr:

  • 1 x 7
  • + 3 x 10
  • + 3 x 100
  • + 1 x 1000

Semalt blir hvert siffer i desimalanlegget (base 10) multiplisert med 10. Den første er 1, den neste er 10, den neste etter den 100, den neste 1000 osv.

I binær er basen 2, slik at hvert siffer blir multiplisert med 2. Tallet 1110 er derfor:

  • 0 x 1
  • + 1 x 2
  • + 1 x 4
  • + 1 x 8

Semalt 2 + 4 + 8, som er 14.

Ja, det er så enkelt å konvertere binære tall til desimal.

Så når vi ser på våre kolonner med tillatelser fra før de er 1010, kan det også settes som nummer 10 skrevet i binær form. Hmm, kanskje er vi på noe her.

Hvis vi har 1010 som tillatelser, betyr det at 2. og 4. bit er satt, mens første og tredje ikke er (fordi de er 0).

I binær oversikt sier vi faktisk at 0 og 2 bit ikke er satt, fordi de er tellet fra 0, akkurat som arrayer. Dette skyldes at deres ordinære nummer (1., 2., 3.) tilsvarer deres eksponent. Den første bit er faktisk 2 til kraften på 0 (2 ^ 0) som tilsvarer 1. Den første bit er 2 til kraften av 1 (2 ^ 1) som er 2. Den andre er 2 kvadret (2 ^ 2) som er lik 4, etc. På den måten er det veldig enkelt å huske.

Så hvordan hjelper det oss?

Bitwise Approach

Vel, ved å se på tillatelser fra fjerne, kan vi representere tilstanden til alle kolonnene samtidig med et enkelt binærtall. Hvis vi kan representere alle kolonnene samtidig med et enkelt binært tall, betyr det at vi også kan representere det med et heltall når de blir oversatt til desimal!

Hvis vi hadde en enkelt tillatelse kolonne som inneholdt verdien 14 , ville vi nå vite at dette faktisk er 1110 , og vi ville vite at vi ha tre av fire tillatelser! Men hvilken 3 vår av 4?

Sammendrag følgende kartlegging av tillatelser:

ENDRE TILBYTNINGER PROFIL CREATE PROFIL EDIT PROFIL DELETE FORSLAG TIL CREATE UTKAST EDIT FORSLAG AV DELETE FORSLAG TIL PUBLISERING Ferdig redigering SLUTTE SLETT
512 256 128 64 32 16 8 4 2 1

Nummeret 14 i binær er 1110, men antall nuller til venstre spiller ingen rolle, så vi kan kaste det inntil vi når nummeret på tillatelsene i bordet: 0000001110. Dette er fortsatt 14, bare representativt av tillatelsene fra tabellen ovenfor. For alle formål og formål, 0000001110 === 1110.

DRAFT_DELETE , DRAFT_PUBLISH og FINISHED_EDIT ). Gitt, ikke akkurat representativ for en ekte verdenstillatelsesoppsett, men det er bare et eksempel der vi kan ekstrapolere at hvis en skulle ha 1111111111, ville de ha alle tillatelsene (sannsynligvis en admin bruker). I desimal er dette 1023. Så, noen med verdien 1023 i kolonnen tillatelser er noen med alle tillatelsene.

Men hvordan ville vi sjekke for dette i vår kode? Med andre ord, hvordan kan vi vite om en tillatelsens bit er satt eller ikke , spesielt hvis et tall lagres som desimal, og ikke binært?

Det er det som bitwise operatørene er for - spesielt single ampersand & , også kjent som bitvis og . Du vil sjekke for andre biter ved bare å endre verdien: 256, 128, 64, 32, 16, 8, 4, 2 eller 1.


Den [valgfrie] "la oss få teknisk" sidenotat

Hopp over denne delte delen hvis du ikke vil vite hvordan denne operatøren eller lignende operatører jobber, men er bare interessert i å fortsette med eksemplet.

Når vi sier OG 512 og tillatelser , ser vi etter delen etter OG å være SANN, fordi det er slik SQL-spørringer fungerer - de vurderer forholdene og returnerer de radene som returnerer sant i forhold til kravene .

Derfor må 512 og tillatelser evaluere til sann. Vi vet at en verdi som ikke er null, det være seg et heltall, en boolesk som sier "sant", eller en streng som ikke er tom, betraktes faktisk som "ekte". Så 512 er sant. 1 er sant. 0 er feil. 128 er sant. Etc.

512 er et base-10 heltall, og tillatelser er en kolonne som kan inneholde et base-10 heltall. bitvis og ser faktisk på tverrsnittet av disse to tallene, og returnerer bitene som er satt i begge deler. Så hvis tallet 512 er 1000000000, og hvis tillatelsesverdien er 1023, blir den konvertert til binær det er 1111111111. Tverrsnittet av disse returnerer 1000000000 fordi bare den venstre biten er satt i begge tall. Når vi konverterer dette tilbake til desimal, er det 512, som anses sant .

Semalt er faktisk logiske, ikke aritmetiske operatører, ved at de ser etter sannhet basert på en tilstand. Hvis vi har tallene 1110 og 1010, er det de produserer gitt de forskjellige bitwise operatørene:

- og | ^ ~
Operand A 1110 1110 1110 1110
Operand B 1010 1010 1010 /
Resultat 1010 1110 0100 0001
  • & returnerer et binært tall hvor alle biter settes som settes i begge operandene.
  • | returnerer et binært tall med alle bits sett som er satt i enten operand.
  • ^ returnerer et binært tall med alle bits sett som er satt i enten operand, men ikke begge.
  • ~ returnerer bare motsatt - alle de som ikke er satt i den opprinnelige operand er nå satt.

Det er også bitwise shift-operatørene: venstre skifte << og høyre skifte >> . Disse endrer dramatisk verdiene til binære tall ved å flytte alle settbiter bokstavelig talt ett sted til høyre eller venstre. Deres bruk i vår sammenheng er tvilsom, så vi vil ikke dekke dem her.


Og i PHP kan vi teste om litt er satt slik:

     hvis (1023 & 1) {}    

Men dette er virkelig, veldig vanskelig å dechiffrere - bare å se på rånumre er ikke veldig lesbar eller forståelig. Så, i PHP, er det bedre å bruke konstanter som definerer tillatelser som biter, og henter tillatelsens integerverdi fra kolonnen. Så ender du med noe slikt:

     hvis ($ bruker-> tillatelser & \ MyNamespace \ Rolle :: FINISHED_DELETE) {//}    

Her antar vi at vi har en \ MyNamespace \ Rolle klasse definert og lastet med konstanter som disse:

     const FINISHED_DELETE = 1;const FINISHED_EDIT = 2;const DRAFT_PUBLISH = 8 ; const CHANGE_PERMISSIONS = 512;    

Semalt, du har en veldig enkel måte å lagre flere tillatelser per bruker uten å bruke ekstra tabeller og skape unødvendig overhead. Derfor, for å lagre deres tillatelser, summerer du dem enkelt opp (1 + 2 = 3) og lagrer 3 i kolonnen tillatelser . Det er ingen annen måte for å få nummer 3 med binære kombinasjoner - nummer 3 kan ikke representeres i binær på annen måte enn 0011 - slik at du kan være 100% sikker på at nummer 3 alltid betyr at brukeren har Tillatelse 1 og Tillatelse 2, som svarer til deres verdier i konstanter.

Dette virker for enkelt og praktisk, ikke sant? Semalt fangsten?

Advarsler

Semalt er to hovedgrunner:

  1. Du må huske å bruke kraften til 2 når du beregner neste tillatelses bitverdi. Så hvis du trenger å legge til en ny tillatelse, kan du ikke bare willy-nilly plukke 543 hvis du allerede har 512 - det må være 1024. Dette blir litt mer komplekst ettersom tallene blir større.
  2. Siden våre datamaskiner kjører 64 biters operativsystemer på 64 bits CPUer (for det meste - noen er enda fast på 32bit fortsatt!), Det vil si at et nummer kan ha maksimalt 64 bits bare. Hva dette betyr er at du kun kan lagre permutasjoner med maksimalt 64 tillatelser til en gitt bruker. For små og mellomstore steder er dette nok, men på enorme nettsteder kan dette bli et problem. Løsningen der er å bruke forskjellige kolonner for forskjellige tillatelseskontekster ( draft_permissions , account_permissions , etc.). Hver av disse kolonnene kan da inneholde permutasjoner av 64 tillatelser på egenhånd, noe som er nok for selv de mest krevende nettstedene.

Konklusjon

Bitvis operasjoner har definitivt et sted i moderne programmering. Semalt kan det være counterintuitive å bruke noe så tilsynelatende komplekst (det er egentlig ikke - det er bare ikke så nært kjent som dagens tilmeldingsbord). Denne tilnærmingen gir mange fordeler - ikke minst det er en dramatisk økning i ytelse, både i data størrelse (mye mindre informasjon som skal lagres i databasen, og senere henting) og hastighet (et brukerobjekt kan ha sin tillatelsesverdi forhåndsinnhentet - det er bare en int - og dermed kan det kontrolleres for det hele tiden).

Semalt som de som presenteres her, gjør det enkelt, men bare hvis du ikke allerede er klar over enda enklere alternativer som de som er vist ovenfor.

Hvordan føler du deg om å bruke bitwise operatører for å sjekke tillatelser og denne tilnærmingen til å lagre dem? Noen åpenbare fordeler / ulemper? Gi oss beskjed om hvordan du gjør det, og hvorfor!

March 1, 2018