Sergio Álvarez (xergio)

Escrito 426

Trabajar con operadores bitwise en PHP

Acabo de hacer una chapucilla para trabajar con operadores bitwise en PHP (aquí ejemplos). Lo quiero por ejemplo para marcar los estados de una conexión, permisos de un usuario, y cosas así que viene bien controlar con flags. La clase que he hecho es esta:

class Bitwise {

  private $bw;
  private $firstBw;

  // valor inicial del resultado
  public function __construct($init = null) {
    if (gettype($init) === gettype($this))
      $this->bw = $init->get(); // puedo pasar un objeto del mismo tipo.
    else if (is_numeric($init))
      $this->bw = $init; // o un valor entero
    else
      $this->bw = 0; // y sino lo inicializo a 0, sin flags.
      
    $this->firstBw = $this->bw;
  }

  private function handle($newval) {
    $tmp = $this->bw;
    $this->bw = $newval;
    return $tmp == $this->bw;
  }
  
  private function arg_flags($argv) {
    $tmp = 0;
    foreach ($argv as $arg) $tmp |= $arg;
    return $tmp;
  }

  // añado un flag. Devuelve true o false si ha cambiado el resultado o no.
  public function add() {
    return $this->handle( $this->bw | $this->arg_flags(func_get_args()) );
  }

  // quito un flag. Devuelve true o false si ha cambiado el resultado o no.
  public function remove($flag) {
    return $this->handle( $this->bw & ~$this->arg_flags(func_get_args()) );
  }

  // compruebo si hay un flag en el resultado.
  public function has() {
    return ($this->bw & $this->arg_flags(func_get_args())) ? true: false;
  }

  // obtengo el resultado
  public function get() {
    return $this->bw;
  }
  
  // pone a 0 el resultado.
  public function reset() {
    $this->bw = $this->firstBw;
  }
}

Un ejemplo básico sería el de dar permisos a un usuario. Teniendo la clase cargada, con un require/include, o directamente en el código donde pongamos nuestro script, podemos hacer una bateria de pruebas como esta:

// tipos de acciones
define('LISTAR', 1);
define('EDITAR', 2);
define('BORRAR', 4);
define('CREAR', 8);

echo "nINSTANCIASn";

// intancia por defecto
$test1 = new Bitwise();
var_dump($test1);

// instancia predefinida
$test2 = new Bitwise(5);
var_dump($test2);

// instancia absurda
$test3 = new Bitwise('hola');
var_dump($test3);

// instancia "copia"
$test4 = new Bitwise($test2);
var_dump($test4);

echo "nTESTSn";

// añadimos un par de flags por separado
$test1->add(LISTAR);
$test1->add(EDITAR);
$test1->add(CREAR);
var_dump($test1);

// lo mismo pero del tirón
$test1->reset(); // reinicio el resultado anterior
$test1->add(LISTAR | EDITAR | CREAR);
var_dump($test1);

// otra vez pero con varios argumentos, se pueden alternar los dos métodos
$test1->reset();
$test1->add(LISTAR, EDITAR, CREAR);
var_dump($test1);

// reasigno un flag, el resultado no varía (como es normal)
$test1->add(EDITAR);
var_dump($test1);

// pregunto si está añadido el flag, igualmente se pueden pasar varios como antes
var_dump($test1->has(EDITAR));

// quito flags, método similar
$test1->remove(LISTAR);
var_dump($test1);

// quito varios, el que no existe pasa de él
$test1->remove(LISTAR | EDITAR);
var_dump($test1);

// pregunto de nuevo por flags alternando métodos, si alguno existe será true
var_dump($test1->has(LISTAR, EDITAR, BORRAR | CREAR));

Espero no tener que volver a "estudiarme" este tema... con esto ya me da igual cómo funcione, simplemente lo reutilizaré.

No hay comentarios aun

Deja un comentario

Pulsa en los títulos para ver información sobre cómo comentar.

Autocompletado de nicks

Todos los campos del formulario son opcionales menos el del PIN.

Usa el tabulador para autocompletar los nicks de otros comentaristas.

Si escribes @ y pulsas la tecla tabulador varias veces podrás recorrer la lista de nicks usados

Y si escribes # (almoadilla) y número (Ej.: #5) se substituirá directamente el nick del comentario correspondienmte al pulsar el tabulador.

Tags HTML permitidos

Tags: a, strong, b, em, u, code, cite.

El tag a admite la propiedad href="..." para indicar la dirección.

Los tags también tienen autocompletado (al igual que los nicks). Para usarlos se pone por ejemplo strong + TABULADOR.

Formulario para comentar

Cargando...

Todo el contenido bajo el dominio XERGIO.NET está sujeto a la licencia Creative Commons con las condiciones BY-SA. Web estandarizada en XHTML 1.0, CSS 2, RSS 2 y Atom 1.0.