重读PHP手册-2

重读php手册,记录一些有意思的问题。

for循环

它们都显示数字 1 到 10:

<?php
//example 1
for($i=1;$i<=10;$i++){
    print $i;
}
//example 2
for($i=1;;$i++){
    if($i>10){break;}
    print $i;
}
//example 3
$i=1;
for(;;){
    if($i>10){break;}
    print $i;
    $i++;
}
//example 4
for($i=1;$i<=10;print $i,$i++);

//example 每次加10
for($i=0; $i<=100; $i+=10){echo $i;} //显示: 0 10 20 30 4 50 60 70 80 90

 

Array数组

  • reset() - 函数将内部指针指向数组中的第一个元素,并输出
  • current() - 返回数组中的当前元素的值
  • end() - 将内部指针指向数组中的最后一个元素,并输出
  • next() - 将内部指针指向数组中的下一个元素,并输出
  • prev() - 将内部指针指向数组中的上一个元素,并输出
  • each() - 返回当前元素的键名和键值,并将内部指针向前移动
<?php
$people = array("Bill", "Steve", "Mark", "David");
echo current($people) . "<br>"; // 当前元素是 Bill
echo next($people) . "<br>";    // Bill 的下一个元素是 Steve
echo current($people) . "<br>"; // 现在当前元素是 Steve
echo prev($people) . "<br>";    // Steve 的上一个元素是 Bill
echo end($people) . "<br>";     // 最后一个元素是 David
echo prev($people) . "<br>";    // David 之前的元素是 Mark
echo current($people) . "<br>"; // 目前的当前元素是 Mark
echo reset($people). "<br>"; // 把内部指针移动到数组的首个元素,即 Bill
echo next($people) . "<br>";    // Bill 的下一个元素是 Steve
print_r (each($people)); // 返回当前元素的键名和键值(目前是 Steve),并向前移动内部指针

 

用 list() 给嵌套的数组解包

PHP 5.5 增添了遍历一个数组的数组的功能并且把嵌套的数组解包到循环变量中,只需将 list() 作为值提供。

例如:

<?php
$array = [
    [1, 2],
    [3, 4],
];
foreach ($array as list($a, $b)) {
    echo "A: $a; B: $b\n";
}

以上例程会输出:

A: 1; B: 2
A: 3; B: 4

 

list() 中的单元可以少于嵌套数组的,此时多出来的数组单元将被忽略:

<?php
$array = [
    [1, 2],
    [3, 4],
];

foreach ($array as list($a)) {
    // Note that there is no $b here.
    echo "$a\n";
}

以上例程会输出:

1
3

 

如果 list() 中列出的单元多于嵌套数组则会发出一条消息级别的错误信息:

<?php
$array = [
    [1, 2],
    [3, 4],
];
foreach ($array as list($a, $b, $c)) {
    echo "A: $a; B: $b; C: $c\n";
}

以上例程会输出:

Notice: Undefined offset: 2 in example.php on line 7
A: 1; B: 2; C: 

Notice: Undefined offset: 2 in example.php on line 7
A: 3; B: 4; C:

 

break

break 可以接受一个可选的数字参数来决定跳出几重循环。

同理,continue也一样,continue 接受一个可选的数字参数来决定跳过几重循环到循环结尾。默认值是 1,即跳到当前循环末尾。如: continue 1;

<?php
$arr = array('one', 'two', 'three', 'four', 'stop', 'five');
while (list (, $val) = each($arr)) {
    if ($val == 'stop') {
        break;    /* You could also write 'break 1;' here. */
    }
    echo "$val<br />\n";
}

/* 使用可选参数 */
$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />\n";
        break 1;  /* 只退出 switch. */
    case 10:
        echo "At 10; quitting<br />\n";
        break 2;  /* 退出 switch 和 while 循环 */
    default:
        break;
    }
}

 

declare结构

declare是PHP的流程控制结构,directive目前支持两个指令【ticks和encoding】,ticks的使用需配合register_tick_function函数(当然还有unregister_tick_function函数)使用

declare 结构用来设定一段代码的执行指令,它的语法结构如下:

  declare (directive) statement

  ticks参数表示运行多少语句调用一次register_tick_function的函数。

  register_tick_function函数定义了每个tick事件发生时的处理函数。

  那么什么是tick事件呢?tick是一个事件。

  tick事件在PHP每执行N条低级语句就发生一次,N由declare语句指定。

  可以用register_tick_function()来指定tick事件发生时应该执行的操作。

  问题又来了, 什么是低级语句呢?它包括:

  简单语句:空语句(就一个;号),return, break, continue, throw, goto, global, static, unset, echo,  内置的HTML文本,分号结束的表达式等均算一个语句。

  复合语句:完整的if/elseif, while, do...while, for, foreach, switch, try...catch等算一个语句。

       语句块:{} 括出来的语句块。

  最后特别的:declare块本身也算一个语句。

 

  看一个简单的例子:
  <?php
        function do_tick()
        {
            echo "<font color=red>do_tick </font>";
        }
        register_tick_function('do_tick');
        declare(ticks=1){
            for($i = 1; $i < 5; $i++){
                echo "<font color=blue>{$i}</font><br>";
            }
        }

  上面这段程序的运行结果:

1
do_tick do_tick 2
do_tick do_tick 3
do_tick do_tick 4
do_tick do_tick do_tick do_tick

  PHP declare控制符及ticks详细教程对结果解释下:

  第一次进入for循环,执行echo后执行第一次do_tick函数;第一次for循环结束后;执行第二次do_tick函数;

  循环四次......;

  第五次进行for循环,条件不满足,for循环结束,执行一次do_tick函数;

  declare本身也是一条语句,也要执行一次do_tick函数。

  从上可以看出,declare和ticks可以用来做调试或性能测试

 

Trait

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法

<?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}
trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}
class MyHelloWorld extends Base {
    use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>

以上例程会输出:

Hello World!

Example 另一个优先级顺序的例子

<?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}
class TheWorldIsNotEnough {
    use HelloWorld;
    public function sayHello() {
        echo 'Hello Universe!';
    }
}
$o = new TheWorldIsNotEnough();
$o->sayHello();
?>

以上例程会输出:

Hello Universe!

 

Iterator(迭代器)接口

Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。

迭代器模式给容器的应用带来以下好处:

1) 支持以不同的方式遍历一个容器角色。根据实现方式的不同,效果上会有差别。

2) 简化了容器的接口。

3) 对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。

由此也能得出迭代器模式的适用范围:

1) 访问一个容器对象的内容而无需暴露它的内部表示。

2) 支持对容器对象的多种遍历。

3) 为遍历不同的容器结构提供一个统一的接口(多态迭代)。

 

Iterator接口摘要如下:

Iterator extends Traversable {

    //返回当前索引游标指向的元素  

    abstract public mixed current ( void )  

    //返回当前索引游标指向的键  

    abstract public scalar key ( void )  

    //移动当前索引游标到下一元素  

    abstract public void next ( void )  

    //重置索引游标  

    abstract public void rewind ( void )  

    //判断当前索引游标指向的元素是否有效  

    abstract public boolean valid ( void )  

}

Example #1 基本用法

这个例子展示了使用 foreach 时,迭代器方法的调用顺序。

<?php
class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );  

    public function __construct() {
        $this->position = 0;
    }
    function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }
    function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }
    function key() {
        var_dump(__METHOD__);
        return $this->position;
    }
    function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }
    function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}

$it = new myIterator;
foreach($it as $key => $value) {
    echo $key.'--'.$value;
    echo "\n";
}
?>

以上例程的输出类似于:

string(18) "myIterator::rewind"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
0--firstelement

string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
1--secondelement

string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
2--lastelement

string(16) "myIterator::next"
string(17) "myIterator::valid"

从以上例子可以看出,如果执行valid返回false,则循环就此结束。

 

ArrayAccess(数组式访问)接口

提供像访问数组一样访问对象的能力的接口。

接口摘要

ArrayAccess {

/* 方法 */

abstract public boolean offsetExists ( mixed $offset )

abstract public mixed offsetGet ( mixed $offset )

abstract public void offsetSet ( mixed $offset , mixed $value )

abstract public void offsetUnset ( mixed $offset )

}

Example #1 Basic usage

<?php
class obj 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;
    }
}

$obj = new obj;
var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>

以上例程的输出类似于:

bool(true)
int(2)
bool(false)
string(7) "A value"
obj Object
(
    [container:obj:private] => Array
        (
            [one] => 1
            [three] => 3
            [two] => A value
            [0] => Append 1
            [1] => Append 2
            [2] => Append 3
        )

)

Table of Contents

  • ArrayAccess::offsetExists — 检查一个偏移位置是否存在
  • ArrayAccess::offsetGet — 获取一个偏移位置的值
  • ArrayAccess::offsetSet — 设置一个偏移位置的值
  • ArrayAccess::offsetUnset — 复位一个偏移位置的值

 

Countable接口 

让对象可以被用于count函数的能力 
定义如下: 

Countable {  

    abstract public function count ( )  

}  
例子: 

<?php  

class  Basket implements Countable{  

    private $fruits =array('apple','banna','pear','orange','watermelon');  

    public function count(){  

        return count($this->fruits);  

    }  

}  

$basket = new Basket();  

var_dump(count($basket));  //5

 

 

转载于:https://my.oschina.net/ganfanghua/blog/882571

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值