这个按位AND运算符的目的是什么?

时间:2014-12-16 09:22:59

标签: php mysql

代码是cms的基本php代码,它读取Mysql内容以基于三种不同的方法呈现网页,按id,名称或特殊类型(索引页面,站点地图页面......)。但我可以&#39 ;了解这一行" $ r = dbRow("从特殊& $ v限制1"的页面中选择*); "什么是按位AND应该做什么?

<?php
class Page{
    static $instances             = array();
    static $instancesByName     = array();
    static $instancesBySpecial   = array();
    function __construct($v,$byField=0,$fromRow=0,$pvq=0){
        # byField: 0=ID; 1=Name; 3=special
        if (!$byField && is_numeric($v)){ // by ID
            $r=$fromRow?$fromRow:($v?dbRow("select * from pages where id=$v limit 1"):array());
        }
        else if ($byField == 1){ // by name
            $name=strtolower(str_replace('-','_',$v));
            $fname='page_by_name_'.md5($name);
            $r=dbRow("select * from pages where name like '".addslashes($name)."' limit 1");
        }
        else if ($byField == 3 && is_numeric($v)){ // by special
            $fname='page_by_special_'.$v;
            $r=dbRow("select * from pages where special&$v limit 1");
        }
        else return false;
        if(!count($r || !is_array($r)))return false;
        if(!isset($r['id']))$r['id']=0;
        if(!isset($r['type']))$r['type']=0;
        if(!isset($r['special']))$r['special']=0;
        if(!isset($r['name']))$r['name']='NO NAME SUPPLIED';
        foreach ($r as $k=>$v) $this->{$k}=$v;
        $this->urlname=$r['name'];
        $this->dbVals=$r;
        self::$instances[$this->id] =& $this;
        self::$instancesByName[preg_replace('/[^a-z0-9]/','-',strtolower($this->urlname))] =& $this;
        self::$instancesBySpecial[$this->special] =& $this;
        if(!$this->vars)$this->vars='{}';
        $this->vars=json_decode($this->vars);
    }
    function getInstance($id=0,$fromRow=false,$pvq=false){
        if (!is_numeric($id)) return false;
        if (!@array_key_exists($id,self::$instances)) self::$instances[$id]=new Page($id,0,$fromRow,$pvq);
        return self::$instances[$id];
    }
    function getInstanceByName($name=''){
        $name=strtolower($name);
        $nameIndex=preg_replace('#[^a-z0-9/]#','-',$name);
        if(@array_key_exists($nameIndex,self::$instancesByName))return self::$instancesByName[$nameIndex];
        self::$instancesByName[$nameIndex]=new Page($name,1);
        return self::$instancesByName[$nameIndex];
    }
    function getInstanceBySpecial($sp=0){
        if (!is_numeric($sp)) return false;
        if (!@array_key_exists($sp,$instancesBySpecial)) $instancesBySpecial[$sp]=new Page($sp,3);
        return $instancesBySpecial[$sp];
    }
}

1 个答案:

答案 0 :(得分:3)

pages.special似乎包含bit field(也就是说,其值中的每个位位置都会标记某些特定于应用程序的属性)。

然后,要查找具有某些属性的记录,可以执行按位AND操作,并且只有相同位置时,结果中的所需“掩码”位位置才会设置中设置值和掩码。一个2位值的完整真值表如下所示:

+---------+------+------------+
|  value  | mask | value&mask |
+---------+------+------------+
|    0b00 | 0b00 |       0b00 |
|    0b01 | 0b00 |       0b00 |
|    0b10 | 0b00 |       0b00 |
|    0b11 | 0b00 |       0b00 |
|    0b00 | 0b01 |       0b00 |
|    0b01 | 0b01 |       0b01 |
|    0b10 | 0b01 |       0b00 |
|    0b11 | 0b01 |       0b01 |
|    0b00 | 0b10 |       0b00 |
|    0b01 | 0b10 |       0b00 |
|    0b10 | 0b10 |       0b10 |
|    0b11 | 0b10 |       0b10 |
|    0b00 | 0b11 |       0b00 |
|    0b01 | 0b11 |       0b01 |
|    0b10 | 0b11 |       0b10 |
|    0b11 | 0b11 |       0b11 |
+---------+------+------------+

例如,假设最低位是相应页面“只读”的标志;并且页面“需要审核”的下一位 - (十进制)2或0b10的值将指示该页面不是只读但 >需要审核。因此,要找到 只读或需要审核的所有页面,可以这样做:

SELECT * FROM pages WHERE (special & 0b11) != 0

因为MySQL没有真正的布尔类型(但是将零视为false而非零视为true),过滤器表达式可以缩写为:

SELECT * FROM pages WHERE special & 0b11

我们也可以用十进制表示掩码,而不是二进制表格:

SELECT * FROM pages WHERE special & 3

并且,如果需要,请在查询中应用LIMIT(尽管在没有ORDER BY子句的情况下,结果是不确定的):

SELECT * FROM pages WHERE special&3 LIMIT 1

鉴于这是我们必须使用的所有内容(来自您展示的代码),我们只能说以下内容:

该查询从pages表中选择一个不确定记录的所有列,其中special的值至少有一个与掩码中设置的相同位$v }。

由于special$v的语义(以及它们中的位位置)是特定于应用程序的,因此如果不对您的应用程序有更深入的了解,就不可能再说些什么。

请注意,虽然紧凑,但在位字段上使用掩码进行过滤是不可靠的 - 所以这往往是非常糟糕的数据库设计。