对于MySQL应该也不是很陌生吧,我常常爱犯的以错误就是执行mysli_qurey()后就使用数据,忘记返回的是结果集了。而对于lSELECT,、SHOW, DESCRIBE 、 EXPLAINmysql_query返回的是mysqli_result object,也就是结果集对象;对于其他的mysql_query返回bool值,我在想为啥一个对象可以遍历呢,查看:
mysqli_result implements Traversable {
/* Properties */
int $current_field ;
int $field_count;
array $lengths;
int $num_rows;
/* Methods */
bool data_seek ( int $offset )
mixed fetch_all ([ int $resulttype = MYSQLI_NUM ] )
mixed fetch_array ([ int $resulttype = MYSQLI_BOTH ] )
array fetch_assoc ( void )
object fetch_field_direct ( int $fieldnr )
object fetch_field ( void )
array fetch_fields ( void )
object fetch_object ([ string $class_name = "stdClass" [, array $params ]] )
mixed fetch_row ( void )
bool field_seek ( int $fieldnr )
void free ( void )
}
mysqli_result是实现Traversable接口,手册是这样说的:
Iterator support was added, as mysqli_result now implements Traversable.
//因为mysqli现在实现了Traversable ,因此迭代被支持
所以查询返回的结果集对象能被遍历。
Traverseable介绍
这个接口没有任何方法,检测一个类是否可以使用 foreach 进行遍历的接口。他是Iterator的父接口,所以实现iterator的方法的类可以进行迭代。最底层的,这个接口一般不会去实现它。
任何需要实现Traversable接口的用户自定义类都必须通过实现从Traversable接口派生的用户自定义接口来做到这一点, IteratorAggregate 或 Iterator 即是它派生的接口。
if((new B()) instanceof Traversable){
foreach () ...
}
IteratorAggregate介绍
IteratorAggregate接口(是用来将Iterator接口要求实现的5个方法委托给其他类(比如ArrayIterator)来实现)。这让你可以在类的外部实现迭代功能.并允许重新使用常用的迭代器方法,而不是在编写的每个可迭代类中重复使用这些方法。
IteratorAggregate extends Traversable { //实现该方法时,必须返回一个实现了Iterator接口的类的实例 abstract public Traversable getIterator ( void )
}
其中getIterator 方法返回值必须是能遍历或实现Iterator接口(must be traversable or implement interface Iterator)。SPL还提供了一些专门用来与IteratorAggregate接口一起使用的内置迭代器。使用这些迭代器意味着只需要实现一个方法并实例化一个类就可以使对象可以迭代访问了。
class myData implements \IteratorAggregate {
public $property1 = "Public property one";
public $property2 = "Public property two";
public $property3 = array([1,23,4],4,5); public function __construct() {
$this->property4 = "last property";
}
//实现这个方法
public function getIterator() {
return new ArrayIterator($this);
}
} $obj = new myData; foreach($obj as $key => $value) {
var_dump($key, $value);
echo "\n";
}
来说说相关的接口吧
ArrayAccess
使一个对象可以当数组用,数组式访问接口(我试了遍历它不行)。
class ImplementArrayAccess implements ArrayAccess
{
private $container = array(); public function __construct()
{
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
} public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
} public function offsetExists($offset)
{
return isset($this->container[$offset]);
} public function offsetUnset($offset)
{
unset($this->container[$offset]);
} public function offsetGet($offset)
{
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
$datas = new ImplementArrayAccess();
$datas['four'] = 4;
unset($datas['three']);
print_r($datas);
结果
ImplementArrayAccess Object
(
[container:ImplementArrayAccess:private] => Array
(
[one] => 1
[two] => 2
[four] => 4
) )
ArrayIterator
这个迭代器允许在遍历数组和对象时删除和更新值与键
定义的接口:
ArrayIterator implements ArrayAccess , SeekableIterator , Countable , Serializable {
/* 方法 */
public void append ( mixed $value )
public void asort ( void )
public __construct ([ mixed $array = array() [, int $flags = 0 ]] )
public int count ( void )
public mixed current ( void )
public array getArrayCopy ( void )
public void getFlags ( void )
public mixed key ( void )
public void ksort ( void )
public void natcasesort ( void )
public void natsort ( void )
public void next ( void )
public void offsetExists ( string $index )
public mixed offsetGet ( string $index )
public void offsetSet ( string $index , string $newval )
public void offsetUnset ( string $index )
public void rewind ( void )
public void seek ( int $position )
public string serialize ( void )
public void setFlags ( string $flags )
public void uasort ( string $cmp_function )
public void uksort ( string $cmp_function )
public string unserialize ( string $serialized )
public bool valid ( void )
}
例子:
$fruits = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum" => "nah, not me"
);
$obj = new ArrayIterator( $fruits );
var_dump($obj); foreach ($obj as $item){
echo $item;
}
ArrayObject
也是让对象可以当着数组来使用
接口
ArrayObject implements IteratorAggregate , ArrayAccess , Serializable , Countable {
/* 常量 */
const integer STD_PROP_LIST = 1 ;
const integer ARRAY_AS_PROPS = 2 ;
/* 方法 */
public __construct ([ mixed $input = [] [, int $flags = 0 [, string $iterator_class = "ArrayIterator" ]]] )
public void append ( mixed $value )
public void asort ( void )
public int count ( void )
public array exchangeArray ( mixed $input )
public array getArrayCopy ( void )
public int getFlags ( void )
public ArrayIterator getIterator ( void )
public string getIteratorClass ( void )
public void ksort ( void )
public void natcasesort ( void )
public void natsort ( void )
public bool offsetExists ( mixed $index )
public mixed offsetGet ( mixed $index )
public void offsetSet ( mixed $index , mixed $newval )
public void offsetUnset ( mixed $index )
public string serialize ( void )
public void setFlags ( int $flags )
public void setIteratorClass ( string $iterator_class )
public void uasort ( callable $cmp_function )
public void uksort ( callable $cmp_function )
public void unserialize ( string $serialized )
}
看着似乎ArrayObject与ArrayIterator功能相似,但他们继承的接口不同,