给力星

Web Developer

重温PHP手册 – 类型

美团点评 2018 届校招内推开始啦!
参与内推 = 简历免筛选 + 多一次笔试 + 提前面试/提前拿 Offer
多一次机会,多一份把握,千万不要错过~
内推申请地址:https://wenjuan.meituan.com/survey/68332

重拾基础,记录一些小细节。

Boolean 布尔类型

当转换为 boolean 时,以下值被认为是 FALSE:

  • 布尔值 FALSE 本身
  • 整型值 0(零)、浮点型值 0.0(零)
  • 空字符串,以及字符串 “0”
  • 不包括任何元素的数组
  • 特殊类型 NULL(包括尚未赋值的变量)
  • 从空标记生成的 SimpleXML 对象

所有其它值都被认为是 TRUE(包括任何资源)。

注意下面这种特殊的情况。

// Consider that the 0 could by any parameters including itself
var_dump(0 == 1); // false
var_dump(0 == (bool)'all'); // false
var_dump(0 == 'all'); // TRUE, take care
var_dump(0 === 'all'); // false

// To avoid this behavior, you need to cast your parameter as string like that :
var_dump((string)0 == 'all'); // false

Integer 整型

8进制与16进制的表示

$a = 0123; // 八进制数 (等于十进制 83)
$a = 0x1A; // 十六进制数 (等于十进制 26)

整数溢出

如果给定的一个数超出了 integer 的范围(包括运算时),将会被解释为 float。

PHP中没有整除的运算符。1/2 产生出 float 0.5。值可以舍弃小数部分强制转换为 integer,或者使用 round() 函数可以更好地进行四舍五入。

转换为整型

用 (int) 或 (integer) 强制转换或用函数 intval()。

当从浮点数转换成整数时,将向下取整(去掉小数位)-> 决不要将未知的分数强制转换为 integer!

    echo (int) ( (0.1+0.7) * 10 ); // 显示 7!

此外一个大的浮点数进行模运算会出现问题。

$i = 6887129852;
echo "i=$i\n";
echo "i%36=".($i%36)."\n";  // -24, wrong
echo "alternative i%36=".($i-floor($i/36)*36)."\n"; // 20, right

Float 浮点数

永远不要相信浮点数结果精确到了最后一位,也永远不要直接比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

比较浮点数

要测试浮点数是否相等,要使用一个仅比该数值大一丁点的最小误差值。该值也被称为机器极小值(epsilon)或最小单元取整数,是计算中所能接受的最小的差别值。

$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001; # 可以比较小数点后五位的浮点数

if(abs($a-$b) < $epsilon) {
    echo "true";
}

有一段别人的Note,解释了造成这种情况的原因:与2进制的表示有关。更深入的内容可以查看http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

just a comment on something the “Floating point precision” inset, which goes: “This is related to …. 0.3333333.”
While the author probably knows what they are talking about, this loss of precision has nothing to do with decimal notation, it has to do with representation as a floating-point binary in a finite register, such as while 0.8 terminates in decimal, it is the repeating 0.110011001100… in binary, which is truncated. 0.1 and 0.7 are also non-terminating in binary, so they are also truncated, and the sum of these truncated numbers does not add up to the truncated binary representation of 0.8 (which is why (floor)(0.8*10) yields a different, more intuitive, result). However, since 2 is a factor of 10, any number that terminates in binary also terminates in decimal.

String 字符串

PHP 中的 string 的实现方式是一个由字节组成的数组再加上一个整数指明缓冲区长度。

PHP 并不特别指明字符串的编码,字符串会被按照该脚本文件相同的编码方式来编码,因此如果一个脚本的编码是 ISO-8859-1,则其中的字符串也会被编码为 ISO-8859-1。

每个字符一个字节,所以PHP只支持256的字符集,不支持Unicode。

语法

  • 单引号、双引号包围的字符串可以写成多行。
  • 单引号包围的字符串,特殊字符和变量不会被转义、解析。
  • 双引号包围的字符串,特殊字符和变量会被转义、解析。
  • string 中的字符可以通过数组的形式访问。

Heredoc 结构

heredoc 类似于双引号,使用运算符 <<< 。在该运算符之后要提供一个标识符,然后换行。接下来是字符串 string 本身,最后要用前面定义的标识符作为结束标志。字符串中的特殊字符和变量会被转义、解析。

    $name = 'Star';
    $str = <<<EOD
        My name is $name,
        spanning multiple lines using heredoc syntax.
EOD;
    echo $str;

    // 注意作为参数传递时,结束标识符后不能有任何内容,包括分号。
    foo(<<<END
        abcd
END
);

结束标识符不能缩进,分号的前后也不能有任何空白或制表符,否则会出错。

Nowdoc 语法

Nowdoc 类似于单引号,当中的内容不进行解析。使用上与Heredoc相同,但开始的标识符要用单引号括起来,即 <<<‘EOT’。

变量解析

简单的解析是根据 $变量名 ,复杂的则是根据花括号{},可以使用复杂的表达式。由于 { 无法被转义,只有 $ 紧挨着 { 时才会被识别。

另外只能用 花括号 才能正确解析String中带引号的键名。

// 有效的表示
echo "This is $great";
echo "This is {$great}";
echo "This is ${great}";

// 需注意的是数组,只能用 花括号 才能正确解析带引号的键名。
echo "resut: $arr[0]";              // 有效
echo "result: $array['result']";    // 出错
echo "result: {$array['result']}";  // 有效
echo "result: ".$arr['result'];     // 有效

转换成字符串

  • 在前面加上 (string) 或使用 strval() 函数。
  • 数组 array 总是转换成字符串 “Array”,因此,echo 和 print 无法显示出该数组的内容。
  • NULL 总是被转变成空字符串。
  • 大部分的 PHP 值可以转变成 string 来永久保存,这被称作串行化,可以用函数 serialize() 来实现。
  • 使用函数 ord() 和 chr() 实现 ASCII 码和字符间的转换。
/* int ord ( string $string )
 * 返回第一个字符的ASCII码 */

$str = "\n";
if (ord($str) == 10) {
    echo "The first character of \$str is a line feed.\n";
}

/* int string chr ( int $ascii )
 * 返回ASCII码指定的单个字符 */

$str = chr(10); // 换行符

Array 数组

语法

PHP 数组可以同时含有 integer 和 string 类型的键名,因为 PHP 实际并不区分索引数组和关联数组。

自 5.4 起可以使用短数组定义语法,用 [] 替代 array()。

删除某键值对,使用 unset() 函数。

$array = array(
    "foo" => "bar",
    "bar" => "foo",
);

// 自 PHP 5.4 起
$array = [
    "foo" => "bar",
    "bar" => "foo",
];

key 会有如下的强制转换:

  • 包含有合法整型值的字符串会被转换为整型。例如键名 “8” 实际会被储存为 8( $arr[8] 和 $arr[“8”] 都可以访问该元素)。但是 “08” 则不会强制转换。
  • 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
  • 布尔值也会被转换成整型。即键名 true 实际会被储存为 1。
  • Null 会被转换为空字符串,即键名 null 实际会被储存为 “”。
  • 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。

如果在数组定义中多个单元都使用了同一个键名,则只使用了最后一个,之前的都被覆盖了

key 为可选项。如果未指定,PHP 将自动使用之前用过的最大 integer 键名加上 1 作为新的键名。所使用的最大整数键名不一定当前就在数组中,是曾经存在过的最大值。若要重建索引,则使用array_value()函数。

$array = array(
         "a",
         "b",
    6 => "c",
         "d",
);
print_r($array);

/* 输出如下, "d"的键名为7
array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [6]=>
  string(1) "c"
  [7]=>
  string(1) "d"
}
*/

unset($array[7]);
$array[] = 7; // 添加新元素
print_r($array); // 此时新元素索引为8而不是7

// 若要重建索引,则使用array_value()函数
$array = array_values($array);
print_r($array); // 索引从0开始

数组单元的访问

自 PHP 5.4 起可以用数组间接引用函数或方法调用的结果(之前只能通过一个临时变量)。可以用数组间接引用一个数组原型。

function getArray() {
    return array(1, 2, 3);
}

// on PHP 5.4
$secondElement = getArray()[1];

// previously
$tmp = getArray();
$secondElement = $tmp[1];

// or
list(, $secondElement) = getArray();

直接改变数组的值自 PHP 5 起可以通过引用传递(&$var)来做到。之前的版本需要使用数组键访问形式。

// 旧版本
foreach ($colors as $key => $color) {
    $colors[$key] = strtoupper($color);
}

// PHP 5
foreach ($colors as &$color) {
    $color = strtoupper($color);
}
unset($color); /* 务必清除引用,否则后面再使用$color就会改变数组最后一个元素的值 */

数组的赋值总是涉及值的拷贝,可以通过引用来拷贝数组(拷贝后指向同一个数组)。

转换为数组

如果将一个其他类型的值转换为数组,将得到一个仅有一个元素的数组,其下标为 0,该元素即为此标量的值。换句话说,(array)$scalarValue 与 array($scalarValue) 完全一样。将 NULL 转换为 array 会得到一个空的数组。

NOTE

若将NULL值转换为数组,则会返回空数组,这点特性可以用在一些地方。例如需要合并两个数组,但其中一个数组可能为NULL。

// $values可能为NULL.
$combined = array_merge((array)$values, $other);

注意,如果在$_POST数组(从form中传递过来)中使用字符串作为键名,键名中的小数点、空格会转换为下划线。程序中操作$_POST数组,则不会有这个情况。如下面点击submit后,输出结果为POST: Array ( [Windows3_1] => Sux, [Mac10.9] => Mavericks )

<html>
<body>
<?php
    $_POST['Mac10.9'] = 'Mavericks';
    printf("POST: "); print_r($_POST); printf("<br/>");
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    <input type="hidden" name="Windows8.1" value="Blue">
    <input type="submit" value="submit" />
</form>
</body>
</html>

Object 对象

创建一个新的对象Object

class foo
{
    function do_foo()
    {
        echo "Doing foo."; 
    }
}

$bar = new foo;
$bar->do_foo();

如果将其它任何类型的值被转换成对象,将会创建一个内置类 stdClass 的实例。如果该值为 NULL,则新的实例为空。数组转换成对象将使键名成为属性名并具有相对应的值。对于任何其它的值,名为 scalar 的成员变量将包含该值。

$obj = (object) 'ciao';
echo $obj->scalar;      // outputs 'ciao'

$arrObj = (object) array('a' => 'aa', 'b'=> 'bb');
echo $arrObj->a;        // outpus 'aa'
echo $arrObj->{'a'}     // outpus 'aa'

如果要将数组转换为Object,务必指定键名,且不能使用数字型,否则无法获取(即使能正确转换)。注意语法为 $arrObj->{‘key’} 。

$arrObj = (object) array('aa', 'bb');
var_dump($arrObj); // object(stdClass)#1 (2) { [0]=> string(2) "aa" [1]=> string(2) "bb" }
echo $arrObj->{0}; // Notice: Undefined property: stdClass::$0 in...

可以创建[递归]的对象:

$literalObjectDeclared = (object) array(
    'foo' => (object) array(
        'bar' => 'baz',
        'pax' => 'vax'
    ),
    'moo' => 'ui'
);
echo $literalObjectDeclared->foo->bar; // outputs "baz"!

Resource 资源类型

资源 resource 是一种特殊变量,保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄。

NULL

NULL表示一个变量没有值,NULL类型唯一可能的值就是NULL(不区分大小写)。

在下列情况下一个变量被认为是 NUL,可通过 is_null() 判断:

  • 被赋值为 NULL。
  • 尚未被赋值。
  • 被 unset() -> 变成未赋值。

注意空数组的情况,空数组 == NULL 成立:

$a = array();

$a == null  <== return true
$a === null <== return false
is_null($a) <== return false

Callback 回调类型

自 PHP 5.4 起可用 callable 类型指定回调类型 callback。一些函数如 call_user_func()(把第一个参数作为回调函数,剩余参数作为回调函数的参数) 或 usort() 可以接受用户自定义的回调函数作为参数。回调函数不止可以是简单函数,还可以是对象的方法,包括静态类方法。

create_function() 可以用来创建一个匿名回调函数。

静态类方法也可不经实例化该类的对象而传递给回调函数,只要在下标 0 中包含类名而不是对象。自 PHP 5.2.3 起,也可以传递 ‘ClassName::methodName’。

// 回调函数
function my_callback_function() {
    echo 'hello world!';
}

// 回调方法
class MyClass {
    static function myCallbackMethod() {
        echo 'Hello World!';
    }
}

// Type 1: 简单的回调
call_user_func('my_callback_function'); 

// Type 2: 静态回调方法
call_user_func(array('MyClass', 'myCallbackMethod')); 

// Type 3: 对象回调方法
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));

// Type 4: 静态回调方法 (As of PHP 5.2.3)
call_user_func('MyClass::myCallbackMethod');

Note

Performance note: The callable type hint, like is_callable(), will trigger an autoload of the class if the value looks like a static method callback.

可以通过$this来指定一个callback:

class MyClass { 
    public $property = 'Hello World!'; 

    public function MyMethod() 
    {
        call_user_func(array($this, 'myCallbackMethod'));
    }

    public function MyCallbackMethod()
    {
        echo $this->property; 
    }
}

Other

void 作为返回类型意味着函数的返回值是无用的。void 作为参数列表意味着函数不接受任何参数。

1条评论

  1. 最后那个是什么意思?是指PHP系统函数和扩展里的函数么?
    void 作为返回类型意味着函数的返回值是无用的。void 作为参数列表意味着函数不接受任何参数。

发表评论

电子邮件地址不会被公开。