1. 变量是什么

概念描述
临时存储数据的空间并不所有数据都需要保存到文件中,对于只用于当前程序的数据用变量更合适
数据复用的手段将程序需要反复调用的数据,保存到一个变量中, 可以实现数据复用

2. 命名规范

序号规则描述
1语法$ + 标识符 (必须以$做为变量标志)
2标识符[a-z][A-Z][0-9]_ 只允许使用大小写英文字母,数字或下划线, 且不能以数字开始
3大小写敏感严格区分大小写: $name$Name是完全不同的变量

示例代码: demo3.php

# 变量命名

$username = 'admin';
$userName = 'peter';

// 区分大小写
echo $username, '<br>', $userName, '<hr>';

// 无效变量名
// 没有使用$开头
// Hello = 'php';
// 标识符以数字开始
// $123aaa = 100;
// 标识符使用了特殊字符
// $user@id = 20;

// 有意义但不推荐, 如中文变量名
$我的邮箱 = 'irils@qq.com';
echo $我的邮箱;

// 无意义变量名
$aaa = 'www.zhi.ro';
$_ = 123;
$_123 = 888;
// 变量要做到望名生义, 一个有意义的变量名,可以极大提升代码的可读性和可维护性
推荐一个变量命名网站,告别命名恐惧症:https://unbug.github.io/codelf/

3. 创建方式

php 是动态语言,所以它的类型,值和变量名都是动态的

序号名称描述
1弱类型变量的类型,由它的当前值决定
2变量传递变量的值来自另一个变量时,有"值传递与引用传递"二种方式
3动态变量名也叫"可变变量", 即变量标识符可以来自另一个变量的值

3.1 弱类型

  • php 是弱类型语言, 它的变量类型,由赋给它的决定
  • 因此, php 变量也不需要使用前进行声明

示例代码: demo4.php

# php变量是弱类型

$var = 100;
var_dump($var);
echo '<br>';
$var = 'Hello World';
var_dump($var);

/*
int(100)
string(11) "Hello World"
*/

3.2 值传递与引用传递

将变量赋值给另一个变量时,有值传递与引用传递二种方式

序号传递方式描述
1值传递将原变量的副本(_变量值_)复制到新变量中
2引用传递将原变量内存访问地址&引用赋值给新变量
变量的值保存在"栈"中, 引用地址保存在"堆"中, 想深入了解请学习数据结构知识

示例代码: demo5.php

# 值传递与引用传递

// 1. 值传递
$price1 = 99;
// 将price1的值,传递给变量price2
$price2 = $price1;

// 更新price2
$price2 = 199;

// 查看price1当前值:99
echo 'price1 = ' . $price1;

echo '<hr>';

// 2. 引用传递
$price1 = 99;
// 将price1的引用(可理解为地址),传递给变量price2
// 注意, 在变量price1前添加一个&:地址引用符
$price2 = &$price1;

// 更新price2
$price2 = 199;

// 查看price1当前值: 199
echo 'price1 = ' . $price1;

// 此时,price1已经随price2同步更新为199

3.3 可变变量

  • 可变变量: 是指变量的标识符可以动态的改变,即变量标识符可以来自另一个变量的值
  • 应用场景: 需要通过动态改变变量来处理不同需求的时候,例如图像处理,请求处理时

示例代码: demo6.php

?php
# 可变变量

$var = 'email';
$$var = 'irls@qq.com';
// 等价于
// $email = 'irls@qq.com';

echo $email;

4. 检测与删除

序号函数描述
1isset()检测变量是否存在且值非null
2unset()删除变量,无返回值
3empty()是否为空(""/0/'0'/null/false/[]/\$a)
4is_null()NULL: 赋值为null/未赋值/unset()
error_reporting(E_ALL);
// $username 未定义, 直接输出会报钷
echo $username;
// isset($var): 如果变量$username存在且不为null,则输出它,此时不再报错
if (isset($username)) echo $username . '<br>';

$username = 'peter zhu';
echo $username, '<br>';
// 销毁/删除变量$username, 无返回值
unset($username);
// 报错:变量未定义
echo $username;
// 如果定义变量而没有初始化/赋值
$email;
// NULL
var_dump($email);
var_dump(is_null($email));
// empty(): 判断变量是否是空值,null只是它的子集之一,应用范围更广泛
$var = '';
var_dump(empty($var));  // true
var_dump(is_null($var)); // false
// 所以,检测表单值是否为空, 应该用empty()

5. 数据类型

变量的访问方式,受以下条件的限制

序号名称描述
1数据类型主要有基本类型, 复用类型,特殊类型
2作用域变量的有效范围,即可见性,查询变量的工具
3生命周期*变量从创建到注销的全过程(程序结束会自动注销)
  • 确定了数据类型, 才可以确定数据的 "取值范围" 与 "操作方式",所以非常重要
  • 变量数据类型由值决定, 值的数据类型有三类:

5.1 基本类型

基本类型: 是构成复合类型的基本数据单元
序号类型标识符检测函数举例
1整数integeris_int()150, 999
2浮点数floatis_float()3.14, .315
2字符stringis_string()'php', "email"
4布尔booleanis_bool()true, false

5.2 复合类型

序号类型标识符检测函数举例
1对象objectis_object()new stdClass()
2数组arrayis_array()$arr = [1,2,3]

5.3 特殊类型

序号类型标识符检测函数举例
1nullis_object()new stdClass()
2资源resourceis_resource()$f = fopen(...)

示例代码: demo7.php

<?php
# 变量类型

// 基本类型
$name = '手机';
$price = 3890;
$is5G = true;
echo $name . '价格: ' . $price . ', 是否5G? ' . ($is5G ? '是' : '否') . '<br>';

// 复合类型
$obj = new stdClass;
$obj->email = 'irils@qq.com';
echo $obj->email, '<br>';

$arr = ['电脑', 8000, 'huawei'];
// print_r($arr);
echo '<pre>' . print_r($arr, true) . '</pre>';

// 特殊类型
$num = null;
var_dump($num);
$f = fopen('demo6.php', 'r');
var_dump($f);
// gettype(): 返回类型字符串
echo gettype($f);

5.4 类型查询

  • 类型检测函数,如is_int()返回的都是一个布尔值
  • gettype(): 返回类型的字符串表示

6 类型转换

6.1 自动转换

  • 自动转换: 表达式根据操作符, 将操作数转为一致的数据类型后再进行运算
  • 自动转换, 通常只发生在 基本类型 参与的算术或字符串运算中
序号类型转换规则
1nullnull => 0
2booleantrue => 1, false => 0
3string123abc => 123, abc123 => 0
4integerint => float

6.2 强制转换

  • 强制转换分为: 临时转换永久转换 二种
  • 临时转换, 可使用类型提示符,或者类型函数实现

使用类型提示符:

序号类型转换规则
1(int)转为整数
2(float)转为浮点数
3(string)转为字符串
4(array)转为数组
5(object)转为对象

使用类型函数:

序号类型转换规则
1intval()转为整数
2floatval()转为浮点数
3strval()转为字符串
4boolval()转为布尔
  • 永久转换: 使用函数settype($var , $type)

示例代码: demo8.php

<?php
# 变量类型转换

// 自动转换

$a = null;
$b = true;
$c = false;
$d = '5g';
$e = 'php';
$f = 15;

echo $a + 10, '<br>';
echo $b + 10, '<br>';
// 字符串转数值型会有警告,但代码仍会执行, 推荐使用强制转换
echo $d + 10, '<br>';
echo $e + 10, '<br>';
// 整数15转为字符串'15'
echo $e . $f;

echo '<hr>';

// 强制转换

// 转换提示符: (int),(sgring)...
// (int)将$d强制转为整数,不再有警告信息
echo (int) $d + 10, '<br>';
// intval()转整数
echo intval($d) + 18, '<br>';
// strval($f)转字符串
echo strval($f) . ' hello', '<br>';

// 以上通过提示符和函数完成的强制转换,并不改变变量原始类型
// $f 依然是整数类型:integer
echo gettype($f), '<br>';

// settype()可将变量类型永久转换
settype($f, 'string');
// $f 永久的成为字符串类型
echo gettype($f), '<br>';

7. 作用域

  • 变量作用域,也叫"变量范围", 即定义变量时的上下文环境
  • 变量作用域,通俗的说,就是变量的生效范围
  • 一个变量必定属于一个作用域, 这个作用域也包括了当前作用域中引入其它文件
  • 也有不受作用域限制的变量,例如超全局变量, 在程序中任何地方都是有定义的
  • 函数作用域: php 中只有函数可以创建作用域, 函数之外的代码全部在全局空间中
序号作用域描述
1函数作用域使用function关键字创建的作用域
2全局作用域函数之外的变量生效范围
  • php 中没有块作用域的概念, 这与其它编程语言不同, 请留意
  • 根据作用域不同, 变量可以分为三类:
序号变量类型描述
1私有变量函数中定义的变量
2全局变量函数之外定义的变量
3超全局变量也叫预定义变量,访问不受作用域限制
  • 超全局变量,也叫超全局数组,随系统加载,因此在所有脚本中均有定义,全局和函数中都可以访问
序号变量名描述
1$GLOBALS引用全局作用域中可用的全部变量
2$_SERVER服务器和执行环境信息
3$_GETHTTP GET 请求:通过 URL 参数传递给当前脚本的变量的数组
4$_POSTHTTP POST 请求: 将变量以关联数组形式传入当前脚本
5$_FILESHTTP 文件上传变量,保存着上传文件的全部信息
6$_COOKIE通过 HTTP Cookies 方式传递给当前脚本的变量的数组
7$_SESSION当前脚本可用 SESSION 变量的数组
8$_REQUEST默认情况下包含了 $_GET$_POST$_COOKIE 的数组
9$_ENV通过环境方式传递给当前脚本的变量的数组

示例代码: demo9.php

# 变量作用域

// 全局作用域: 默认
$siteName = 'php中文网';

// 函数作用域
function getInfo(): string
{
    // 函数中不能直接访问全局变量
    // $private = $siteName;

    // 方法1: global 引入
    global $siteName;
    $local = $siteName;

    // 访问2: 使用超全局变量: $GLOBALS
    $local = $GLOBALS['siteName'];

    // 函数中访问超全局变量
    echo $_SERVER['SCRIPT_NAME'] . '<br>';

    return $local;
}

// 全局中访问函数私有变量: 未定义错误
echo getInfo(), '<br>';

// 全局中访问超全局变量
echo $_SERVER['SCRIPT_NAME'];

/*
/demo9.php
php中文网
/demo9.php
*/

8. 静态变量

8.1 基本常识

  • 定义在函数中的静态变量使用static修饰,并且与函数作用域绑定
  • 静态变量定义时必须初始化,且只能初始化一次,默认为0
  • 当程序执行离开函数作用域后,静态变量的值不丢失
  • 静态变量的值,可以在函数的多次调用中保持不变,即可带入下次调用中
  • 函数中静态变量遵循私有变量约束, 全局不可访问

8.2 应用场景

  • 当多次调用同一函数,且要求每次调用之间共享或保留某些变量的时候
  • 尽管全局变量也可以办到,但没必要, 采用局部静态变量更合适

示例代码: demo10.php


# 静态变量

namespace ns1;

function test1(): float
{
    // $sum: 局部动态变量,每次调用都会初始化,无法在多次调用中保持不变
    $sum = 0;
    $sum = $sum + 1;
    return  $sum;
}

echo test1(), '<br>';
echo test1(), '<br>';
echo test1(), '<br>';

echo '<hr>';

namespace ns2;

// 全局变量
$sum = 0;
function test1(): float
{
    // 通过全局变量,将每次的调用结果保存到全局中
    global $sum;
    $sum = $sum + 1;
    return  $sum;
}

echo test1(), '<br>';
echo test1(), '<br>';
echo test1(), '<br>';

echo '<hr>';

namespace ns3;


function test1(): float
{
    // 静态变量: 仅第一次调用时初始化,以后调用可保持原值
    // 静态变量: 可简单理解为仅在函数中使用的"伪全局变量"
    // 可以实现在函数的多次调用中的数据共享
    static $sum = 0;
    $sum = $sum + 1;
    return  $sum;
}

echo test1(), '<br>';
echo test1(), '<br>';
echo test1(), '<br>';

9. 变量过滤器

  • PHP 过滤器用于验证和过滤来自非安全来源的外部数据
  • 外部数据来源:
序号数据来源描述
1表单来自表音的用户输入数据
2Cookies来自浏览器中的 cookie
3服务器变量防止伪装的合法访问
4Web 服务数据Web 请求的数据
5数据库查询结果数据表中的数据并不可信
  • 常用的过滤器函数
序号函数描述
1filter_list()
2filter_id()
3filter_var()过滤单个变量
4filter_var_array()过滤多个变量
5filter_has_var()检测是否存在某个外部变量
6filter_input()过滤单个外部变量
7filter_input_array()过滤多个外部变量
  • 外部变量类型: INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV
  • 过滤器主要分为二类: 验证过滤器, 清理过滤器

9.1 验证过滤器常量

  • 验证过滤器: 又叫"验证器", 主要用于数据的类型和格式验证
序号过滤器函数描述
1FILTER_VALIDATE_INT验证整数
2FILTER_VALIDATE_FLOAT浮点点验证
3FILTER_VALIDATE_BOOLEAN验证布尔项
4FILTER_VALIDATE_EMAIL验证邮箱
5FILTER_VALIDATE_URL验证 URL 地址
6FILTER_VALIDATE_IP验证 IP 地址
7FILTER_VALIDATE_REGEXP正则验证
  • FILTER_VALIDATE_BOOLEAN: 布尔选项的返回值类型
序号返回值描述
1true"1", "true", "on" 和 "yes"
2false"0", "false", "off", "no", ""
3null除以上情形外

9.2 清理过滤器常量

  • 清理过滤器: 去掉非法字符,仅保留指定内容
序号过滤器函数描述
1FILTER_UNSAFE_RAW保持原始数据
2FILTER CALLBACK自定义函数过滤数据
3FILTER_SANITIZE_STRING去除标签以及特殊字符:strip_tags()
4FILTER_SANITIZE_STRIPPED"string" 过滤器别名
5FILTER_SANITIZE_ENCODEDURL-encode 字符串,去除或编码特殊字符
6FILTER_SANITIZE_SPECIAL_CHARSHTML 转义字符, 等价于 htmlspecialchars()
7FILTER_SANITIZE_EMAIL仅保留邮箱地址的合法字符
8FILTER_SANITIZE_URL仅保留合法的 URL, 必须从协议开始http/https
9FILTER_SANITIZE_NUMBER_INT仅保留合法的数字和正负号+-
10FILTER_SANITIZE_NUMBER_FLOAT仅保留合法的数字和正负号+- 以及指数 .,eE
11FILTER_SANITIZE_MAGIC_QUOTES等价于函数: addslashes()

9.3 选项与标志

  • 可以对过滤器设置选项和标志, 对数据进行更加精准的过滤处理
  • 选项与标志使用数组键名表示: 'options'=>[...], 'flags'=>...(复数)
  • 举例:
filter_var($int, FILTER_VALIDATE_INT, ['options'=>['min_range'=>10,'max_range'=>80]]);
// FILTER_REQUIRE_SCALAR: 必须是标量(即单值数据,如字符串,数值,布尔, 不能是数组或对象)
filter_var($data, FILTER_VALIDATE_EMAIL, ['flags'=>FILTER_REQUIRE_SCALAR]);

示例代码: demo11.php

# 变量过滤器

// filter_list(): 查看支持的所有过滤器
// filter_id(): 返回过滤器常量对应的ID
foreach (filter_list() as $filter) {
    // echo $filter . ' => ' . filter_id($filter) . '<br>';
}
echo '<hr>';

// 1. filter_var(): 过滤单个变量
$age = 30;
var_dump(filter_var($age, FILTER_VALIDATE_INT));
// 验证时,会将变量值转为字符串类型, 所以这样写也对
$age = '30';
var_dump(filter_var($age, FILTER_VALIDATE_INT));
echo '<br>';
// 还可以添加第三个参数,对过滤器行为进行限定
// 被过滤的数据也支持字面量,但不推荐这样
var_dump(filter_var(10, FILTER_VALIDATE_INT, ['options' => ['min_range' => 18, 'max_range' => 60]]));
$age = 40;
var_dump(filter_var($age, FILTER_VALIDATE_INT, ['options' => ['min_range' => 18, 'max_range' => 60]]));

echo '<br>';

// 既可以使用过滤器常量,也可以使用过滤器ID
$email = '80360650@qq.com';
// 过滤器常量
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
echo '<br>';
// 过滤器ID
var_dump(filter_var($email, 274));
echo '<br>';
var_dump(filter_var('irils@qq.com', 274));
echo '<br>';

// 2. filter_var_array():过滤多个变量
$a = 10;
$b = 'php';
// 返回值是数组, 验证失败返回false,成功返回原值
var_dump(filter_var_array([$a, $b], FILTER_VALIDATE_INT));
echo '<br>';
// 对于多变量验证最好将数组放在数组中统一处理
$data = [$a, $b, 'html', [6, 7, 8], 150, 200];
var_dump(filter_var_array($data, FILTER_VALIDATE_INT));
// 过滤掉验证未通过的元素
var_dump(array_filter(filter_var_array($data, FILTER_VALIDATE_INT)));

echo '<hr>';

// 3. filter_has_var(): 检测是否存在指定类型的外部变量
// 变量类型仅限:INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV
var_dump(filter_has_var(INPUT_GET, 'id'));
echo '<br>';

//4. filter_input(): 通过名称获取特定的外部变量,并且可以通过过滤器处理它
// 变量类型仅限:INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV
// false:验证失败, null: 变量不存在, 成功返回当前值
// $_GET['id'] 必须是大于1的整数
$res = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
var_dump($res);
echo '<hr>';

// 5. filter_input_array(): 同时验证多个外部变量
// 为一组数据应用统一过滤器
var_dump(filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING));

// 为每一个元素应用不同的过滤器
// 设置变量对应过滤器
$args = [
    'username' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => ['filter' => FILTER_VALIDATE_INT, 'flags'=>FILTER_REQUIRE_SCALAR, 'options' => ['min_range' => 18]],
    'blog' => FILTER_VALIDATE_URL,
];

// 非法: demo11.php?username=<a>admin</a>&email=abc&age=15&blog=www.zhi.ro
// 合法: demo11.php?username=admin&email=abc@qq.com&age=25&blog=https://www.zhi.ro
var_dump(filter_input_array(INPUT_GET, $args));