Après la lecture de la source intéressante de malalam :
http://www.phpcs.com/codes/SQUELETTE-GESTION-DROITS_48756.aspx
J'ai voulu expérimenter également la possibilité de gérer les bits.
Le contexte est le même : j'ai une classe qui peut avoir plusieurs variables avec deux états (on/off) avec le besoin de vérifier que les états se croisent.
Un utilisateur qui aurait un ensemble de droits serait le parfait exemple.
Deux choses sont traités dans ma proposition - la première étant la gestion des bits, la seconde étant le moyen d'encapsuler les propriétés (puis de les exploiter).
Regardez le code pour plus de détails.
Source / Exemple :
<?php
/**
- Classe de gestion des bits
- /
abstract class byte {
private $value;
private $const;
public function __construct($value = 0) {
$this->value = $value;
}
public function set($flag, $value) {
if ($value) {
// SET BIT 1
$this->value = $this->value | $flag;
} else {
// SET BIT 0
$this->value = $this->value & ~$flag;
}
}
public function get($flag) {
return (($this->value & $flag) == $flag);
}
public function get_enum() {
if (!$this->const) {
$reflect = new ReflectionClass(get_class($this));
$this->const = $reflect->getConstants();
}
return $this->const;
}
public function __get($key) {
$c = $this->get_enum();
if (isset($c[$key])) {
return $this->get($c[$key]);
} else throw new Exception('Definition not found');
}
public function __set($key, $value) {
if (!is_bool($value)) throw new Exception('Boolean value expected !');
$c = $this->get_enum();
if (isset($c[$key])) {
return $this->set($c[$key], $value);
} else throw new Exception('Definition not found for '.$key);
}
public function __call($func, $args) {
$action = substr($func, 0, 3);
$key = strtolower(substr($func, 3));
$c = $this->get_enum();
if ($action == 'can') {
if (isset($c[$key])) {
return $this->get($c[$key]);
} else throw new Exception('Definition not found for '.$key);
} else if($action == 'set') {
if (isset($c[$key])) {
if (isset($args[0])) {
if (is_bool($args[0])) {
return $this->set($c[$key], $args[0]);
} else {
throw new Exception('Boolean value expected !');
}
} else {
return $this->set($c[$key], true);
}
} else throw new Exception('Definition not found for '.$key);
} else throw new Exception('Undefined function '.$func);
}
}
/**
class userRights extends byte {
const read = 1; // 001
const write = 2; // 010
const delete = 4; // 100
const admin = 7; // 111
}
/**
- Instanciation avec valeurs par défaul
- /
$foo = new userRights(
userRights::read |
userRights::write |
userRights::delete
);
// MANIPULATION
$foo->write = false;
$foo->setRead(false);
$foo->setRead();
// AFFICHAGE
echo 'Read : '.$foo->read.'<hr />';
echo 'Write : '.$foo->write.'<hr />';
echo 'Delete : '.$foo->canDelete();
?>
Conclusion :
Le premier avantage à utiliser cette méthode d'encapsultation est que vous définissez les constantes (pas de collision de noms possible) et vous exploitez directement les bits à travers des fonctions encapsulées.
Donc source utilisable par tout le monde :)
Regardez le fichier example.php pour voir comment c'est simple d'utilisation.