我想创建一个类并扩展一个
PHP类FilesystemIterator,如下面的代码所示.我定义一个方法hasFlag(),并测试它是否包含一个标志(我希望它像一些其他PHP函数,例如.glob),但结果总是不同于预期.那么我该如何解决这个问题呢?
class c extends FilesystemIterator { /* These are parent constants */ const CURRENT_AS_FILEINFO = 0 ; const KEY_AS_PATHNAME = 0 ; const CURRENT_AS_SELF = 16 ; const CURRENT_AS_PATHNAME = 32 ; const CURRENT_MODE_MASK = 240 ; const KEY_AS_FILENAME = 256 ; const NEW_CURRENT_AND_KEY = 256 ; const FOLLOW_SYMLINKS = 512 ; const KEY_MODE_MASK = 3840 ; const SKIP_DOTS = 4096 ; const UNIX_PATHS = 8192 ; public function __construct($flags) { $this->flags = $flags; } public function hasFlag($flag) { //How do I test $this->flags it contains a $flag??? return ($this->flags & $flag) ? true : false; } } $c = new c( c::CURRENT_AS_FILEINFO | c::KEY_AS_PATHNAME | c::CURRENT_AS_SELF | c::CURRENT_AS_PATHNAME | c::CURRENT_MODE_MASK | c::KEY_AS_FILENAME | c::NEW_CURRENT_AND_KEY | c::FOLLOW_SYMLINKS | c::KEY_MODE_MASK | c::SKIP_DOTS | c::UNIX_PATHS ); var_dump($c->hasFlag(c::CURRENT_AS_FILEINFO));
编辑1
为什么呢
var_dump( ((0 | 16 | 32 | 240 | 3840) & 0) == 0 ); //true var_dump( ((0 | 16 | 32 | 240 | 3840) & 32) == 32 ); //true var_dump( ((0 | 16 | 32 | 240 | 3840) & 240) == 240 ); //true var_dump( ((0 | 16 | 32 | 240 | 3840) & 1024) == 1024 ); //true?? var_dump( ((0 | 16 | 32 | 240 | 3840) & 2048) == 2048 ); //true?? var_dump( ((0 | 16 | 32 | 240 | 3840) & 3840) == 3840 ); //true
关于默认值和掩码
在FilesystemIterator
中有几个特殊的标志,被称为面具;他们将相关的多个标志(或在这种情况下是互斥的)组合在一起,不应该作为常规标志传递;下面是他们的二进制表示:
000x00xx0000 +--++--+ | | | +---- CURRENT_MODE_MASK | +-------- KEY_MODE_MASK
这些标志用于确定是否应该使用默认的key()和current()方法.两种方法的默认值在此定义:
const CURRENT_AS_FILEINFO = 0 ; const KEY_AS_PATHNAME = 0 ;
以下代码说明了如何测试它:
if ($flags & CURRENT_MODE_MASK == 0) { // CURRENT_AS_FILEINFO is used } else { // either CURRENT_AS_PATHNAME,CURRENT_AS_SELF or CURRENT_AS_PATHNAME is used } if ($flags & KEY_MODE_MASK == 0) { // KEY_AS_PATHNAME is used } else { // KEY_AS_FILENAME is used }
具有诸如 – > hasFlag()这样的功能的问题是您无法区分两个默认值,即要测试CURRENT_AS_FILEINFO还是KEY_AS_PATHNAME?你必须重新思考逻辑.
关于互斥旗帜
有几个标志不能一起使用,因为它们会导致未定义的行为;例如:
const CURRENT_AS_SELF = 16 ; const CURRENT_AS_PATHNAME = 32 ;
您不能为current()定义两种类型的行为,其中之一(或默认值)应该被使用.一组兼容的标志可以是:
$c = new c( c::CURRENT_AS_SELF | c::KEY_AS_FILENAME | c::FOLLOW_SYMLINKS | c::SKIP_DOTS | c::UNIX_PATHS );
关于扩展类
class c extends FilesystemIterator { public function hasFlag($flag) { $flags = $this->getFlags(); // use parent function here // logic here } }