细数php里的那些“坑”

Part 1  Grammer

尽管PHP的语法已经很松散,写起来很“爽”。但是对于学过 Java 的“完全面向对象程序员“来说,PHP程序设计语言里,还是有一些的坑的。下面请让我来盘点一下。

 

Parse error: syntax error, unexpected T_STRING, expecting T_FUNCTION in......

  错误原因:在PHP语法中,声明任何函数,函数名的前面需要 function 关键字。

<?php
//错误代码如下
class Test{
  __construct(){
    echo 'I am construction!';    
  }    
}

  正确示例:每一次声明函数(方法),都要写上“function”这个关键字。无论您想声明的是 __construct()这类魔术方法,还是自定义函数,都逃不出 function 的手掌心。

<?php
class Test{
  //正确代码如下
    function __construct(){
        echo 'I am construction!';
    }
}

 

PHP Fatal error:  Class Service_Page_Statistic_ZhiziBase contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Service_Page_Statistic_ZhiziBase::executeHook) in /home/map/odp_wmaudit/app/wmaudit/models/service/page/statistic/ZhiziBase.php on line 18

 

 

Fatal error: Access to undeclared static property: ......

   错误原因:self::只能指向静态属性,而指向非静态属性只能用 $this->。

<?php
//错误代码
class Person{
    function __construct($name){
        self::$name = $name;
    }
    private $name;
}

$paul = new Person('paul');

  正确方法:self::指向静态属性,$this->指向非静态属性。

<?php
//正确代码 $this
class Person{
    function __construct($name){
        $this->$name = $name;
    }
    private $name;
}

$paul = new Person('paul');

 

<?php
//正确代码 self::
class Person{
    function setBirthday($date){
        self::$birthday = $date;
    }
    static private $birthday;
}

$paul = new Person();
$paul->setBirthday('1990-01-01');

 

Fatal error: Cannot redeclare A::__construct() in......

  错误原因:PHP不支持函数重载

  解决方法:使用PHP内置函数 func_num_args() 、func_get_arg() 、func_get_args()来模拟实现OOP的函数重载

<?php
class Test{
    function __construct(){
        switch(func_num_args()){
            case 0:
                echo 'no argument';
            default:
                echo 'the number of arguments is '.func_num_args(). '<br />';
                $argumentArray = func_get_args();
                //遍历方法一
                foreach($argumentArray as $key => $value){
                    echo 'the No'. $key. ' argument is '. $value. '<br />';
                }
                echo '<br />';
                //遍历方法二
                for($i=0; $i<func_num_args(); $i++){
                    echo 'the No'. $i. ' argument is '. func_get_arg($i). '<br />';
                }
        }
        echo '<hr />';
    }
}

new Test();
new Test(1);
new Test(1,2,3);

 

 Warning: file_get_contents(0): failed to open stream: No such file or directory in

  错误原因:字符串相加结果“意外”等于“0”。

  解决方法1:“点”操作符(.)连接字符串。

<?php

$url = "http://op.juhe.cn/onebox/train/query?";
$param = "name=Tank&age=22";

$data = file_get_contents( $url. $param );

 

  解决方法2:使用PHP内置函数 implode() 将数组连接成字符串。  

<?php

$url = "http://op.juhe.cn/onebox/train/query?";
$param = "name=Tank&age=22";

$url = implode('', array($url, $param));
$data = file_get_contents( $url );

 

PHP Fatal error:  Class ...... contains 1 abstract method and must therefore be declared abstract or implement the remaining methods ([类名]::[方法名]) in /home/....../xxx.php on line 18

  错误原因:该类也需要是抽象类。如果一个普通类包含了抽象方法,那么该类被实现了怎么办?被实现的时候,类中的抽象方法还没有被定义,这一定是不安全的。另外,PHP 中的抽象方法都是完全抽象的。

  解决方法:使声明了抽象方法的类都定义为抽象类。

 

Part 2  语言本身

变量的引用

PHP 引用有毒。PHP 的引用和 C++ 类似,但是不完全一样,使用不当会引入bug。

foreach($data as &$val) {
    &val = 1;       
}

 

 

数组插入顺序

PHP 数组是基于 HashTable 实现的,但不同于 C++ STL 的 std::map(如下定义)。PHP 的 key 是不排序的,其遍历顺序会遵从“插入时的顺序”。

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

 

下面这段关于 std::map keys 排序的介绍,很好地诠释了std::map 是如何运作的。以辅助理解 PHP 的数组。

std::map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare.

 

posted @ 2014-08-20 11:31  健康平安快乐  阅读(477)  评论(0编辑  收藏  举报