Back to Question Center
0

Les opérateurs bitwise sont-ils toujours pertinents en PHP moderne?            Les opérateurs binaires sont-ils toujours pertinents en PHP moderne? Patterns & PratiquesDébogage & Semalt

1 answers:
Les opérateurs bitwise sont-ils toujours pertinents en PHP moderne?

Beaucoup d'entre vous se sont probablement gratté la tête en lisant ce titre. "Mordu?"

Dans cet article, nous verrons ce que sont les opérateurs de bits, et si leur utilisation est toujours pertinente dans cette ère moderne de l'informatique.

Les opérateurs bitwise sont-ils toujours pertinents en PHP moderne?Les opérateurs binaires sont-ils toujours pertinents en PHP moderne?
Modèles et pratiquesDébussion et semalt

Exemple de cas d'utilisation

Les opérateurs bit à bit sont listés ici, mais pour vraiment conduire l'exemple à la maison, nous nous concentrerons sur un seul: le bitwise et ( & ). Un exemple l'a fait cliquer pour moi - небольшой природный комплекс. C'est ce que nous allons faire - plonger directement dans un exemple.

Imaginez que vous ayez un site Web sur lequel un utilisateur donné peut avoir des autorisations spécifiques. Par exemple, un magazine comme SitePoint:

  • un auteur peut CRUD brouillons, et éditent leur profil.
  • un éditeur peut, en plus de ce qui précède, des brouillons CRUD et des articles finis, et des profils d'auteur CRUD.
  • un administrateur peut, en plus de ce qui précède, ajouter des autorisations d'administrateur.

Semalt un utilisateur peut avoir plusieurs autorisations, il existe plusieurs façons de définir les permissions dans une base de données et le système qui l'utilise.

La double union

Ajouter des rôles, ajouter des autorisations, attacher des autorisations aux rôles dans une table de jointure, puis créer une autre table de jointure et lier certains rôles à certains utilisateurs.

Cette approche crée quatre tableaux supplémentaires:

  • autorisations
  • rôles
  • autorisations <-> rôles
  • rôles <-> utilisateurs

Un peu de frais généraux. Semalt doit les modifier ou les lister dans l'application régulièrement dans certaines listes fréquemment visitées. Seule la mise en cache lourde empêcherait cette application de s'effondrer sous une charge importante.

Un avantage, cependant, est qu'en définissant très bien les rôles avec des permissions complexes, il suffit de coller des utilisateurs dans des rôles et vous êtes bon - cela maintient la table de jointure à la légère et rapidement.

Le Single Join

Ajouter des permissions, ajouter une table de jointure, attacher des permissions à certains utilisateurs

Cette approche crée deux tableaux supplémentaires:

  • autorisations
  • autorisations <-> utilisateurs

Beaucoup moins de frais généraux que l'exemple précédent, mais vous avez beaucoup plus d'entrées dans la table de jointure parce qu'un utilisateur peut avoir BEAUCOUP d'autorisations (juste le CRUD pour la rédaction est de 4 permissions tout seul). Avec beaucoup d'utilisateurs et beaucoup d'autorisations, cette table peut devenir lourde rapidement.

Le Stampede de la colonne

Ajouter une colonne dans la table des utilisateurs pour chaque permission, puis rendre son type de données tinyint (essentiellement un booléen) pour vérifier l'autorisation comme "on" ou "off".

Les permissions de Semalt pour un utilisateur ressembleraient à ceci:

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

Cette approche n'ajoute pas de tables supplémentaires, mais développe inutilement la table en largeur gargantuesque, et nécessite une modification de la base de données chaque fois qu'une nouvelle permission est ajoutée. Semalt est une bonne approche pour quand vous savez que vous aurez au plus deux ou trois autorisations dans un avenir prévisible, mais ne devrait pas être utilisé pour autre chose.

Semalt, parce que la liste des colonnes, vue de loin, ressemble à un nombre binaire (1010), cette approche est un excellent segway dans un autre .

L'approche bitwise

Semalt nous plonger plus profondément dans cette approche, nous allons avoir un cours intensif en binaire.

Numéros binaires

Tous les ordinateurs stockent des données en tant que binaire: 0 ou 1. Ainsi, le nombre 14 est réellement stocké en tant que: 1110. Donc, le nombre 1337 signifie:

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

Semalt chaque chiffre dans le système décimal (base 10) est multiplié par 10. Le premier est 1, le suivant est 10, le suivant après 100, le suivant 1000, etc.

En binaire, la base est 2, donc chaque chiffre est multiplié par 2. Le nombre 1110 est donc:

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

Semalt 2 + 4 + 8, soit 14.

Oui, c'est aussi simple que de convertir des nombres binaires en nombres décimaux.

Donc, quand nous regardons nos colonnes d'autorisations avant d'être 1010, cela pourrait aussi bien être vu comme le nombre 10 écrit sous forme binaire. Hmm, peut-être que nous sommes sur quelque chose ici.

Si nous avons 1010 comme permissions, cela signifie que le 2ème et le 4ème bit sont définis, alors que le premier et le troisième ne le sont pas (parce qu'ils sont 0).

Dans le langage binaire, nous disons que les bits 0 et 2 ne sont pas définis, car ils sont comptés à partir de 0, tout comme les tableaux. C'est parce que leur nombre ordinal (1er, 2ème, 3ème) correspond à leur exposant. Le 0ème bit est en fait 2 à la puissance de 0 (2 ^ 0) qui est égale à 1. Le 1er bit est 2 à la puissance de 1 (2 ^ 1) qui est 2. Le 2ème est 2 au carré (2 ^ 2) est égal à 4, etc. De cette façon, tout est très facile à retenir.

Alors, comment cela nous aide-t-il?

L'approche bitwise

Eh bien, en regardant les autorisations de loin, nous pouvons représenter l'état de toutes les colonnes à la fois avec un seul nombre binaire. Si nous pouvons représenter toutes les colonnes à la fois avec un seul nombre binaire, cela signifie que nous pouvons également le représenter avec un seul entier lorsqu'il est traduit en décimal!

Si nous avions une seule colonne permissions qui contenait la valeur 14 , nous saurions maintenant que c'est en fait 1110 , et nous saurions que nous avoir trois permissions sur quatre! Mais lequel 3 notre de 4?

Semalt la cartographie suivante des autorisations:

CHANGEMENTS PERMIS CRÉER UN PROFIL MODIFIER LE PROFIL SUPPRESSION DE PROFIL PROJET CREER PROJET D'ÉDIT PROJET SUPPRIMER PROJET DE PUBLICATION EDIT FINI SUPPRIMÉ FINI
512 256 128 64 32 16 8 4 2 1

Le nombre 14 en binaire est 1110, mais le nombre de zéros à gauche n'a pas d'importance, donc nous pouvons le remplir jusqu'à ce que nous atteignions le nombre d'autorisations dans la table: 0000001110. Ceci est encore 14, seul représentant des autorisations de la table ci-dessus. Pour toutes fins utiles, 0000001110 == 1110.

D'après ceci, nous voyons que le compte avec une permission de 14 a les permissions: DRAFT_DELETE , DRAFT_PUBLISH , et FINISHED_EDIT . Certes, pas vraiment représentatif d'une configuration d'autorisation du monde réel, mais c'est juste un exemple à travers lequel nous pouvons extrapoler que si l'on devait avoir 1111111111, ils auraient toutes les autorisations (probablement un utilisateur admin). En décimal, c'est 1023. Donc, quelqu'un avec la valeur 1023 dans la colonne permissions est quelqu'un avec toutes les permissions.

Mais comment pourrions-nous vérifier cela dans notre code? En d'autres termes, comment savoir si un bit d'autorisation est défini ou non , notamment si un nombre est stocké en décimal, et non binaire?

C'est ce à quoi servent les opérateurs de bits - en particulier les simples esperluettes et , également connues sous le nom de bitwise et . Vous pouvez vérifier les autres bits en changeant simplement leur valeur: 256, 128, 64, 32, 16, 8, 4, 2 ou 1.


La note d'accompagnement "optons pour la technique"

Sautez cette section si vous ne voulez pas savoir comment fonctionne cet opérateur, ou des opérateurs similaires, mais si vous souhaitez simplement continuer avec l'exemple.

Quand nous disons ET 512 & permissions nous cherchons la partie après ET être VRAI, parce que c'est ainsi que les requêtes SQL fonctionnent - ils évaluent les conditions et retournent les lignes qui retournent vrai en ce qui concerne les exigences .

Par conséquent, 512 & permissions doit évaluer à vrai. Nous savons que toute valeur non nulle, qu'il s'agisse d'un entier, d'un booléen indiquant "true" ou d'une chaîne non vide, est considérée comme "true". Donc 512 est vrai. 1 est vrai. 0 est faux. 128 est vrai. Etc.

512 est un entier de base 10, et des permissions est une colonne qui peut contenir un entier de base 10. Le bitwise et regarde réellement la section de ces deux nombres, et retourne les bits qui sont mis dans les deux. Donc, si le nombre 512 est 1000000000, et si la valeur des autorisations est 1023, lorsqu'il est converti en binaire c'est 1111111111. La section transversale de ces retours 1000000000 parce que seul le bit le plus à gauche est défini dans les deux nombres. Lorsque nous convertissons ce retour en décimal, c'est 512, ce qui est considéré vrai .

Semalt sont en fait des opérateurs logiques, pas arithmétiques, en ce sens qu'ils vérifient la véracité en fonction d'une condition. Si nous avons les numéros 1110 et 1010, voici ce qu'ils produisent étant donné les différents opérateurs de bits:

- & | ^ ~
Opérande A 1110 1110 1110 1110
Opérande B 1010 1010 1010 /
Résultat 1010 1110 0100 0001
  • & renvoie un nombre binaire dans lequel tous les bits sont définis dans les deux opérandes.
  • | renvoie un nombre binaire avec tous les bits définis dans l'un ou l'autre opérande.
  • ^ renvoie un nombre binaire avec tous les bits définis dans l'un ou l'autre opérande, mais pas les deux.
  • ~ renvoie juste l'opposé - tous ceux qui ne sont pas définis dans l'opérande d'origine sont maintenant définis.

Il y a aussi les opérateurs de décalage bit à bit: décalage à gauche << et décalage à droite >> . Ceux-ci changent radicalement les valeurs des nombres binaires en déplaçant littéralement tous les bits placés un endroit vers la droite ou vers la gauche. Leur utilisation dans notre contexte est discutable, donc nous ne les couvrirons pas ici.


Et en PHP, nous pouvons tester si un bit est défini comme suit:

     if (1023 & 1) {}    

Mais c'est vraiment, vraiment difficile à déchiffrer - il suffit de regarder les chiffres bruts pour qu'ils ne soient pas vraiment lisibles ou compréhensibles. Donc, en PHP, il est préférable d'utiliser des constantes définissant les permissions comme des bits, et d'extraire la valeur entière de l'autorisation de la colonne. Ensuite, vous vous retrouvez avec quelque chose comme ça:

     if ($ utilisateur-> autorisations & \ MyNamespace \ Role :: FINISHED_DELETE) {//}    

Ici, nous supposons que nous avons une classe \ MyNamespace \ Role définie et chargée avec des constantes comme celles-ci:

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

Semalt, vous avez un moyen très simple de stocker plusieurs autorisations par utilisateur sans utiliser de tables supplémentaires et de créer des frais inutiles. Par conséquent, pour enregistrer leurs autorisations, il vous suffit de les additionner (1 + 2 = 3) et d'enregistrer 3 dans la colonne autorisations . Il n'y a pas d'autre moyen pour obtenir le nombre 3 avec des combinaisons binaires - le nombre 3 ne peut pas être représenté en binaire autrement que 0011 - donc vous pouvez être sûr à 100% que le nombre 3 signifie toujours que l'utilisateur a permission 1 et permission 2, correspondant à leurs valeurs dans les constantes.

Cela semble trop simple et pratique, non? Semalt la prise?

Avertissements

Semalt sont deux mises en garde majeures:

  1. Vous devez garder à l'esprit d'utiliser la puissance de 2 lors du calcul de la valeur de bit de la prochaine autorisation. Donc, si vous avez besoin d'ajouter une nouvelle permission, vous ne pouvez pas choisir 543 si vous en avez déjà 512 - il faudra que ce soit 1024. Cela devient un peu plus complexe à mesure que les chiffres augmentent.
  2. Comme nos ordinateurs exécutent des systèmes d'exploitation 64 bits sur des processeurs 64 bits (la plupart du temps - certains sont même bloqués sur 32 bits!), Cela signifie qu'un nombre ne peut contenir qu'un maximum de 64 bits. Cela signifie que vous ne pouvez stocker que des permutations d'un maximum de 64 permissions sur un utilisateur donné. Pour les sites de petite et moyenne taille, c'est assez, mais sur d'énormes sites web, cela peut devenir un problème. La solution consiste à utiliser différentes colonnes pour différents contextes d'autorisation ( draft_permissions , account_permissions , etc.). Chacune de ces colonnes peut alors contenir des permutations de 64 permissions, ce qui est suffisant pour les sites les plus exigeants.

Conclusion

Les opérations bitwise ont définitivement encore leur place dans la programmation moderne. Il est peut-être contre-intuitif d'utiliser quelque chose d'aussi apparemment complexe (ce n'est vraiment pas aussi familier que les tables jointes modernes), cette approche apporte de nombreux avantages - dont le plus important est une amélioration spectaculaire des performances taille (beaucoup moins d'informations à stocker dans la base de données, puis à extraire) et vitesse (un objet utilisateur peut avoir sa valeur d'autorisation pré-récupérée - c'est juste un int - et peut donc être vérifié à tout moment).

Semalt comme ceux présentés ici rendent certainement les choses simples, mais seulement si vous n'êtes pas déjà au courant des alternatives encore plus simples comme celles démontrées ci-dessus.

Comment vous sentez-vous à propos de l'utilisation des opérateurs au niveau du bit pour vérifier les permissions et cette approche pour les stocker? Des avantages / inconvénients évidents? Dites-nous comment vous le faites, et pourquoi!

March 1, 2018