Skip to content

PHP 基础知识 #73

@huliuqing

Description

@huliuqing

PHP 基础知识

原文在这

比较运算符

比较运算是一个比较容易轻视的知识点,如果没有足够的了解很有可能导致意料外的错误。举个例子,严格比较运算 ===

<?php
$a = 5;// 5 是 integer

var_dump($a == 5); // true
var_dump($a == '5');// 忽略类型比较(ignore type),true

var_dump($a === 5);// 比较类型和值(integer vs integer), true
var_dump($a === '5');// 比较类型和值(integer vs string),false

// 等值比较

if (strpos("testing", "test")) {// 'test' is found at position 0, which is interpreted as the boolean 'false'

}

if (false !== strpos("testing", "test")) {  // true, as strict comparison was made (false !== 0)

}

条件语句

If 语句

当在方法或函数里使用 if/else 语句时,有这样一种错觉,else 需要与 if 成对出现才行。但是,如果 else 语句仅仅是定义返回值,并且作为方法或函数结束,此时 else 不是必须的。

<?php

function test($a)
{
    if ($a) {
        return true;
    } else {
        return false;
    }
}

// vs

function test($a)
{
    if ($a) {
        return true;
    }

    return false;
}

// 或者更简洁

function test($a)
{
    return (bool) $a;
}

switch 语句

使用 switch 语句可以避免使用过多的 if/else 判断,不过有几点需要注意:

  • switch 仅仅比较值,而不比较类型(相当于 ==)
  • switch 将逐条比较 case 语句,如果为匹配到 case 语句,则进入 default 语句(仅当定义了 default语句时)
  • 如果 case 语句里没有 break 语句,将继续匹配 case 语句直到进入 break/return语句。
  • Within a function, using ‘return’ alleviates the need for ‘break’ as it ends the function
<?php
$answer = test(2);    // the code from both 'case 2' and 'case 3' will be implemented

function test($a)
{
    switch ($a) {
        case 1:
            // code...
            break;             // break is used to end the switch statement
        case 2:
            // code...         // with no break, comparison will continue to 'case 3'
        case 3:
            // code...
            return $result;    // within a function, 'return' will end the function
        default:
            // code...
            return $error;
    }
}

-switch 语句

全局命名空间(Global namespace)

当使用命名空间时,你会发现 PHP 内置函数或类在自定义方法内不可用。为了修复这个问题,在使用这些内置函数是加上反斜杠 ****。

<?php
namespace phptherightway;

function fopen()
{
    $file = \fopen();    // Our function name is the same as an internal function.
                         // Execute the function from the global space by adding '\'.
}

function array()
{
    $iterator = new \ArrayIterator();    // ArrayIterator is an internal class. Using its name without a backslash
                                         // will attempt to resolve it within your namespace.
}

String

字符串连接

  • 如果一行的长度超过了推荐的字符长度(120 字符),你应该考虑使用字符串连接多行
  • 为了可读,推荐使用连接操作,而不是使用连接赋值(.=)
  • 如果需要连接变量,建议另起新行
<?php
$a = "Multi-line example";// 连接赋值(.=)
$a .= "\n";
$a .= "of what not to do";

$a = "Multi-line example" // 连接操作符
    . "\n"                // 另起一行
    . "of what not to do";

字符串运算符

字符串类型

字符串是由一系列字符组成的。采用不同的字符串语法,会有些许差别。

单引号字符串

单引号用户表示一串字符(literal character),字符内的变量将不会被解析

如果使用单引号,在字符串内输入变量名如: 'hello $name',输出的结果也是 hello $name。如果使用的是双引号,PHP 将会尝试解析 $name,如果变量未定义,将输出错误信息

<?php
echo 'This is my string, loot at how pretty it is.';  // no need to parse a simple string

/**
 * Output:
 *
 * This is my string, look at how pretty it is.
 */
双引号

双引号功能很强大,除了能够解析变量,也能处理特殊字符如 \n 换行\t 制表符 等等

<?php
echo 'phptherightway is ' . $adjective . '.'     // a single quotes example that uses multiple concatenating for
    . "\n"                                       // variables and escaped string
    . 'I love learning' . $code . '!';

// vs

echo "phptherightway is $adjective.\n I love learning $code!"  // Instead of multiple concatenating, double quotes
                                                               // enables us to use a parsable string

双引号内可以包含变量,称之为 "插值(interpolation)"。

<?php
$juice = 'plum';
echo "I like $juice juice";    // Output: I like plum juice

当使用 插值 特性的时候,有时变量需要连接其它字符。这就需要区分什么时候做变量解析,什么时候是纯字符(literal character)

为了解决这个问题,需要使用花括号 {} 包裹变量

<?php
$juice = 'plum';
echo "I drank some juice made of $juices";    // $juice cannot be parsed

// vs

$juice = 'plum';
echo "I drank some juice made of {$juice}s";    // $juice will be parsed

/**
 * Complex variables will also be parsed within curly brackets
 */

$juice = array('apple', 'orange', 'plum');
echo "I drank some juice made of {$juice[1]}s";   // $juice[1] will be parsed

双引号

nowdoc 语法结构(自 PHP 5.3.0 起)

nowdoc 语法自 5.3 引入,它的功能有点类似单引号,只不过不需要连接字符便可以完成多行字符串连接操作。

<?php
$str = <<<'EOD' //以 <<< 实现 nowdoc 初始化
EOD;//以 'EOD' 结尾,并独占一行,且不能有前后空格 

/**
 * Output:
 *
 * Example of string
 * spanning multiple lines
 * using nowdoc syntax.
 * $a does not parse.
 */

nowdoc 语法

heredoc 语法结构

heredoc 语法类似双引号作用,同样支持多行字符串而不行也要使用字符串连接操作符(.)。

<?php
$a = 'Variables';

$str = <<<EOD               // initialized by <<<
Example of string
spanning multiple lines
using heredoc syntax.
$a are parsed.
EOD;                        // closing 'EOD' must be on it's own line, and to the left most point

/**
 * Output:
 *
 * Example of string
 * spanning multiple lines
 * using heredoc syntax.
 * Variables are parsed.
 */

heredoc 语法

效率

据闻,单引号效率要高于双引号,这种说法并不对( This is fundamentally not true.)

如果仅仅定义一个字符串,那么他们的效率几乎一样,效率都很快

如果字符内包含多种类型的变量,那么效率可能会有差异。如果仅仅有少许变量需要连接,则连接字符(.)效率较高;而如果是连接很多变量的话,插值运算则更快。

但是,即便如此这些效率的差异,对项目而言差异很小,如果从这方面来着手优化性能,没有太大意义。

Disproving the Single Quotes Performance Myth

三元运算符

三元运算符可以简化代码,三元运算可以嵌套(tacked/nested)使用,但建议将运算写在一行增加可读性

<?php
$a = 5;
echo ($a == 5) ? 'yay' : 'nay';

这是一个反例,为了简化代码牺牲了可读性

<?php
echo ($a) ? ($a == 5) ? 'yay' : 'nay' : ($b == 10) ? 'excessive' : ':(';    // excess nesting, sacrificing readability

三元运算符的返回值需要这样写

<?php
$a = 5;
echo ($a == 5) ? return true : return false;    // this example will output an error

// vs

$a = 5;
return ($a == 5) ? 'yay' : 'nope';    // this example will return 'yay'

不过,如果仅仅是返回 bool 值,就不要使用三元运算符了

<?php
$a = 3;
return ($a == 3) ? true : false; // Will return true or false if $a == 3

// vs

$a = 3;
return $a == 3; // Will return true or false if $a == 3

This can also be said for all operations(===, !==, !=, == etc).

使用括号组织代码和函数

使用三元运算符是,括号能够提升代码可读性和组织语句。一个例子

<?php
$a = 3;
return ($a == 3) ? "yay" : "nope"; // return yay or nope if $a == 3

// vs

$a = 3;
return $a == 3 ? "yay" : "nope"; // return yay or nope if $a == 3

Bracketing also affords us the capability of creating unions within a statement block where the block will be checked as a whole. Such as this example below which will return true if both ($a == 3 and $b == 4) are true and $c == 5 is also true.

<?php
return ($a == 3 && $b == 4) && $c == 5;

Another example is the snippet below which will return true if ($a != 3 AND $b != 4) OR $c == 5.

<?php
return ($a != 3 && $b != 4) || $c == 5;

PHP 5.3 起,可以省略三元运算符的一部分,语法是 expr1 ?: expr3,当 expr1 为 true 返回 expr1,否则 返回 expr3

三元运算符

变量声明

通常我们为了代码简洁,会定义变量名,但这样做为消耗两倍的内存。For the example below, let us say an example string of text contains 1MB worth of data, by copying the variable you’ve increased the scripts execution to 2MB.

<?php
$about = 'A very long string of text';    // uses 2MB memory
echo $about;

// vs

echo 'A very long string of text';        // uses 1MB memory

Performance tips

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions