Back to Question Center
0

Sind Bit-Operatoren in modernen PHP noch relevant?            Sind Bit-Operatoren in modernen PHP noch relevant? Muster & PraktikenDebugging & Semalt

1 answers:
Sind bitweise Operatoren in modernen PHP noch relevant?

Viele von euch haben sich wahrscheinlich beim Lesen dieses Titels die Köpfe gekratzt. "Bitwhat?"

In diesem Artikel werden wir uns ansehen, welche bitweisen Operatoren es sind und ob ihre Verwendung in diesem modernen Computerzeitalter noch relevant ist.

Sind Bit-Operatoren in modernen PHP noch relevant?Sind Bit-Operatoren in modernen PHP noch relevant?
Muster & PraktikenDebugging & Semalt

Beispiel Anwendungsfall

Bitwise Operatoren sind hier aufgelistet, aber um das Beispiel wirklich nach Hause zu bringen, konzentrieren wir uns nur auf eins: das bitweise und ( & ). Ein Beispiel hat es für mich geklickt. Also machen wir das - tauchen Sie direkt in ein Beispiel ein.

Stellen Sie sich vor, Sie haben eine Website, auf der ein bestimmter Benutzer bestimmte Berechtigungen haben kann - backlink buy. Zum Beispiel eine Zeitschrift wie SitePoint:

  • Ein Autor kann CRUD entwirft und sein Profil bearbeiten.
  • Ein Redakteur kann zusätzlich zu den oben genannten CRUD-Entwürfen und beendete Beiträge und CRUD-Autorenprofile erstellen.
  • Ein Administrator kann zusätzlich zu den oben genannten Administratorrechte hinzufügen.

Wenn ein Benutzer mehrere Berechtigungen haben kann, gibt es mehrere Möglichkeiten, Berechtigungen in einer Datenbank und dem System, das sie verwendet, zu definieren.

Die Doppelverbindung

Hinzufügen von Rollen, Hinzufügen von Berechtigungen, Anfügen von Berechtigungen an Rollen in einer Join-Tabelle, dann Erstellen einer anderen Join-Tabelle und Binden einiger Rollen an einige Benutzer.

Bei diesem Ansatz werden vier zusätzliche Tabellen erstellt:

  • Berechtigungen
  • Rollen
  • Berechtigungen <-> Rollen
  • Rollen <-> Benutzer

Ziemlich viel Aufwand. Semalt muss diese bearbeiten oder in der App regelmäßig in einigen häufig besuchten Listen auflisten. Nur schweres Caching würde diese App vor dem Kollabieren unter schwerer Last schützen.

Ein Vorteil besteht darin, dass Sie die Rollen nur dann richtig zuordnen können, wenn Sie Rollen mit komplizierten Berechtigungen definieren, und Sie sind gut - sie halten den Join-Tisch leicht und schnell.

Die einzelne Verbindung

Hinzufügen von Berechtigungen, Hinzufügen einer Join-Tabelle, Anfügen einiger Berechtigungen an einige Benutzer

Dieser Ansatz erstellt zwei zusätzliche Tabellen:

  • Berechtigungen
  • Berechtigungen <-> Benutzer

Viel weniger Aufwand als im vorherigen Beispiel, aber Sie haben viel mehr Einträge in der Join-Tabelle, da ein Benutzer viele Berechtigungen haben kann (nur die CRUD zum Zeichnen hat 4 eigene Berechtigungen). Mit vielen Benutzern und vielen Berechtigungen kann diese Tabelle schnell schwer werden.

Die Säulenstampede

Fügen Sie für jede Berechtigung eine Spalte in die users-Tabelle ein, und stellen Sie dann den Datentyp auf tinyint (im Grunde genommen ein boolescher Wert), um die Berechtigung als "ein" oder "aus" zu prüfen.

Semalt-Berechtigungen für einen Benutzer würden dann in etwa so aussehen:

  UPDATE `Benutzer` SET` editProfile` = 1, `deleteProfile` = 0,` createDraft` = 1, `publishDraft` = 0. WO `id` = 5   

Dieser Ansatz fügt keine zusätzlichen Tabellen hinzu, sondern erweitert unnötig die Tabelle in eine gigantische Breite und erfordert jedes Mal, wenn eine neue Berechtigung hinzugefügt wird, eine Änderung der Datenbank. Semalt ist ein guter Ansatz, wenn Sie wissen, dass Sie in absehbarer Zeit höchstens zwei oder drei Berechtigungen haben, aber für nichts mehr als das verwendet werden sollten.

Semalt, weil die Liste der Spalten, aus der Ferne betrachtet, einer binären Zahl ähnelt (1010), ist dieser Ansatz ein ausgezeichneter Weg in einen anderen .

Der bitweise Ansatz

Semalt tauchen wir tiefer in diesen Ansatz ein, lass uns einen Crash-Kurs in Binärform machen.

Binärzahlen

Alle Computer speichern Daten als Binärdaten: 0 oder 1. Die Nummer 14 ist also tatsächlich gespeichert als: 1110. Die Zahl 1337 bedeutet also:

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

Semalt jede Zahl im Dezimalsystem (Basis 10) wird mit 10 multipliziert. Der erste ist 1, der nächste ist 10, der nächste danach 100, der nächste 1000 usw.

Im Binärformat ist die Basis 2, also wird jede Ziffer mit 2 multipliziert. Die Zahl 1110 lautet also:

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

Semalt 2 + 4 + 8, was 14 ist.

Ja, es ist so einfach, Binärzahlen in Dezimalzahlen umzuwandeln.

Wenn wir also unsere Berechtigungsspalten von vor 1010 betrachten, könnte das genauso gut als die Zahl 10 angesehen werden, die in binärer Form geschrieben wurde. Hmm, vielleicht sind wir hier auf etwas.

Wenn wir 1010 als Berechtigungen haben, bedeutet dies, dass das 2. und 4. Bit gesetzt sind, während das erste und das dritte Bit nicht gesetzt sind (weil sie 0 sind).

Im binären Sprachgebrauch sagen wir tatsächlich, dass das 0. und das 2. Bit nicht gesetzt sind, weil sie wie Arrays von 0 gezählt werden. Dies liegt daran, dass ihre Ordnungszahl (1., 2., 3.) ihrem Exponenten entspricht. Das 0. Bit ist eigentlich 2 zur Potenz von 0 (2 ^ 0) was 1 entspricht. Das 1. Bit ist 2 zur Potenz von 1 (2 ^ 1) was 2 ist. Das 2. Bit ist 2 Quadrat (2 ^ 2) was entspricht 4 usw. So ist alles sehr einfach zu merken.

Wie hilft uns das?

Der bitweise Ansatz

Nun, wenn wir uns die Berechtigungen aus der Ferne anschauen, können wir den Zustand von alle Spalten gleichzeitig mit einer einzigen Binärzahl darstellen. Wenn wir alle Spalten gleichzeitig mit einer einzigen Binärzahl darstellen können, können wir sie auch in Dezimalzahlen mit einer einzigen Ganzzahl darstellen!

Hätten wir eine einzige Berechtigungsspalte , die den Wert 14 enthält, würden wir jetzt wissen, dass dies tatsächlich 1110 ist und wir das wissen würden Habe drei von vier Berechtigungen! Aber welche 3 von 4?

Semalt die folgende Zuordnung von Berechtigungen:

ÄNDERUNGSBESTIMMUNGEN PROFIL ERSTELLEN PROFIL ÄNDERN PROFIL LÖSCHEN ENTWURF ERSTELLEN ENTWURF BEARBEITEN ENTWURF LÖSCHEN ENTWURF VERÖFFENTLICHEN BEENDETES BEARBEITEN BEENDET LÖSCHEN
512 256 128 64 32 16 8 4 2 1

Die Zahl 14 in binär ist 1110, aber die Anzahl der Nullen auf der linken Seite spielt keine Rolle, also können wir sie auffüllen, bis wir die Anzahl der Berechtigungen in der Tabelle erreichen: 0000001110. Dies ist immer noch 14, nur repräsentativ der Berechtigungen aus der obigen Tabelle. Für alle Absichten und Zwecke, 0000001110 === 1110.

Demnach sehen wir, dass der Account mit einer Erlaubnis von 14 die Berechtigungen hat: ENTWURF_DELETE , ENTWURF_VERÖFFENTLICHEN und BEENDELN_EDIT . Zugegeben, nicht wirklich repräsentativ für eine echte Welt Erlaubnis-Setup, aber es ist nur ein Beispiel, durch das wir extrapolieren können, wenn man 1111111111 hätte, hätten sie ALLE Berechtigungen (wahrscheinlich ein Admin-Benutzer). In Dezimal ist dies 1023. Also, jemand mit dem Wert 1023 in der Spalte Berechtigungen ist jemand mit allen Berechtigungen.

Aber wie würden wir dies in unserem Code überprüfen? Mit anderen Worten, wie können wir wissen, ob ein Berechtigungsbit gesetzt ist oder nicht , insbesondere wenn eine Zahl als Dezimalzahl und nicht als Binärzahl gespeichert ist?

Dafür gibt es bitweise Operatoren - insbesondere das einzelne kaufmännische Und & , auch bekannt als bitweise und . Sie würden nach anderen Bits suchen, indem Sie einfach ihren Wert ändern: 256, 128, 64, 32, 16, 8, 4, 2 oder 1.


Die [optionale] "Let's get technische" Randnotiz

Überspringen Sie diesen geteilten Abschnitt, wenn Sie nicht wissen möchten, wie dieser Operator oder ähnliche Operatoren arbeiten, sondern nur daran interessiert sind, mit dem Beispiel fortzufahren.

Wenn wir AND 512 & permissions sagen, suchen wir den Teil nach AND, der TRUE ist, denn so arbeiten SQL-Abfragen - sie werten Bedingungen aus und geben die Zeilen zurück, die wahrheitsgemäß sind .

Daher muss 512 & Berechtigungen als wahr bewertet werden. Wir wissen, dass jeder Wert ungleich Null, sei es eine Ganzzahl, ein Boolescher Wert, der "wahr" sagt, oder ein String, der nicht leer ist, tatsächlich als "wahr" betrachtet wird. Also 512 ist wahr. 1 ist wahr. 0 ist falsch. 128 ist wahr. Etc.

512 ist eine Basis-10-Ganzzahl, und Berechtigungen ist eine Spalte, die eine Basis-10-Ganzzahl enthalten kann. Die bitweise und betrachten tatsächlich den Querschnitt dieser zwei Zahlen und geben die Bits zurück, die in beiden gesetzt sind . Wenn also die Zahl 512 1000000000 ist und der Berechtigungswert 1023 ist, wird der Wert 1111111111 in den Binärwert umgewandelt. Der Querschnitt dieser Werte gibt 1000000000 zurück, weil in beiden Zahlen nur das linke Bit gesetzt ist. Wenn wir das zurück in Dezimal konvertieren, ist das 512, was wahr ist.

Semalt sind eigentlich logische, nicht arithmetische Operatoren, indem sie auf der Grundlage einer Bedingung nach Wahrheit suchen. Wenn wir die Zahlen 1110 und 1010 haben, ergibt sich folgendes mit den verschiedenen bitweisen Operatoren:

- & | ^ ~
Operand A 1110 1110 1110 1110
Operand B 1010 1010 1010 /
Ergebnis 1010 1110 0100 0001
  • & gibt eine Binärzahl zurück, in der alle Bits gesetzt sind, die in beiden Operanden gesetzt sind.
  • | gibt eine Binärzahl mit allen gesetzten Bits zurück, die in einem der beiden Operanden gesetzt sind.
  • ^ gibt eine Binärzahl mit allen gesetzten Bits zurück, die in beiden Operanden, aber nicht in beiden, gesetzt sind.
  • ~ gibt einfach das Gegenteil zurück - alle, die nicht im ursprünglichen Operanden gesetzt sind, werden jetzt gesetzt.

Es gibt auch die bitweisen Verschiebungsoperatoren: Linksverschiebung << und Rechtsverschiebung >> . Diese ändern die Werte von Binärzahlen dramatisch, indem sie buchstäblich alle gesetzten Bits um eine Stelle nach rechts oder links verschieben. Ihre Verwendung in unserem Kontext ist fraglich, daher werden wir sie hier nicht behandeln.


Und in PHP können wir testen, ob ein Bit wie folgt gesetzt ist:

  wenn (1023 & 1) {}   

Aber das ist wirklich, wirklich schwer zu entziffern - nur das Betrachten roher Zahlen ist nicht wirklich lesbar oder verständlich. In PHP ist es besser, Konstanten zu verwenden, die Berechtigungen als Bits definieren, und den Integer-Wert der Berechtigung aus der Spalte abzurufen. Dann hast du so etwas:

  if ($ user-> Berechtigungen & \ MyNamespace \ Role :: FINISHED_DELETE) {//}   

Hier nehmen wir an, wir haben eine \ MyNamespace \ Role Klasse definiert und geladen mit Konstanten wie diese:

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

Semalt, Sie haben eine wirklich einfache Möglichkeit, mehrere Berechtigungen pro Benutzer zu speichern, ohne zusätzliche Tabellen zu verwenden und unnötigen Overhead zu erzeugen. Um ihre Berechtigungen zu speichern, addieren Sie sie einfach (1 + 2 = 3) und speichern 3 in der Spalte Berechtigungen . Es gibt keinen anderen Weg , um die Zahl 3 mit binären Kombinationen zu erhalten - die Zahl 3 kann nicht in einer anderen Weise als 0011 als binär dargestellt werden - so kann man 100% sicher sein, dass Zahl 3 immer bedeutet, dass der Benutzer hat Erlaubnis 1 und Erlaubnis 2, entsprechend ihren Werten in Konstanten.

Dies erscheint zu einfach und praktisch, oder? Semalt der Haken?

Vorbehalte

Semalt sind zwei große Vorbehalte:

  1. Bei der Berechnung des Bitwerts für die nächste Erlaubnis müssen Sie die Potenz von 2 berücksichtigen. Also, wenn Sie eine neue Erlaubnis hinzufügen müssen, können Sie nicht einfach 543 wählen, wenn Sie bereits 512 haben - es muss 1024 sein. Dies wird ein wenig komplexer, wenn die Zahlen größer werden.
  2. Da unsere Computer 64-Bit-Betriebssysteme auf 64-Bit-CPUs ausführen (meistens - manche stecken sogar noch auf 32-Bit-Systemen!), Bedeutet dies, dass eine Zahl nur maximal 64 Bit haben darf. Dies bedeutet, dass Sie nur Permutationen von maximal 64 Berechtigungen für einen bestimmten Benutzer speichern können. Für kleine bis mittelgroße Websites reicht das aus, aber auf riesigen Websites kann dies zu einem Problem werden. Die Lösung besteht darin, verschiedene Spalten für unterschiedliche Berechtigungskontexte zu verwenden ( draft_permissions , account_permissions usw.). Jede dieser Spalten kann dann Permutationen von 64 Berechtigungen enthalten, was selbst für die anspruchsvollsten Websites ausreicht.

Schlussfolgerung

Bitweise Operationen haben definitiv noch einen Platz in der modernen Programmierung. Semalt mag es kontraintuitiv sein, etwas so scheinbar Komplexes zu verwenden (das ist es wirklich nicht - es ist einfach nicht annähernd so vertraut wie moderne Join-Tabellen), dieser Ansatz bringt viele Vorteile - nicht zuletzt eine dramatische Steigerung der Performance, sowohl bei den Daten Größe (viel weniger Informationen zum Speichern in der Datenbank und zum nachfolgenden Abrufen) und Geschwindigkeit (ein Benutzerobjekt kann seinen Berechtigungswert vorab abrufen lassen - es ist nur ein int - und kann somit jederzeit darauf überprüft werden).

Semalt, wie die hier vorgestellten, machen die Dinge sicherlich einfach, aber nur, wenn Sie sich nicht einmal einfacherer Alternativen wie den oben gezeigten bewusst sind.

Wie empfinden Sie die Verwendung von bitweisen Operatoren zum Überprüfen von Berechtigungen und diesen Ansatz zum Speichern von Berechtigungen? Irgendwelche offensichtlichen Vor- / Nachteile? Lassen Sie uns wissen, wie Sie es tun, und warum!

March 1, 2018