0%

php语法

最好的语言!

资料

基本语法

  • <?php code ?> 如果是纯 php 代码时, 建议忽略最后 php>, 防止最后的空白进行输出

  • <? code ?> 配置为 --enable-short-tags

  • <?php if(){ ?>
      if-content
    <?php } else { ?>
      else-content
    <?php } ?>
    
    // same
    <?php if(): ?>
      if-content
    <?php else: ?>
      else-content
    <?php endif ?>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52

    - 必须写分号 `;`

    ## 类型

    标量类型

    - boolean
    - string
    - integer
    - float

    复合类型

    - array
    - object
    - callable

    特殊类型

    - resource
    - NULL

    ### special function

    - `gettype($var)` 返回 `"integer"` / `"float"` / `"string"` / `"boolean"`
    - `is_$type()` 返回 boolean, 如 `is_string($x)`

    ### boolean

    - `true` / `false` 不区分大小写
    - 一切空值都是 false, 空字符串 / `0` / 空 array ...
    - 使用 `(boolean)"1"/ (bool)"1"` 进行强制转换

    ### string

    - `''` 单引号字符不进行 expand, 和 SHELL 一样

    - `""` 双引号字符串会进行 expand, 类似 js 模板字符串

    - Here doc

    ```php
    $s = <<<END
    hello
    here doc
    END;

    $s = <<<"END"
    hello
    here doc
    END;
  • Now doc, Here doc + single quote 标识不进行 expand variales 操作

    1
    2
    3
    4
    $s = <<<'END'
    hello
    here doc
    END;

float / integer

  • 常规表示 0b / 0 / 0x 前缀表示 二进制/八进制/十六进制
  • integer 只有 signed integer, 与平台有关, 32 位系统上是 32 bit signed

array

  • = JsArray + JsObject
  • key 可以是 int / string
  • 使用 array() / [] 创建. key => val

object

  • 使用 $val = (object) $other; 将一个值强转为 object 类型
  • 将会创建一个内置类*stdClass* 的实例

NULL

  • NULL 类型的值只能是 NULL
  • NULL 值不区分大小写, null is OK
  • 这些情况会是 NULL
    • 被赋值为 NULL
    • 尚未被赋值。
    • unset()

callable

  • 使用 string 类型标识一个函数
  • 使用 array('ClassName', 'staticMethodName') 来表示一个方法
  • 使用 array($instance, 'instanceMethodName') 来表示一个方法

变量

全局变量

  • 出了函数作用域之后的变量, 类似 Python
  • 使用 global $a, $b; 声明使用全局变量
  • 全局变量实际上是存储在 $GLOBALS 这个 array 中

超全局变量

  • 是全局变量
  • 在任意作用域都可以直接访问, 不需要使用 global $var 声明

包含

常量

  • 使用 define / const 来声明常量, 常量值只能是标量类型 / resource 类型

  • // http://php.net/manual/zh/function.define.php
    bool define ( string $name , mixed $value [, bool $case_insensitive = false ] )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    - `get_defined_constants()` 返回已定义的常量 array

    ### 魔术常量

    类似 Node.js `__dirname` / `__filename`

    - `__LINE__` 当前行号
    - `__FILE__` 当前文件完整路径, realpath when symlink
    - `__DIR__` 当前文件所在文件夹, realpath when symlink
    - `__FUNCTION__` / `__METHOD__` 当前函数名 / 方法名
    - `__CLASS__` / `__TRAIT__` / `__NAMESPACE__` 当前类, Trait , namespace 名

    ## 表达式

    ### 运算符

    - `===` / `==` 与 JavaScript 一致, `===` 表示类型和值都相等
    - `!=` = `<>`
    - `a <=> b`
    - `a > b` -> `>0`
    - `a = b` -> `=0`
    - `a < b` -> `<0`
    - `$a ?? $b ?? $c` 返回第一个不为 `NULL` 的值
    - 逻辑运算符 `&&` & `and` / `||` & `or` 都可以
    - `$var instanceof Class`

    #### 错误控制运算符 `@`

    > 当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。

    #### 执行 Shell 运算符 ``

    > 会被当成 shell 命令来执行, 和 `shell_exec()` 函数效果一致

    > 在 **安全模式** 和 **关闭`shell_exec`** 时不起作用

    ## 控制流

    ### `foreach`

    ```php
    foreach($arr as $item) {

    }

等同于 JavaScript 中

1
2
for (let $item of $arr) {
}

include / require

  • include 失败会导致 E_WARNING 级别的错误
  • require 失败会导致 E_COMPILE_ERROR 级别的错误, 会导致脚本处理终止

include

处理顺序

  1. 有路径, 按照路径查找, include_path 会被忽略
    • 绝对路径 / 开头
    • 相对路径 ./ or ../
  2. 只有文件名时, 按顺序查找
    1. 按照 include_path 寻找, 类似 Java classpath
    2. 脚本所在目录
    3. 当前工作目录 pwd

include 返回值

  • 成功时返回 1
  • 失败返回 false, 并发出警告
1
2
3
if(include 'path.php') {
// blabla
}

函数 x

  • PHP 中的所有函数和类都具有全局作用域,可以定义在一个函数之内而在之外调用,反之亦然。
  • PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数。

全局作用域实例

  • barfoo 调用的时候定义的, 但是也具有全局作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}

/* 现在还不能调用bar()函数,因为它还不存在 */

foo();

/* 现在可以调用bar()函数了,因为foo()函数
的执行使得bar()函数变为已定义的函数 */

bar();

可变数量参数

1
2
3
function fn_name(...$args) {
//
}

默认参数

1
2
3
function makecoffee($type = "cappuccino") {
return "Making a cup of $type.\n";
}

可变函数

如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数

1
2
3
4
5
6
function hello_world(){
echo 'Hello World';
}

$fn_name = 'hello_world';
$fn_name();

匿名函数

  • PHP 会自动把此种表达式转换成内置类 Closure 的对象实例
  • 把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号. 相当于 JavaScript 函数表达式.

闭包使用外部变量

  • 需要使用 use 提前声明
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

$me = 'Tao';

/**
* greeting to another
*/
$greeting = function($who) use ($me) {
echo "$me says: Hello $who \n";
};

$greeting('Si');
// Tao says: Hello Si

类与对象

属性和方法

  • var $prop / public $prop
  • static $staticProp
  • function method()
  • static function staticFunctionName()

规则

  • 属性
    • 必须使用 public / private / protectedvar 限定
    • 使用 var 声明, 为 public
    • 使用 $this -> prop 引用, 注意没有 $
  • 静态属性
    • 不能使用 var 声明
    • 使用 self::$staticProp 引用, 注意有 $
  • 方法
    • 可使用 public / private / protected 限定, 默认为 public

static

1
2
3
4
5
6
7
8
9
class Test{
public static function create(){
return new Test();
}

public static $staticProps = 'static props';
}

Test::create()
  • 使用 ClassName::staticFunctionName() 调用
  • 在类中使用
    • self::staticFunctionName() 使用 self 指代自己
    • parent::staticFunctionName() 使用 parent 指代父类

const

类常量

1
2
3
class Test{
const NAME = 'Tao';
}
  • 在定义和使用常量的时候不需要使用 $ 符号。
  • 不能使用范围限定符, 默认就是 public

new

  • new ClassName()
  • new "ClassName"()
  • new $cls()

abstract

  • 定义为抽象的类不能被实例化。
  • 任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。
  • 被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
  • 继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;
  • 这些方法的访问控制必须和父类中一样(或者更为宽松)。

interface

  • 接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。

trait

同 mixin

  1. 定义和 class 一致
  2. 使用, use MyTrait;

重载

PHP 所提供的”重载”(overloading)是指动态地”创建”类属性和方法。

http://php.net/manual/zh/language.oop5.overloading.php

final

  • 如果父类中的方法被声明为 final,则子类无法覆盖该方法。
  • 如果一个类被声明为 final,则不能被继承。

clone / __clone

  • $obj2 = clone $obj1

  • 会去调用 obj1 的 __clone 方法, 类如果不实现 __clone 方法的话, 默认为赋值浅克隆. 对于属性值是引用类型的属性, 在实现 __clone 方法的时候, 需要调用 clone 再次复制子属性.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Object{
    var $prop = 1;
    }

    class Test{
    var $o = new Object();

    function __clone(){
    $this -> o = clone $this -> o;
    }
    }

    $t1 = new Test;
    $t2 = clone $t1;
    // 这时 $t1 / $t2 的 `-> o -> prop` 就不是同一个值

命名空间

  • 使用 namespace Level1\Level2; 定义命名空间
  • 使用 use Level1\Level2; 使用命名空间
  • 使用 use Level1\Level2 as L2; 使用命名空间别名

名称解析规则

http://php.net/manual/zh/language.namespaces.rules.php

错误处理

生成器

引用

注意在函数调用时没有引用符号——只有函数定义中有。

以下内容可以通过引用传递:

  • 变量,例如 foo($a)

  • New 语句,例如 foo(new foobar())

  • 从函数中返回的引用,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    <?php

    function &bar(){
    $a = 5;
    return $a;
    }

    foo(bar());