AI 摘要
在 PHP 应用中要和 MySQL 数据库进行交互,需要借助 PHP 提供的数据库扩展。
MySQLi 扩展提供了大量的函数操作 MySQL,使得在 PHP 程序中操作数据库变得轻松便捷。
MySQLi 扩展默认已经安装,在使用时需要在 PHP 配置文件(php.ini)中开启。
PHP 配置文件(php.ini):
extension=mysqliMySQLi 扩展不仅为 PHP 连接数据库、执行 SQL 语句提供了函数,而且提供了很多简化开发的其他常用操作函数。
MySQLi 扩展的基本函数:
| 名称 | 描述 |
|---|---|
| mysqli_connect() | 连接 MySQL 服务器 |
| mysqli_connect_error() | 获取连接服务器时的错误信息 |
| mysqli_select_db() | 选择数据库 |
| mysqli_set_charset() | 设置客户端字符集 |
| mysqli_query() | 执行 SQL 语句 |
| mysqli_insert_id() | 获取上一次插入操作时产生的 id |
| mysqli_affected_rows() | 获取上一次操作时受影响的行数 |
| mysqli_errno() | 返回上一个 MySQL 操作中的错误信息的错误码 |
| mysqli_error() | 返回上一个 MySQL 操作产生的错误信息 |
| mysqli_close() | 关闭数据库连接 |
PHP 访问 MySQL 数据库之前,需要连接数据库。
mysqli_connect 函数的基本用法:
$数据库连接对象 = mysqli_connect(主机地址, 用户名, 密码, 数据库名, 主机端口号);在使用 PHP 连接数据库时,还需要设置字符集,确保 PHP 与 MySQL 的连接使用相同的字符集 UTF8。
mysqli_set_charset 函数的基本用法:
mysqli_set_charset(数据库连接对象, 字符集编码);MySQL 连接成功后,执行完操作,需要在适当的时候关闭数据库连接。
mysqli_close 函数的基本用法:
mysqli_close(数据库连接对象);示例:连接数据库
SQL 脚本:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
`orderId` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单编号',
`productName` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '产品名称',
`price` decimal(10,2) DEFAULT NULL COMMENT '产品价格',
`userName` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '买家姓名',
`phone` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '买家电话',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of order
-- ----------------------------
BEGIN;
INSERT INTO `order` (`id`, `orderId`, `productName`, `price`, `userName`, `phone`) VALUES (1, 'No.001', '智能手机', 14999.00, '张三', '13888888888');
INSERT INTO `order` (`id`, `orderId`, `productName`, `price`, `userName`, `phone`) VALUES (2, 'No.002', '笔记本电脑', 8999.00, '李四', '15788888888');
INSERT INTO `order` (`id`, `orderId`, `productName`, `price`, `userName`, `phone`) VALUES (3, 'No.003', '无线蓝牙耳机', 129.00, '王五', '18988888888');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;入口页面(index.php):
<?php
// 连接数据库
$mysql = mysqli_connect("localhost", "root", "123456..", "demo", "3306");
if(!$mysql) {
// 连接失败,输出错误信息
exit(mysqli_error($mysql));
}
// 设置字符集编码
mysqli_set_charset($mysql, "utf8");
print_r("数据库连接成功");
// 关闭数据库连接
mysqli_close($mysql);示例效果:
数据库连接成功后,就可以执行 SQL 语句进行数据操作。
mysqli_query 函数的基本用法:
mysqli_query(数据库连接对象, SQL语句, 结果集模式);当函数执行写操作时,函数返回值为 boolean。
当函数执行读操作时,函数根据结果集模式返回查询结果集。
使用 mysqli_query 函数执行读操作时,返回的是一个资源类型的结果集,需要对结果集作进一步处理,获取结果集中的数据。
MySQLi 扩展处理结果集的基本函数:
| 名称 | 描述 |
|---|---|
| mysqli_num_rows(结果集对象) | 获取结果中行的数量 |
| mysqli_fetch_all(结果集对象, 数组形式) | 获取所有结果并以数组方式返回 数组形式:MYSQL_ASSOC(关联数组)/ MYSQL_NUM(索引数组) |
| mysqli_fetch_array(结果集对象) | 获取一行结果并以数组方式返回 |
| mysqli_fetch_assoc(结果集对象) | 获取一行结果并以关联数组返回 |
| mysqli_fetch_row(结果集对象) | 获取一行结果并以索引数组返回 |
| mysqli_free_result(结果集对象) | 释放结果集 |
示例:处理结果集
入口页面(index.php):
<?php
// 连接数据库
$mysql = mysqli_connect("localhost", "root", "123456..", "demo", "3306");
if(!$mysql) {
// 连接失败,输出错误信息
exit(mysqli_error($mysql));
}
// 设置字符集编码
mysqli_set_charset($mysql, "utf8");
print_r("数据库连接成功");
// 执行SQL语句
$result = mysqli_query($mysql, "SELECT * FROM `order`");
// 获取结果集数组
print_r("<pre>");
print_r(mysqli_fetch_all($result, MYSQLI_ASSOC));
print_r("</pre>");
// 关闭数据库连接
mysqli_close($mysql);示例效果:
使用 MySQLi 扩展执行增删改操作时,需要拼接 SQL 语句,效率低,安全性差,容易导致 SQL 注入问题。
MySQLi 扩展预处理提供了预处理方式,实现 SQL 语句和数据的分离,执行 SQL 语句运行效率高,无须考虑数据中包含特殊字符导致的 SQL 注入问题。
预处理的实现过程:
mysqli_prepare 函数用于预处理 SQL 模板,在编写 SQL 模板时,使用 ? 号占位符代替数据部分,且占位符两边无须使用引号包裹。
mysqli_prepare 函数的基本用法:
$预处理对象 = mysqli_prepare(数据库连接对象, SQL模板);mysqli_stmt_bind_param 函数用于将变量作为参数绑定到预处理语句中。
mysqli_stmt_bind_param 函数的基本用法:
mysqli_stmt_bind_param(预处理对象, 数据类型, 绑定变量1, 绑定变量2...);使用 mysqli_stmt_bind_param 函数进行参数绑定时,可以指定数据类型,且与绑定变量一一对应,绑定变量使用引用传参。
参数绑定时可以指定的基本数据类型:
| 名称 | 描述 |
|---|---|
| i | 整型 |
| d | 浮点型 |
| s | 字符串型 |
| b | 二进制对象 |
mysqli_stmt_execute 函数用于执行预处理语句。
mysqli_stmt_execute 函数的基本用法:
mysqli_stmt_execute(预处理对象);示例:预处理操作
入口页面(index.php):
<?php
// 连接数据库
$mysql = mysqli_connect("localhost", "root", "123456..", "demo", "3306");
if(!$mysql) {
// 连接失败,输出错误信息
exit(mysqli_error($mysql));
}
// 设置字符集编码
mysqli_set_charset($mysql, "utf8");
print_r("数据库连接成功");
// 定义预处理对象
$stmt = mysqli_prepare($mysql, "UPDATE `order` SET productName = ?, price = ? WHERE id = ?");
// 绑定参数
$productName = "HUAWEI手机";
$price = 7999.0;
$id = 1;
mysqli_stmt_bind_param($stmt, "sdi", $productName, $price, $id);
// 执行预处理语句
$result = mysqli_stmt_execute($stmt);
print_r($result ? "执行成功" : "执行失败");
// 关闭数据库连接
mysqli_close($mysql);示例效果:
PDO(PHP Data Objects)是 PHP 官方提供的数据库抽象层扩展,从 PHP 5.1 开始内置支持,PHP 7/8 成为操作数据库的主流标准,也是所有主流 PHP 框架(如 Laravel、ThinkPHP、Yii 等)的底层数据库驱动。
PDO 是一套统一的数据库操作接口,封装了不同数据库的底层实现差异,让开发者能用同一套代码语法操作 MySQL、PostgreSQL、SQLite、Oracle 等几十种数据库,同时提供了完善的防 SQL 注入方案,是现代 PHP 开发中操作数据库的首选方案。
PDO 与 mysqli、mysqli 对比:
| 特性 | PDO | mysqli | mysql |
|---|---|---|---|
| 支持数据库 | 跨库兼容 | 仅 MySQL/MariaDB | 仅 MySQL/MariaDB |
| 防注入支持 | 原生预处理(推荐) | 原生预处理(仅问号占位) | 无,需手动转义 |
| 占位符类型 | 命名占位符 + 问号占位符 | 仅问号占位符 | 无占位符,需拼接 SQL |
| 错误处理 | 支持异常抛出,高效 | 需手动判断,繁琐 | 需手动判断,繁琐 |
| 语法风格 | 统一面向对象语法 | 面向对象 + 过程化(双套) | 仅过程化语法 |
PHP 7/8 已默认启用 PDO,无需额外安装,如未默认启用,需要在 PHP 配置文件(php.ini)中开启。
PHP 配置文件(php.ini):
extension=pdo_mysqlPDO 通过构造函数创建连接对象。
PDO 构造函数的基本用法:
// 构建 DSN
$dsn = "mysql:host=主机地址:主机端口号;dbname=数据库名;charset=编码";
// 构建 PDO核心配置项
$options = [
// 错误时抛出异常,替代手动判断
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// 关闭模拟预处理,使用MySQL原生预处理,防SQL注入核心
PDO::ATTR_EMULATE_PREPARES => false,
// 默认返回关联数组
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
// 构建 PDO
$pdo = new PDO($dsn, 用户名, 密码, $options);
} catch (PDOException $e) {
// 捕获异常
die("数据库连接失败:".$e->getMessage());
}示例:连接数据库
入口页面(index.php):
<?php
$dsn = "mysql:host=localhost:3306;dbname=demo;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, "root", "123456..", $options);
echo "数据库连接成功";
} catch (PDOException $e) {
die("数据库连接失败:".$e->getMessage());
}示例效果:
PDO 执行 SQL 分两种场景:
预处理语句分为 prepare 预处理 和 execute 执行两步:
PDO 支持两种占位符:
预处理操作的基本用法:
// 定义带命名占位符的SQL(字段名和占位符对应)
$sql = "INSERT INTO user (name, age, email) VALUES (:name, :age, :email)";
// prepare 预处理
$stmt = $pdo->prepare($sql);
// 定义参数数组(键=占位符,值=实际数据)
$params = [
':name' => '张三',
':age' => 20,
':email' => '[email protected]'
];
// execute 执行
$stmt->execute($params);PDO CRUD 中的基本函数:
| 名称 | 描述 |
|---|---|
| lastInsertId() | 获取新增数据的自增 ID |
| fetch() | 获取单条数据,适用于按 ID 查、查一条记录 |
| fetchAll() | 获取所有数据,适用于查列表、多条记录 |
| rowCount() | 获取查询结果的行数 增删改时返回操作影响的行数 |
PDO 操作数据库的核心流程:
示例:CRUD
入口页面(index.php):
<?php
$dsn = "mysql:host=localhost:3306;dbname=demo;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, "root", "123456..", $options);
echo "数据库连接成功";
} catch (PDOException $e) {
die("数据库连接失败:".$e->getMessage());
}
// 新增数据
echo "【新增数据】<br>";
$insertSql = "INSERT INTO `order` (orderId, productName, price, userName, phone) VALUES (:orderId, :productName, :price, :userName, :phone)";
$insertStmt = $pdo->prepare($insertSql);
$insertStmt->execute([
':orderId' => 'No.004',
':productName' => '华为Mate80 Pro',
':price' => 9999.00,
':userName' => '张三',
':phone' => '13800138000'
]);
$newOrderId = $pdo->lastInsertId();
echo "新增成功!自增ID:{$newOrderId}<br><hr>";
// 查询数据
echo "【查询数据】<br>";
$listSql = "SELECT id, orderId, productName, price, userName FROM `order` ORDER BY id DESC";
$listStmt = $pdo->query($listSql);
$orderList = $listStmt->fetchAll();
echo "所有数据(共{$listStmt->rowCount()}条):<br>";
foreach ($orderList as $item) {
echo "ID:{$item['id']} | 订单号:{$item['orderId']} | 商品:{$item['productName']} | 价格:{$item['price']}元<br>";
}
echo "<hr>";
// 修改数据
echo "【修改数据】<br>";
$updateSql = "UPDATE `order` SET productName = :productName, price = :price, phone = :phone WHERE id = :id";
$updateStmt = $pdo->prepare($updateSql);
$updateStmt->execute([
':productName' => '华为Mate60 Pro+',
':price' => 7999.00,
':phone' => '13900139000',
':id' => $newOrderId
]);
$updateRow = $updateStmt->rowCount();
if ($updateRow > 0) {
echo "修改成功!共修改{$updateRow}条数据<br>";
} else {
echo "修改失败<br>";
}
echo "<hr>";
echo "【删除数据】<br>";
$deleteSql = "DELETE FROM `order` WHERE id = :id";
$deleteStmt = $pdo->prepare($deleteSql);
$deleteStmt->execute([':id' => 1]);
$deleteRow = $deleteStmt->rowCount();
if ($deleteRow > 0) {
echo "删除成功!已删除ID为{$newOrderId}的数据<br>";
} else {
echo "删除失败<br>";
}示例效果:
AI 摘要
HTTP(Hyper Text Transfer Protocol,超文本传输协议) 是浏览器与 Web 服务器之间进行数据交互时需要遵循的一种协议,用于定义浏览器与 Web 服务器之间数据交换的格式。
HTTP 的特点:
HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer,超文本传输安全协议)解决了 HTTP 明文传输不安全的问题,它在 HTTP 基础上通过加密和身份认证保证数据传输过程中的安全性。主要应用于对安全性要求比较高的通讯中。
HTTPS 和 HTTP 的区别:
基于 HTTP/1.0 版本的客户端与服务器在交互过程中需要经历 :
使用 HTTP/1.0 每次建立 TCP 连接后,只能处理一个 HTTP 请求,这种通信方式对于内容越来越丰富的网页来说,效率十分低下。
HTTP/1.1 支持持久连接,能够在一个 TCP 连接上传送多个 HTTP 请求和响应,从而避免多次建立和关闭 TCP 连接导致网页加载延时的问题。
当客户端与服务器建立连接后,客户端可以发送多个 HTTP 请求,并且在发送下一个请求时无须等待上次请求的返回结果,服务器必须按照接收请求的先后顺序依次返回响应结果,以保证客户端区分每次的响应内容,因此 HTTP/1.1 有效提高了交互效率。
当用户通过浏览器访问网站时,浏览器会向服务器发送请求数据,这些请求数据被称为请求消息。
POST /index.php HTTP/1.1
Host: localhost
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
a=1&b=2请求消息包含:
请求头的基本参数:
| 名称 | 描述 |
|---|---|
| Accept | 客户端接受的数据类型 |
| Accept-Charset | 客户端接受的字符集 |
| Accept-Encoding | 客户端接受的数据编码格式 |
| Accept-Language | 客户端接受的语言,可以指定多个 |
| Host | 客户端想要访问的服务器主机 |
| If-Modified-Since | 客户端拥有资源的有效时间 |
| Referer | 客户端的原始资源 URI |
| User-Agent | 客户端的系统信息,包括操作系统、浏览器版本号等 |
| Cookie | 客户端需要带给服务器的数据 |
| Cache-Control | 客户端的缓存控制 |
| Connection | 请求完成后,客户端希望是保持连接还是关闭连接 |
| Content-Type | 客户端发送的请求体的数据类型 |
| Content-Length | 客户端发送的请求体的长度 |
在浏览器的开发者工具中,可以查看请求标头。
超全局数组变量 $_SERVER 是一个关联数组,可以查看服务器的相关信息和 PHP 运行环境的相关信息,这些信息由 Web 服务器创建,对于不同的 Web 服务器,获取到的内容也会有所不同。
超全局数组变量 $_SERVER 中的基本参数:
| 名称 | 描述 |
|---|---|
| HTTP_HOST | 当前请求头中 Host 字段的内容 |
| HTTP_USER_AGENT | 当前请求头中 User-Agent 字段的内容 |
| HTTP_ACCEPT | 当前请求头中 Accept 字段的内容 |
| HTTP_ACCEPT_ENCODING | 当前请求头中 Accept-Encoding 字段的内容 |
| HTTP_ACCEPT_LANGUAGE | 当前请求头中 Accept-Language 字段的内容 |
| HTTP_REFERER | 当前请求头中 Referer 字段的内容 |
| SERVER_NAME | 服务器名称 |
| SERVER_ADDR | 服务器地址 |
| SERVER_PORT | 服务器端口 |
| REMOTE_ADDR | 来源地址 |
| REMOTE_PORT | 来源端口 |
| DOCUMENT_ROOT | 服务器文档根目录 |
| SERVER_ADMIN | 服务器管理员邮箱地址 |
| SCRIPT_FILENAME | 脚本文件的绝对路径 |
| SCRIPT_NAME | 脚本文件的相对路径 |
| SERVER_PROTOCOL | HTTP 版本 |
| REQUEST_METHOD | 请求方式 |
| QUERY_STRING | “?”后面的 URL 参数 |
| REQUEST_URI | 请求 URI |
| PHP_SELF | 脚本文件的相对路径 |
| REQUEST_TIME | 客户端发出请求的时间戳 |
示例:$_SERVER
入口页面(index.php):
<?php
print_r("请求头中的Host:".$_SERVER["HTTP_HOST"]."<br>");
print_r("请求头中的User-Agent:".$_SERVER["HTTP_USER_AGENT"]."<br>");
print_r("服务器名称:".$_SERVER["SERVER_NAME"]."<br>");
print_r("服务器端口:".$_SERVER["SERVER_PORT"]."<br>");
print_r("请求方式:".$_SERVER["REQUEST_METHOD"]."<br>");示例效果:
服务器接收到客户端发送的请求数据后,将处理后的数据返回给客户端,这些数据被称为响应消息。
HTTP/1.1 200 OK
Date: Wed, 26 Oct 2016 01:15:33 GMT
Server: Apache/2.2.25 (Win32) mod_fcgid/2.3.6
Vary: Accept-Encoding,Cookie
Cache-Control: max-age=3, must-revalidate
Content-Length: 18327
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html><body></body></html>响应消息包含:
响应头的基本参数:
| 名称 | 描述 |
|---|---|
| Server | 服务器的类型和版本信息 |
| Date | 服务器的响应时间 |
| Expires | 控制缓存的过期时间 |
| Location | 控制浏览器显示哪个页面,重定向到新的 URL |
| Accept-Ranges | 服务器是否支持分段请求,以及请求范围 |
| Content-Disposition | 服务器控制浏览器以下载方式打开文件 |
| Content-Encoding | 实体内容的编码格式 |
| Content-Length | 实体内容的长度 |
| Content-Language | 实体内容的语言和国家名 |
| Content-Type | 实体内容的类型 |
| Last-Modified | 请求文档的最后一次修改时间 |
| Transfer-Encoding | 文件传输编码 |
| Set-Cookie | 发送 Cookie 相关的信息 |
| Connection | 是否需要持久连接 |
在浏览器的开发者工具中,可以查看响应标头。
有时开发者需要手动更改一些响应消息头,以满足网站项目的特殊需求,通过 header 函数可以自定义响应头。
示例:header 函数
入口页面(index.php):
<?php
header("Location: https://www.duox.dev");一个完整的表单是由 form 标签和表单控件标签组成的。
form 标签的基本用法:
<form action="..." method="..." enctype="...">
<!-- ... -->
</form>form 标签的基本属性:
| 名称 | 描述 |
|---|---|
| action | 指定接收表单数据的服务器程序的地址 |
| method | 设置表单数据的提交方式,可选 GET/POST ,默认值为 GET |
| enctype | 设置表单数据发送到服务器前对表单数据的编码方式 application/x-www-form-urlencoded:默认值,在发送表单数据前对所有字符编码 multipart/form-data:不进行字符编码,通常含有文件上传的表单使用该值 text/plain:传输普通文本,不对特殊字符编码 |
input 表单控件标签的基本用法:
<!-- 文本框 -->
<input type="text" name="user" value="test">
<!-- 密码框 -->
<input type="password" name="pwd" value="">
<!-- 文件上传域 -->
<input type="file" name="upload">
<!-- 隐藏域 -->
<input type="hidden" name="id" value="2">
<!-- 重置按钮 -->
<input type="reset" value="重置">
<!-- 提交按钮 -->
<input type="submit" value="提交">
<!-- 单选按钮 -->
<input type="radio" name="gender" value="m" checked> 男
<input type="radio" name="gender" value="w"> 女
<!-- 复选按钮 -->
<input type="checkbox" name="hobby[]" value="reading" checked> 读书
<input type="checkbox" name="hobby[]" value="running"> 跑步textarea 表单控件标签的基本用法:
<textarea name="introduce" cols="5" rows="10">
<!-- ... -->
</textarea>select 表单控件标签的基本用法:
<select name="area">
<option selected>--请选择--</option>
<option value="xiamen">厦门</option>
<option value="quanzhou">泉州</option>
<!-- ... -->
</select>表单数据提交后,在 PHP 中可以使用不同的超全局数组变量接收数据。
接收表单数据的基本超全局数组变量:
| 名称 | 描述 |
|---|---|
| $_GET["key"] | 接收 GET 方式提交的数据 |
| $_POST["key"] | 接收 POST 方式提交的数据 |
| $_REQUEST["key"] | 接收 GET 或 POST 方式提交的数据 |
示例:表单数据交互
入口页面(index.php):
<?php
var_dump($_REQUEST);
?>
<form method="post" action="index.php?a=param1">
<input type="text" name="b" value="param2">
<input type="submit" value="提交">
</form>示例效果:
Cookie 是网站为了辨别用户身份而存储在用户本地终端(浏览器)上的数据。
当用户第一次访问 Web 服务器时,服务器会返回给用户一些信息,这些信息都保存在浏览器的 Cookie 中,当用户再次访问服务器时,浏览器会在请求头中将 Cookie 数据发送给服务器。
服务器接收到浏览器的请求后,根据请求头中的 Cookie 数据,判断用户是否访问过,进而识别用户的身份。
尽管 Cookie 实现了浏览器与 Web 服务器之间的信息交互,但也存在缺点:
使用 setcookie 函数可以创建或修改 Cookie。
setcookie 函数的基本用法:
setcookie(Cookie键, Cookie值, 有效时间戳, 生效路径, 生效域名, 是否需要在HTTPS传输);任何从客户端发送的 Cookie 数据都会被自动存入到 $_COOKIE 超全局数组变量中,通过 $_COOKIE 变量可以获取 Cookie 数据。
$_COOKIE 超全局数组变量的基本用法:
$_COOKIE[Cookie键];第一次使用 setcookie 函数创建 Cookie 时,$_COOKIE 超全局数组变量中没有 Cookie 数据,只有当浏览器下次请求并携带 Cookie 时,才能通过 $_COOKIE 超全局数组变量获取到 Cookie 数据。
示例:Cookie
入口页面(index.php):
<?php
// 设置Cookie
setcookie("userName", "多仔");
// 获取指定Cookie
echo $_COOKIE["userName"];
// 立即过期,删除Cookie
setcookie("userName", "", time() - 1);
// 获取所有Cookie
var_dump($_COOKIE);示例效果:
Cookie 在浏览器中是根据域名分开保存的,每个 Cookie 都具有名字、值、域名、路径等信息,浏览器在发送 Cookie 时,不同主机和不同路径之间都是隔离的,路径可以向下继承。
setcookie 函数可以设置 Cookie 的访问路径和有效域名。
一个浏览器、一个域名下最多可以存放 Cookie 的数量、大小都会受到浏览器的限制,不同版本的浏览器限制不同,不建议在 Cookie 中存放太多的数据。
Session 存储在服务器端,是用于实现数据跨脚本共享的会话技术,它的生命周期从用户访问页面开始,到与网站断开连接时结束,保存用户连续访问 Web 服务器时的相关数据。
Session 技术的实现依赖于 Cookie 技术。
当通过浏览器访问服务器时,服务器会设置 Cookie 给浏览器,同时服务器会创建一个 Session 文件来存储核心数据。
浏览器再次访问服务器时,服务器会根据 Cookie 数据打开对应的 Session 文件,获取存储的内容信息。
PHP 程序启动 Session 后,服务器会为每个浏览器创建一个供其独享的 Session 文件,每一个 Session 文件都具有唯一的会话 ID,用于标识不同的用户,会话 ID 分别保存在客户端和服务器端,客户端通过 Cookie 保存,服务器端则以文件的形式保存。
使用 session_start 函数可以启动 Session。
session_start 函数的基本用法:
session_start();Session 启动后,可以使用 $_SESSION 全局数组操作 Session。
$_SESSION 全局数组的基本用法:
$_SESSION[Session键];
$_SESSION[Session键] = 值;示例:Session
入口页面(index.php):
<?php
// 开启Session
session_start();
// 设置Session
$_SESSION["userName"] = "多仔";
// 获取Session
echo $_SESSION["userName"];
// 删除Session
unset($_SESSION["username"]);
// 清空Session
$_SESSION = [];
// 结束Session
session_destroy();示例效果:
cURL 扩展是一个基于 libcurl 库开发的扩展,其可以像浏览器一样完成与服务器的连接和通信,cURL 扩展支持多种传输协议,如 HTTP、HTTPS、FTP 等。
cURL 的基本函数:
| 名称 | 描述 |
|---|---|
| curl_init() | 初始化一个 cURL 会话 |
| curl_setopt ($ch, $option, $value) | 设置一个 cURL 传输选项 |
| curl_exec($ch) | 执行一个 cURL 会话 |
| curl_close($ch) | 关闭一个 cURL 会话 |
cURL 的基本传输选项:
| 名称 | 描述 |
|---|---|
| CURLOPT_URL | 需要获取的 URL 地址 |
| CURLOPT_HEADER | 启用时会将头文件的信息作为数据流输出 |
| CURLOPT_HTTPHEADER | 设置 HTTP 头字段数组 |
| CURLOPT_SSL_VERIFYPEER | 禁用后 cURL 将终止从服务端进行 SSL 验证 |
| CURLOPT_SSL_VERIFYHOST | 禁用后 cURL 将终止从服务端进行 SSL 验证 |
| CURLOPT_POST | 启用时会发送一个常规的 POST 请求,类似于表单 |
| CURLOPT_POSTFIELDS | 使用 POST 发送的数据数组 |
| CURLOPT_RETURNTRANSFER | 将 cURL 获取的响应结果直接返回,而不是直接输出 |
| CURLOPT_REFERER | 设置 HTTP 请求头 Referer |
使用 cURL 可以模拟浏览器发送请求、自定义请求头、模拟表单提交等。
示例:cURL
入口页面(index.php):
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.duox.dev/");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$respData = curl_exec($ch);
curl_close($ch);
print_r($respData);示例效果:
AI 摘要
PHP 的基本错误类型:
| 名称 | 描述 |
|---|---|
| 语法错误 | 程序代码不符合语法规则而发生的错误,会阻止 PHP 脚本的执行 |
| 运行错误 | 程序运行时出现的错误 |
| 逻辑错误 | 编写程序时实现思路出现错误,不会阻止 PHP 脚本的执行,也不会显示具体的错误信息 |
| 环境错误 | PHP 开发环境配置问题引发的错误 |
PHP 中的错误分为多种类型,每种错误类型都对应不同的错误级别。
错误级别通常用常量来表示,每个错误级别对应的值都是一个整型数据,错误级别常量用于表示当前的错误等级。
PHP 的基本错误级别:
| 名称 | 值 | 描述 |
|---|---|---|
| E_ERROR | 1 | 运行时的致命错误,会导致 PHP 脚本停止运行 |
| E_WARNING | 2 | 运行时警告,仅给出提示信息,PHP 脚本不会停止运行 |
| E_PARSE | 4 | 编译时语法解析错误,程序无法执行 |
| E_NOTICE | 8 | 运行时通知,表示 PHP 脚本可能会表现为错误的情况 |
| E_STRICT | 2048 | 严格语法检查,确保代码具有互用性和向前兼容性 |
| E_ALL | 32767 | 表示所有的错误和警告信息 PHP 5.4 之前不包含 E_STRICT |
| E_USER_ERROR | 256 | 类似 E_ERROR,由用户使用 trigger_error 触发的错误 |
| E_USER_WARNING | 512 | 类似 E_WARNING,由用户使用 trigger_error 触发的错误 |
| E_USER_NOTICE | 1024 | 类似 E_NOTICE,由用户使用 trigger_error 触发的错误 |
当 PHP 脚本发生错误时,默认情况下,PHP 程序会报告错误发生的原因,并将错误信息显示到页面中。
在实际开发中,有时候需要控制是否显示错误报告,以及报告哪些级别的错误,可以通过修改 PHP 配置文件或使用错误报告函数进行控制。
通过修改 PHP 配置文件(php.ini)可以控制错误报告的显示和关闭。
PHP 配置中控制错误报告的基本配置项:
| 名称 | 描述 |
|---|---|
| error_reporting | 设置错误报告的级别 E_ALL & ~E_NOTICE 表示显示除了 E_NOTICE 级别之外的所有的错误 |
| display_errors | 设置是否显示错误报告,可选 On/Off 一般情况下,在开发模式中将该配置项设置为 On,在生产模式中将该配置项设置为 Off |
PHP 提供的 error_reporting 函数和 init_set 函数也可以控制错误报告的显示和关闭。
示例:显示错误报告
入口页面(index.php):
<?php
// 显示错误报告
ini_set('display_errors', 1);
// 显示所有级别的错误报告
error_reporting(E_ALL);
echo $info;
// 显示除E_WARNING之外的错误报告
error_reporting(E_ALL & ~E_WARNING);
echo $info;示例效果:
在生产环境中,一般不会将错误报告直接显示出来。
在 PHP 中,可以通过 PHP 配置文件配置日志记录,或使用错误日志记录函数来记录错误日志。
通过修改 PHP 配置文件(php.ini)可以记录错误日志。
PHP 配置中记录错误日志的基本配置项:
| 名称 | 描述 |
|---|---|
| log_error | 设置是否记录日志,可选 On/Off |
| error_log | 指定错误报告日志文件的路径 |
PHP 提供的 error_log 函数也可以用于记录错误日志。
示例:记录错误日志
入口页面(index.php):
<?php
error_log('error message', 3, '/Users/duozai/Desktop/php.log');示例效果:
在 PHP 中,开发者可以根据不同的需求手动触发错误。
手动触发错误的基本用法:
trigger_error(错误信息, [, E_USER_XXX错误级别]);示例:手动触发错误
入口页面(index.php):
<?php
function divide($num1, $num2) {
if ($num2 == 0) {
trigger_error("除数不能为0");
return false;
}
return $num1 / $num2;
}
echo divide(100, 0);示例效果:
在 PHP 中,除了将错误报告记录到日志文件,还可以自定义错误处理函数,自行处理错误。
自定义错误处理的基本用法:
function 错误处理函数(错误级别, 错误信息) {
// ...
}
set_error_handler(错误处理函数, 错误级别);示例:自定义错误处理函数
入口页面(index.php):
<?php
function customError($errno, $errstr) {
echo "<b>Error:</b> [$errno] $errstr";
}
set_error_handler('customError');
echo $student;示例效果:
Xdebug 是一个开源的 PHP 程序调试工具,使用该工具可以追踪代码出错的具体位置,根据错误信息调试程序,提高开发效率。
Xdebug 文档:https://xdebug.org/
在 IntelliJ IDEA 中,可以快速安装 Xdebug。
Xdebug 安装完成后,需要重启 PHP 相关服务后生效。
Xdebug 会将错误信息变成彩色表格形式,并且将错误定位到具体的函数。
示例:Xdebug
入口页面(index.php):
<?php
function getFile() {
require 'outfile.php';
}
getFile();示例效果:
AI 摘要
数组类型属于数据类型中的复合类型,用于存储大批量数据。
在 PHP 中,数组分为索引数组和关联数组。
索引数组即键的数据类型为整型的数组,默认情况下,索引数组的键从 0 开始,依次递增。
关联数组即键的数据类型为字符串型的数组,通常情况下,关联数组的键和值之间有一定的业务逻辑关系,经常使用关联数组来存储具有逻辑关系的变量。
在 PHP 中,可以通过 array 结构法、赋值法、短数组定义法来定义数组。
array 结构法定义数组的基本用法:
// 定义索引数组
$数组 = array("值", "值", "...");
// 定义关联数组
$数组 = array("键" => "值", "键" => "值", ...);
// 定义混合数组
$数组 = array("值", "值", "键" => "值", "键" => "值", ...);
// 定义二维数组
$数组 = array(
"键" => array(...),
...
);赋值法定义数组的基本用法:
$数组[] = "值";
$数组[键] = "值";短数组定义法定义数组的基本用法:
$数组 = ["值", "值", "..."];
$数组 = array("键" => "值", "键" => "值", ...);在 PHP 中,可以通过键访问数组。
访问数组的基本用法:
$数组[键];使用 isset 函数可以判断变量或数组元素是否存在。
isset 函数的基本用法:
isset($array[$key]);示例:访问数组
入口页面(index.php):
<?php
$user = [
"name" => "John",
"age" => 30,
"city" => "XiaMen"
];
print_r("数组中是否存在name:");
var_dump(isset($user["name"]));
print_r("<br>");
print_r("数组中是否存在sex:");
var_dump(isset($user["sex"]));示例效果:
在 PHP 中,通常使用 foreach 语句遍历数组。
foreach 语句遍历数组的基本用法:
foreach($数组 as $键 => $值) {
// ...
}示例:遍历数组
入口页面(index.php):
<?php
$user = [
"name" => "John",
"age" => 30,
"city" => "XiaMen"
];
foreach ($user as $key => $value) {
echo "$key: $value<br>";
}示例效果:
在 PHP 中,unset 函数可以删除数组中的元素。
索引数组元素被删除后,数组中的数字键名不会自动填补空缺的数字。
unset 函数的基本用法:
unset($array[$key]);示例:删除数组元素
入口页面(index.php):
<?php
$user = [
"name" => "John",
"age" => 30,
"city" => "XiaMen"
];
print_r("删除元素前的数组:");
var_dump($user);
unset($user["age"]);
print_r("<br>删除元素后的数组:");
var_dump($user);示例效果:
PHP 提供了数组运算符对数组进行运算。
PHP 的基本数组运算符:
| 名称 | 描述 |
|---|---|
| + | 联合,$a+$b 即 $a 和 $b 的联合 |
| == | 相等,$a == $b 即 $a 和 $b 有相同的键值对,则为 true |
| === | 全等,$a === $b 即 $a 和 $b 有相同的键值对,且顺序和类型都相同,则为 true |
| != | 不等,$a != $b 即 $a 不等于 $b,则为 true |
| <> | 不等,$a != $b 即 $a 不等于 $b,则为 true |
| !== | 不全等,$a != $b 即 $a 不全等于 $b,则为 true |
示例:数组运算符
入口页面(index.php):
<?php
$num = [1, 2];
$str = ["a", "b", "c"];
$temp = $num + $str;
print_r("数组联合的结果:");
var_dump($temp);示例效果:
数组指针用于指向数组中的某个元素,默认指向数组的第 1 个元素,通过移动或改变指针的位置,可以访问数组中的任意元素。
指针操作的基本函数:
| 名称 | 描述 |
|---|---|
| key($array) | 获取当前指针指向数组元素的键 |
| current($array) | 获取当前指针指向数组元素的值 |
| next($array) | 将数组中的指针向后移动一位 |
| prev($array) | 将数组中的指针向前移动一位 |
| end($array) | 将数组的指针指向最后一个数组元素 |
| reset($array) | 将数组的指针指向第一个数组元素 |
示例:指针操作函数
入口页面(index.php):
<?php
$array = ["a", "b", "c", "d"];
print_r("当前指针所在的键是:".key($array).",所在的值是:".current($array));
print_r("<br>");
next($array);
print_r("指针向后移动,当前指针所在的键是:".key($array).",所在的值是:".current($array));
print_r("<br>");
end($array);
print_r("指针移动到最后,当前指针所在的键是:".key($array).",所在的值是:".current($array));
print_r("<br>");
prev($array);
print_r("指针向前移动,当前指针所在的键是:".key($array).",所在的值是:".current($array));
print_r("<br>");
reset($array);
print_r("指针移动到最前,当前指针所在的键是:".key($array).",所在的值是:".current($array));示例效果:
PHP 提供了一些针对数组元素的操作函数。
元素操作的基本函数:
| 名称 | 描述 |
|---|---|
| array_shift($array) | 删除数组开头的元素 |
| array_pop($array) | 删除数组末尾的元素 |
| array_unshift($array, $value1, ...) | 在数组开头添加元素 |
| array_push($array, $value1, ...) | 在数组末尾添加元素 |
| array_unique($array) | 去除数组中重复的值 |
| array_slice($array, $start, $length) | 从数组中截取出部分数组 |
| array_splice($array1, $start, $length, $array2) | 去掉数组中的一部分元素,并用其他值代替 |
示例:元素操作函数
入口页面(index.php):
<?php
$array = ["a", "b", "c", "d"];
print_r("当前数组:");
var_dump($array);
print_r("<br>");
array_shift($array);
print_r("删除数组开头的元素后的结果:");
var_dump($array);
print_r("<br>");
array_pop($array);
print_r("删除数组结尾的元素后的结果:");
var_dump($array);
print_r("<br>");
array_unshift($array, "e");
print_r("在数组开头添加元素后的结果:");
var_dump($array);
print_r("<br>");
array_push($array, "f");
print_r("在数组结尾添加元素后的结果:");
var_dump($array);示例效果:
PHP 内置了数组排序函数,可以很方便地实现对数组的排序。
数组排序的基本函数:
| 名称 | 描述 |
|---|---|
| sort($array) | 对数组进行升序排序 |
| rsort($array) | 对数组进行降序排序 |
| ksort($array) | 对数组按照键名升序排序 |
| krsort($array) | 对数组按照键名降序排序 |
| asort($array) | 对关联数组按照键值进行升序排序 |
| arsort($array) | 对关联数组按照键值进行倒序排序 |
| shuffle($array) | 将数组打乱 |
| array_reverse($array) | 以相反的顺序返回数组 |
示例:数组排序函数
入口页面(index.php):
<?php
$array = ["c", "b", "d", "a"];
print_r("当前数组:");
var_dump($array);
print_r("<br>");
sort($array);
print_r("数组升序排序后的结果:");
var_dump($array);
print_r("<br>");
rsort($array);
print_r("数组降序排序后的结果:");
var_dump($array);
print_r("<br>");
shuffle($array);
print_r("数组打乱后的结果:");
var_dump($array);示例效果:
PHP 内置了数组检索函数,可以很方便地对数组中的元素进行查找。
数组检索的基本函数:
| 名称 | 描述 |
|---|---|
| in_array($value, $array) | 检查数组中是否存在指定的值 |
| array_search($value, $array) | 搜索数组中给定的值并返回键名 |
| array_key_exists($key, $array) | 检查指定的键名是否存在于数组中 |
示例:数组检索函数
入口页面(index.php):
<?php
$array = ["c", "b", "d", "a"];
print_r("数组中是否存在元素b:");
var_dump(in_array("b", $array));
print_r("<br>");
print_r("数组中元素c的键名是:");
var_dump(array_search("c", $array));
print_r("<br>");
print_r("数组中是否存在键名为9的元素:");
var_dump(array_key_exists("9", $array));
示例效果:
PHP 提供了很多其他常用的数组函数。
数组的其他基本函数:
| 名称 | 描述 |
|---|---|
| count($array) | 计算数组中元素的个数 |
| range($min, $max, $step) | 创建包含指定范围单元的数组 |
| array_keys($array) | 返回数组中所有的键名 |
| array_values($array) | 返回数组中所有的值 |
| array_rand($array, $num) | 返回数组中一个或多个随机的键 |
| array_merge($array1, $array2, ...) | 把一个或多个数组合并为一个数组 |
| array_chunk($array, $size) | 把一个数组分割为新的数组块 |
| array_sum($array) | 返回数组中值的和 |
| array_replace($array1, $array2, ...) | 使用后面数组的值替换第一个数组的值 |
示例:其他数组函数
入口页面(index.php):
<?php
$array = ["c", "b", "d", "a"];
print_r("数组中的元素个数:".count($array));
print_r("<br>");
print_r("数组中所有的键名:");
var_dump(array_keys($array));
print_r("<br>");
print_r("数组中所有的值:");
var_dump(array_values($array));示例效果:
AI 摘要
在程序开发中,通常通过定义一个函数来实现特定的功能,从而使代码可以被复用,避免重复编写相同功能的代码。
函数的基本用法:
function 函数名([$参数1, $参数2]) {
函数体
[return 函数返回值;]
}对于函数而言,设置参数的方式不同,其调用方式也不同。
定义无参数的函数时,不需要传递参数,函数体用于完成指定的功能。
示例:无参函数
入口页面(index.php):
<?php
function sout() {
return "Hello PHP";
}
echo sout();示例效果:
定义有参数的函数时,函数内部会根据用户传递的参数进行操作。
示例:有参函数
入口页面(index.php):
<?php
function add($a, $b) {
return $a + $b;
}
echo "1 + 2 = ".add(1, 2);示例效果:
当需要函数修改它的参数值时,需通过函数参数的引用传递来实现,即引用传参。
在函数中使用引用传参的基本用法:
function 函数名(&$参数) {
函数体
[return 函数返回值;]
}示例:引用传参
入口页面(index.php):
<?php
function extra(&$message) {
$message = $message." PHP";
}
$message = "hello";
extra($message);
echo $message;示例效果:
在设置函数参数时,还可以为其指定默认值,即可选参数,当调用者未传递该参数时,函数将使用默认值进行操作。
指定函数的参数默认值的基本用法:
function 函数名($参数 = 参数默认值) {
函数体
[return 函数返回值;]
}示例:参数默认值
入口页面(index.php):
<?php
function say($name, $message = "Hello~") {
return $name . " say " . $message;
}
echo say("Tom");示例效果:
在自定义函数时,可以指定参数具体是哪种数据类型。
一般情况下,指定参数类型的方式是弱类型参数设置,在调用函数时,如果传递的参数不是指定的类型,程序会将其强制转换成指定类型再进行操作。
设置函数的弱类型参数的基本用法:
function 函数名(参数类型 $参数) {
函数体
[return 函数返回值;]
}示例:参数类型
入口页面(index.php):
<?php
function add(int $a, int $b) {
return $a + $b;
}
echo "2.6 + 3.8 = ".add(2.6, 3.8);示例效果:
在 PHP 中,还可以将函数参数设置为强类型参数,当用户传递的参数类型不符合函数的定义时,程序会报错提醒。
设置函数的强类型参数的基本用法:
declare(strict_types = 1);
function 函数名(参数类型 $参数) {
函数体
[return 函数返回值;]
}示例:设置函数的强类型参数
入口页面(index.php):
<?php
declare(strict_types = 1);
function add(int $a, int $b) {
return $a + $b;
}
echo "2.6 + 3.8 = ".add(2.6, 3.8);示例效果:
从 PHP 5.6 及以上版本开始,在定义函数时,可以指定可变参数列表,即函数可以接受不定数量的参数。
指定函数的可变参数列表的基本用法:
function 函数名(...$参数) {
函数体
[return 函数返回值;]
}在指定函数的可变参数列表时,需要注意:
示例:可变参数列表
入口页面(index.php):
<?php
function num(...$num) {
echo var_dump($num);
}
echo num(1, 2, 3, 4, 5, 6, 7);示例效果:
从 PHP 7 开始,引入了对函数返回值类型声明的强大支持,允许明确指定函数返回的数据类型。
指定函数返回值类型的基本用法:
declare(strict_types = 1);
function 函数名(参数类型 $参数) : 返回值类型 {
函数体
[return 函数返回值;]
}示例:函数返回值类型
入口页面(index.php):
<?php
declare(strict_types = 1);
function returnIntValue(int $value) : int {
// int + float = float
return $value + 1.0;
}
echo returnIntValue(5);示例效果:
变量只有在其作用范围内才可以被使用,这个作用范围称为变量的作用域。
示例:函数中变量的作用域
入口页面(index.php):
<?php
$sum = 0;
function test() {
$sum = 36;
return $sum;
}
echo 'test() => '.test();
echo "<br>";
echo '$sum => '.$sum;示例效果:
若要在函数中使用全局变量,可以使用 global 关键字或超全局变量 $GLOBALS。
global 关键字的基本用法:
function 函数名() {
global $全局变量名;
}超全局变量 $GLOBALS 的基本用法:
function 函数名() {
$GLOBALS['全局变量名'];
}示例:全局变量
入口页面(index.php):
<?php
$sum1 = 0;
$sum2 = 100;
function test() {
global $sum1;
echo '全局变量 $sum1 => '.$sum1;
echo "<br>";
echo '全局变量 $sum2 => '.$GLOBALS['sum2'];
}
test();示例效果:
嵌套调用是指在调用一个函数的过程中,调用另一个函数。
示例:嵌套调用
入口页面(index.php):
<?php
function sum($sub1, $sub2) {
return $sub1 + $sub2;
}
function avg($sub1, $sub2) {
$sum = sum($sub1, $sub2);
return $sum / 2;
}
echo avg(92, 90);
echo "<br>";
echo avg(78, 56);示例效果:
递归调用时函数嵌套中的一种特殊的调用,是指函数在其函数题内调用自身的过程。
示例:递归调用
入口页面(index.php):
<?php
function factorial($n) {
if ($n == 0) {
return 1;
} else {
return $n * factorial($n - 1);
}
}
echo factorial(5);示例效果:
在 PHP 函数中,执行完函数后,在函数中定义的变量会被释放或者被重新赋值,若想在函数执行完成后依然保留局部变量的值,可以使用静态变量。
静态变量的基本用法:
static $变量名 = 变量值;示例:静态变量
入口页面(index.php):
<?php
function num1() {
$num = 0;
$num++;
// num1函数中的变量$num在每一次调用函数时都会重新被赋值
return $num;
}
function num2() {
static $num = 0; // 静态变量
$num++;
// num2函数中定义了静态变量,变量$num在每一次调用函数时不会重新被赋值
// 重复调用num2函数,变量$num自增
return $num;
}
for($i = 0; $i < 5; $i++) {
echo num1().", ";
}
echo "<br>";
for($i = 0; $i < 5; $i++) {
echo num2().", ";
}示例效果:
可变函数就是将一个变量变成一个函数的形式,PHP 会自动寻找与变量值同名的函数,并且尝试执行它。
可变函数的基本用法:
$变量名 = 变量值;
$变量名();在使用可变函数时,需要注意:
示例:可变函数
入口页面(index.php):
<?php
function test() {
echo "Hello PHP";
}
$functionName = "test";
// $functionName() = test()
$functionName();示例效果:
回调函数是指将一个函数作为参数传递给另一个函数,然后在适当的时候被调用执行。
示例:回调函数
入口页面(index.php):
<?php
function sum($a, $b) {
return $a + $b;
}
// call_user_funch函数可以接受用户自定义的回调函数作为参数
// 参数1:回调函数名
// 参数...:传递给回调函数的参数
// call_user_func函数执行后,将调用sum函数并返回执行结果
echo call_user_func('sum', 1, 2);示例效果:
回调函数具有很大的灵活性和实用性,可以用于数据排序、数组过滤、文件处理等场景。
匿名函数就是没有函数名称的函数,也称为闭包函数,其强调的是函数本身没有名称,需要通过变量来引用和使用。
匿名函数的基本用法:
$变量名 = function() {
函数体
[return 函数返回值;]
};
$变量名();示例:匿名函数
入口页面(index.php):
<?php
$sum = function ($a, $b) {
return $a + $b;
};
echo $sum(1, 2);示例效果:
若要在匿名函数中使用外部的变量,可以使用 use 关键字来实现。
匿名函数使用外部变量的基本用法:
$变量名 = function() use ($变量名) {
函数体
[return 函数返回值;]
};
$变量名();示例:匿名函数使用外部变量
入口页面(index.php):
<?php
$c = 100;
$sum = function ($a, $b) use($c) {
return $a + $b + $c;
};
echo $sum(1, 2);示例效果:
匿名函数还可以作为函数的参数传递,实现回调函数。
示例:匿名函数作为函数的参数传递
入口页面(index.php):
<?php
function calculate($a, $b, $func) {
// 调用回调函数func
return $func($a, $b);
}
// 调用calculate函数时,传入一个回调函数
echo calculate(10, 20, function ($a, $b) {
return $a + $b;
});
echo "<br>";
echo calculate(10, 20, function ($a, $b) {
return $a * $b;
});示例效果:
字符串的基本函数:
| 名称 | 描述 |
|---|---|
| strlen($string) | 获取字符串的长度,一个英文字符、一个空格的长度均为 1 UTF-8 字符集的中文字符长度为 3 GBK 字符集的中文字符长度为 2 |
| mb_strlen($string) | 获取字符串的长度,1 个中文字符长度为 1 在使用该函数时,需确保 PHP 配置文件开启 mbstring 扩展 |
| strpos($string, $find) | 在字符串中查找另一个字符串首次出现的位置 |
| strrpos($string, $find) | 在字符串中查找另一个字符串最后一次出现的位置 |
| str_replace($find, $replace, $string) | 替换字符串中的一些字符 |
| substr_replace($string, $replace, $start) | 替换字符串的一部分 |
| substr($string, $start, $length) | 截取字符串的一部分 |
| explode($separator, $string) | 将字符串按照指定的分隔符分割成数组 |
| implode($separator, $array) | 将数组元素连接成一个字符串 |
| trim($string, $charlist) | 去除字符串两端的空白字符或其他预定义字符 |
| str_repeat($string, $repeat) | 重复指定的字符串指定的次数 |
| strcmp($string1, $string2) | 比较两个字符串是否相等 该函数二进制安全,且区分大小写,函数返回 0 即字符串相等 |
示例:字符串函数
入口页面(index.php):
<div>strlen+mb_strlen获取字符串长度:</div>
<?php $str1 = "多仔的PHP笔记"; ?>
<div>$str1:<?php echo $str1; ?></div>
<div>$str1的长度是:<?php echo strlen($str1); ?></div>
<div>$str1的长度是:<?php echo mb_strlen($str1); ?></div>
<br>
<div>strpos+strrpos+substr截取字符串:</div>
<?php $str2 = "/Users/duozai/Desktop/demo.png" ?>
<div>$str2:<?php echo $str2; ?></div>
<div>"duozai" 第一次出现的位置:<?php echo strpos($str2, "duozai"); ?></div>
<div>"/" 最后一次出现的位置:<?php echo strrpos($str2, "/"); ?></div>
<div>截取文件名:<?php echo substr($str2, strrpos($str2, "/") + 1); ?></div>
<br>
<div>str_replace+substr_replace+str_repeat替换字符串:</div>
<?php $str3 = "+00 13200077700" ?>
<div>$str3:<?php echo $str3; ?></div>
<div>将 "+00" 替换成 "+86" :<?php echo str_replace("+00", "+86", $str3); ?></div>
<div>将手机号中间四位替换成*:<?php echo substr_replace($str3, str_repeat("*", 4), 7, 4); ?></div>
<br>
<div>explode+implode转换数组与字符串:</div>
<?php $str4 = "1,2,3,4,5,6,7" ?>
<div>$str4:<?php echo $str4; ?></div>
<div>将字符串转换成数组:<?php var_dump(explode(",", $str4)); ?></div>
<div>将数组转换成字符串:<?php echo implode("-", explode(",", $str4)); ?></div>
<br>
<div>trim去除字符串两端符号</div>
<?php $str5 = ",1,2,3,4,5,6,7," ?>
<div>$str5:<?php echo $str5; ?></div>
<div>去除两端逗号:<?php echo trim($str5, ","); ?></div>
<br>
<div>strcmp判断字符串是否相等</div>
<?php $str6 = "hello"; ?>
<?php $str7 = "Hello"; ?>
<div>$str6:<?php echo $str6; ?></div>
<div>$str7:<?php echo $str7; ?></div>
<div>$str6与$str7是否相等:<?php echo strcmp($str6, $str7); ?></div>示例效果:
数学的基本函数:
| 名称 | 描述 |
|---|---|
| abs($number) | 返回一个数的绝对值 |
| ceil($number) | 返回一个数向上取最接近的整数 |
| floor($number) | 返回一个数向下取最接近的整数 |
| round($number) | 返回一个数的四舍五入的整数 |
| min(...$value) | 返回一个数组中的最小值,或者几个指定值中的最小值 |
| max(...$value) | 返回一个数组中的最大值,或者几个指定值中的最大值 |
| pi() | 返回圆周率的值 |
| pow($x, $y) | 返回一个数的指定次幂 |
| sqrt($number) | 返回一个数的平方根 |
| rand($min, $max) | 返回一个随机整数 |
示例:数学函数
入口页面(index.php):
<div>-123的绝对值是<?php echo abs(-123); ?></div>
<div>19.8向上取整是<?php echo ceil(19.8); ?></div>
<div>19.8向下取整是<?php echo floor(19.8); ?></div>
<div>19.8四舍五入是<?php echo round(19.8); ?></div>
<div>2, 4, 8的最小值是<?php echo min(2, 4, 8); ?></div>
<div>2, 4, 8的最大值是<?php echo max(2, 4, 8); ?></div>
<div>圆周率的值是<?php echo pi(); ?></div>
<div>2的3次方是<?php echo pow(2, 3); ?></div>
<div>9的平方根是<?php echo sqrt(9); ?></div>
<div>1-100的随机数是<?php echo rand(1, 100); ?></div>示例效果:
PHP 通过 UNIX 时间戳处理时间,UNIX 时间戳定义了从格林尼治时间 1970 年 1 月 1 日 0 时 0 分 0 秒起至当前时间的总秒数。
时间和日期的基本函数:
| 名称 | 描述 |
|---|---|
| time() | 获取当前的 UNIX 时间戳 |
| date($format[, $timestamp]) | 格式化一个本地时间或日期 |
| mktime($hour, $minute, $second, $month, $day, $year) | 获取指定日期的 UNIX 时间戳 |
| strtotime($string) | 将字符串转换成 UNIX 时间戳 |
| microtime() | 获取当前 UNIX 时间戳和微秒数 |
日期时间格式的基本字符:
| 名称 | 描述 | |
|---|---|---|
| 年 | Y | 4 位数字表示的完整年份 |
| y | 2 位数字表示的年份 | |
| L | 是否为闰年,1 是/0 否 | |
| 月 | m | 数字表示的月份,有前导 0,返回值 01-12 |
| n | 数字表示的月份,无前导 0,返回值 1-12 | |
| t | 给定月份所应有的天数,返回值 28-31 | |
| F | 完整英文单词表示的月份 | |
| M | 三个字母缩写表示的月份 | |
| 日 | d | 月份中的第几天,有前导 0,返回值 01-31 |
| j | 月份中的第几天,无前导 0,返回值 1-31 | |
| 时间 | g | 小时,12 小时制,无前导 0,返回值 1-12 |
| h | 小时,12 小时制,有前导 0,返回值 01-12 | |
| G | 小时,24 小时制,无前导 0,返回值 0-23 | |
| H | 小时,24 小时制,有前导 0,返回值 00-23 | |
| i | 分钟,有前导 0,返回值 00-59 | |
| s | 秒数,有前导 0,返回值 00-59 | |
| 星期 | N | 星期几,返回值 1(星期一)-7(星期日) |
| w | 星期几,返回 0(星期日)-6(星期六) | |
| D | 三个字母缩写表示的星期 | |
| l | 完整英文单词表示的星期 |
示例:时间和日期函数
入口页面(index.php):
<div>当前时间戳:<?php echo time(); ?></div>
<div>当前时间戳和微秒:<?php echo microtime(); ?></div>
<div>当前日期:<?php echo date('Y-m-d H:i:s'); ?></div>
<div>2024年07月11日 08:00:00的时间戳:<?php echo mktime(8, 0, 0, 7, 11, 2024); ?></div>
<div>2024年07月11日 08:00:00的时间戳:<?php echo strtotime('2024-07-11 08:00:00'); ?></div>示例效果:
AI 摘要
PHP 代码可以嵌入 HTML 中使用,为了区分 PHP 代码和 HTML 代码,需要使用 PHP 标记对 PHP 代码进行标识,PHP 的标记分为标准标记和短标记。
PHP 标记的基本用法:
<?php 代码块 ?>
<? 代码块 ?> // 不推荐使用,需要在php.ini中启用short_open_tag
<?= 输出内容 ?>示例:PHP 标记
入口页面(index.php):
<h1><?php echo "Hello PHP!" ?></h1>
<h1><?= "Hello PHP!" ?></h1>示例效果:
在 PHP 标记后面,如果没有除 PHP 以外的其他代码,标记末尾的 ?> 符号可以省略。
在 PHP 开发中,为了方便开发人员阅读和维护代码,可以添加注释对代码进行解释说明。
单行注释的基本用法:
// ...
# ...多行注释的基本用法:
/*
....
*/PHP 提供了一系列的输出语句,常用的输出语句有 echo、print、print_r、var_dump 等。
echo 输出语句用于输出字符串,如果输出其他类型的数据,会自动转换成字符串。
echo 输出语句的基本用法:
echo "...";
echo "...", "...";print 输出语句与 echo 输出语句类似,但 print 输出语句只能输出一个数据。
print 输出语句的基本用法:
print "...";print_r 输出语句可以输出任意类型的数据,如字符串、数组等。
print_r 输出语句的基本用法:
print_r("...");var_dump 输出语句不仅可以输出一个或多个任意类型的数据,还可以获取数据的类型和元素值。
var_dump 输出语句的基本用法:
var_dump("...");
var_dump("...", "...");示例:输出语句
入口页面(index.php):
<?php
echo "Hello echo<br>";
print "Hello print<br>";
print_r("Hello print_r<br>");
var_dump("Hello var_dump")示例效果:
定义标识符(如变量名、函数名、类名、方法名等)需要遵循一定的规则:
在使用关键字时,需要注意关键字不能作为常量、函数名或类名使用。
随着 PHP 版本的更新,关键字也在不断变化,可以通过查阅 PHP 官方手册来获取最新的关键字列表。
PHP 是弱类型语言,变量不需要实现声明,就可以直接进行赋值使用。
PHP 变量赋值分为传值赋值和引用赋值。
传值赋值是将等号右边的数据赋值给左边的变量。
传值赋值的基本用法:
$变量名 = 变量值;示例:传值赋值
入口页面(index.php):
<?php
$userName = "多仔";
$age = 18;
echo "姓名:".$userName; // 使用.号拼接字符串
echo "<br>";
echo "年龄:".$age;示例效果:
引用赋值时,如果其中的一个变量的值发生改变,则另一个变量的值也会发生改变。
引用赋值的基本用法:
$变量名 = &$要引用的变量名;示例:引用赋值
入口页面(index.php):
<?php
$userName = "多仔";
$age = 18;
echo "姓名:".$userName;
echo "<br>";
echo "年龄:".$age;
echo "<br>";
// 引用赋值
$newAge = &$age;
// 修改变量$age的值
$age = 81;
// 变量$newAge的值随着变量$age的改变而改变
echo "年龄:".$newAge;示例效果:
PHP 提供了可变变量,可以在开发时动态地改变一个变量的名称,将另一个变量的值作为该变量的名称。
在使用可变变量时,变量的值要符合标识符规则,避免出现非法变量名的情况。
可变变量的基本用法:
$变量名 = $$变量名;示例:可变变量
入口页面(index.php):
<?php
$userName = "多仔";
$age = 18;
$variableName = "userName";
// 相当于输出$userName
echo "姓名:".$$variableName;示例效果:
在 PHP 中,常量的值始终保持不变,常量一旦被定义就不能被修改或重新定义。
常量的命名遵循标识符的命名规则,习惯上总是使用大写字母定义常量名称。
在 PHP 中定义常量,可以使用 define 函数或 const 关键字。
define 函数的基本用法:
define(常量名, 常量值);const 关键字的基本用法:
const 常量名 = 常量值;示例:常量
入口页面(index.php):
<?php
define("HOST", "localhost");
define("PORT", "3306");
const USER = "root";
const PASSWORD = "root";
echo "HOST=", HOST, "<br>";
echo "PORT=", PORT, "<br>";
echo "USER=", USER, "<br>";
echo "PASSWORD=", PASSWORD, "<br>";示例效果:
PHP 提供了预先定义好的常量来获取 PHP 中的信息。
PHP 中的基本预定义常量:
| 名称 | 描述 |
|---|---|
| FILE | 获取 PHP 文件的完整路径 |
| LINE | 获取 PHP 文件中当前代码的行号 |
| PHP_VERSION | 获取 PHP 的版本信息 |
| PHP_OS | 获取当前 PHP 环境的操作系统类型 |
| PHP_INT_MAX | 获取当前 PHP 环境中整型数的最大值 |
| PHP_INT_SIZE | 获取 PHP 中整型数的字长 |
| TRUE | 该常量是一个真值(true) |
| FALSE | 该常量是一个假值(false) |
| NULL | 该常量是一个空值(null) |
| E_ERROR | 表示运行时的致命性错误,值为 1 |
| E_WARNING | 表示运行时的警告错误,值为 2 |
| E_PARSE | 表示编译时的解析错误,值为 4 |
| E_NOTICE | 表示编译时的题型信息,值为 8 |
示例:预定义常量
入口页面(index.php):
<?php
echo "PHP版本号:", PHP_VERSION, "<br>";
echo "PHP文件路径:", __FILE__, "<br>";示例效果:
表达式是 PHP 中非常重要的基石,任何有值的内容都可以理解为表达式。
PHP 的基本表达式:
<?php
$a = 1;
echo $a + 1;
$a = $a + 4;
echo $a + $b;
echo PHP_VERSION;PHP 支持 3 类数据类型,8 种数据类型。
| 名称 | 描述 | ||
|---|---|---|---|
| 标量类型 | bool | 布尔型 | 值为 true/false,且不分大小写 |
| int | 整型 | 可用八进制、十进制、十六进制表示 在不同位数的操作系统中,取值范围不一样 当定义的整型数值大于系统的整型数所能表示的最大范围时,将会被自动转换为浮点数 | |
| float | 浮点型 | 可用标准格式和科学计数法表示 | |
| string | 字符串型 | 可用单引号、双引号、heredoc、nowdoc 表示 | |
| 复合类型 | array | 数组 | 支持单维和多维数组 |
| object | 对象 | 可以用来表示具体的实体或抽象的概念 | |
| 特殊类型 | resource | 资源 | 用于表示对外部资源的引用 外部资源可以是文件、图像、数据库连接等 |
| NULL | 空值 | 表示一个变量没有被赋予任何值 |
字符串是由连续的字母、数字或字符组成的字符序列。
在 PHP 中,可以使用单引号、双引号表示字符串。
示例:字符串数据类型
入口页面(index.php):
<?php
$number = 100;
echo '$number=', $number;
echo '<br>';
echo "$number=", $number;示例效果:
当双引号字符串中包含变量时,可能会出现变量与字符串混淆的问题。
为了让 PHP 识别变量,可以使用 {} 符号将变量包裹起来,{} 符号中的内容会被识别成具体的变量。
示例:使用 {} 识别变量
入口页面(index.php):
<?php
$ap = "test";
// 将$ap识别成一个变量
echo "{$ap}ple";示例效果:
在 PHP 中,heredoc 和 nowdoc 是两种特殊的字符串表示方式。
使用 heredoc 定义字符串数据的基本用法:
>>>EOD
// ...
EOD;使用 nowdoc 定义字符串数据的基本用法:
>>>'EOD'
// ...
EOD;在使用 heredoc 和 nowdoc 时,需要注意:
heredoc 和 nowdoc 在处理大段的文本内容时非常有用,能使代码更加清晰易读。
示例:heredoc 和 nowdoc
入口页面(index.php):
<?php
$name = "PHP";
$heredoc = <<<EOD
<div>
<h3>$name 是世界上最好的语言</h3>
</div>
EOD;
echo $heredoc;
$nowdoc = <<<'EOD'
<div>
<h3>$name 是世界上最好的语言</h3>
</div>
EOD;
echo $nowdoc;示例效果:
为了检测数据类型是否符合预期,PHP 提供了一组 is_xxx 形式的内置函数用于检测数据类型。
数据类型检测的基本函数:
| 名称 | 描述 |
|---|---|
| is_bool($var) | 是否是布尔型 |
| is_string($var) | 是否是字符串型 |
| is_float($var) | 是否是浮点型 |
| is_int($var) | 是否是整型 |
| is_null($var) | 是否是空值 |
| is_array($var) | 是否是数组 |
| is_resource($var) | 是否是资源型 |
| is_object($var) | 是否是对象型 |
| is_numeric($var) | 是否为数字或由数字组成的字符串 |
示例:数据类型检测
入口页面(index.php):
<?php
var_dump(is_bool("1"));
echo "<br>";
var_dump(is_numeric("1"));
echo "<br>";
var_dump(is_string("1"));示例效果:
自动数据类型转换是指当参数与运算的两个数据类型不同时,PHP 会自动转换成相同的类型再进行运算。
自动转换成布尔型时:
示例:自动转换成布尔型
入口页面(index.php):
<?php
var_dump(0 == false);
echo "<br>";
var_dump(0.0 == false);
echo "<br>";
var_dump('' == false);
echo "<br>";
var_dump("0" == false);示例效果:
自动转换成整型时:
示例:自动转换成整型
入口页面(index.php):
<?php
var_dump(true + 1);
echo "<br>";
var_dump(false + 1);
echo "<br>";
var_dump("101PHP" + 1);
echo "<br>";
var_dump("PHP101" + 1);示例效果:
自动转换成字符串型时:
示例:自动转换成字符串型
入口页面(index.php):
<?php
var_dump("true => " . true);
echo "<br>";
var_dump("false => " . false);
echo "<br>";
var_dump(101 . "PHP");
echo "<br>";
var_dump(3.14 . "PHP");示例效果:
强制数据类型转换是将某个数据或变量转换成想要的数据类型。
强制数据类型转换的基本用法:
(目标数据类型) 变量或数据示例:强制数据类型转换
入口页面(index.php):
<?php
var_dump((boolean) -1);
echo "<br>";
var_dump((integer) "hello");
echo "<br>";
var_dump((float)false);
echo "<br>";
var_dump((string)101);示例效果:
PHP 提供了一系列数据类型转换函数,用于获取变量或数据的指定类型的值。
数据类型转换的基本函数:
| 名称 | 描述 |
|---|---|
| strval($var) | 获取字符串型的值 |
| intval($var) | 获取整型的值 |
| floatval($var) | 获取浮点型的值 |
| boolval($var) | 获取布尔型的值 |
示例:数据类型转换
入口页面(index.php):
<?php
var_dump(strval(false));
echo "<br>";
var_dump(intval("101"));
echo "<br>";
var_dump(floatval("0"));
echo "<br>";
var_dump(boolval("1"));示例效果:
PHP 的基本算数运算符:
| 运算符 | 描述 | 运算符 | 作用 |
|---|---|---|---|
| + | 加 | - | 减 |
| * | 乘 | / | 除 |
| % | 取模 | ** | 幂运算 |
PHP 的基本赋值运算符:
| 运算符 | 描述 | 运算符 | 描述 |
|---|---|---|---|
| = | 赋值 | += | 加并赋值 |
| -= | 减并赋值 | *= | 乘并赋值 |
| /= | 除并赋值 | % | 取模并赋值 |
| .= | 连接并赋值 | **= | 幂运算并赋值 |
PHP 的基本比较运算符:
| 运算符 | 描述 | 运算符 | 描述 |
|---|---|---|---|
| == | 等于 | != | 不等于 |
| <> | 不等于 | === | 全等 |
| !== | 不全等 | > | 大于 |
| >= | 大于等于 | < | 小于 |
| <= | 小于等于 |
使用 PHP 的比较运算符时需要注意:
三元运算符即三目运算符,用于实现简单的条件判断,根据条件表达式的结果执行不同的表达式。
三元运算符的基本用法:
条件表达式 ? 条件表达式成立时执行 : 条件表达式不成立时执行PHP 的基本逻辑运算符:
| 运算符 | 描述 | 运算符 | 描述 | ||
|---|---|---|---|---|---|
| && | 与 | 或 | |||
| ! | 非 | xor | 异或 | ||
| and | 与 | or | 或 |
PHP 基本的递增/递减运算符:
| 运算符 | 描述 | 运算符 | 描述 |
|---|---|---|---|
| ++ | 递增 | -- | 递减 |
使用 PHP 的递增/递减运算符时需要注意:
PHP 提供了用于拼接两个字符串的运算符 . 符号。
当使用字符串拼接运算符拼接布尔型、整型、浮点型或 NULL 时,会被自动转换成字符串型。
示例:字符串拼接
入口页面(index.php):
<?php
echo "Hello"."PHP";PHP 中的位运算符用于对二进制位(0 和 1)进行操作。
PHP 的基本位运算符:
| 运算符 | 名称 | 描述 | |
|---|---|---|---|
| & | 按位与 | 如果两个二进制位都为 1,则该位的运算结果为 1,否则为 0 | |
| 按位或 | 如果二进制位上有一个值位 1,则该位的运算结果为 1,否则为 0 | ||
| ~ | 按位非 | 如果二进制位时 0,则取反值 1。 如果二进制位时 1,则取反值 0 | |
| ^ | 按位异或 | 如果两个二进制位相同,则该位的运算结果为 0,否则为 1 | |
| << | 左移 | 将所有二进制位向左移动 1 位,右边的空位补 0,左边移走的部分舍去 | |
| >> | 右移 | 将所有二进制位向右移动 1 位,左边的空位根据原数的符号补位 0 或 1,原数是负数就补 1,原数是正数就补 0 |
示例:位运算符
入口页面(index.php):
<?php
$m = 1; // 二进制为01
$n = 2; // 二进制为10
// 按位与
$mn_and = $m & $n;
echo "按位与结果:" . $mn_and . "<br>";
// 按位或
$mn_or = $m | $n;
echo "按位或结果:" . $mn_or . "<br>";
// 按位异或
$mn_xor = $m ^ $n;
echo "按位异或结果:" . $mn_xor . "<br>";
// 按位取反
$m_not = ~$m;
echo "按位取反结果:" . $m_not . "<br>";
$m = 3;
// 左移
$m_left_shift = $m << 1;
echo "左移结果:" . $m_left_shift . "<br>";
$m = 8;
// 右移
$m_right_shift = $m >> 2;
echo "右移结果:" . $m_right_shift . "<br>";示例效果:
位运算可以用于优化一些特定的操作,例如在处理标志位、进行高效的位掩码操作或利用位移实现快速的乘除运算等场景中。
错误控制运算符用于在可能出现错误的表达式前使用,不会直接将错误显示给用户。
错误控制运算符的基本用法:
@表达式;在 PHP8 中,错误控制运算符已经被弃用。
PHP 中的分支结构常用的有 if、if-else、if-elseif-else、switch-case。
if 语句的基本用法:
if(条件表达式) {
// ...
}if-else 语句的基本用法:
if(条件表达式) {
// ...
} else {
// ...
}if-elseif-else 语句的基本用法:
if(条件表达式) {
// ...
} elseif(条件表达式) {
// ...
} else {
// ...
}switch-case 语句的基本用法:
switch(表达式) {
case 值1:
// ...
break;
case 值2:
// ...
break;
// ...
default:
// ...
}PHP 中的循环结构常用的有 while、do-while、for。
while 语句的基本用法:
while(循环条件) {
// ...
}do-while 语句的基本用法:
do{
// ...
} while(循环条件);for 语句的基本用法:
for(初始化表达式; 循环条件; 操作表达式) {
// ...
}PHP 中的跳转语句常用的有 berak、continue。
在 HTML 模板中嵌入 PHP 代码时,流程控制替代语句是一种可读性更好的语法。
流程控制语句和流程控制替代语句的比较:
| 流程控制语句 | 流程控制替代语句 |
|---|---|
| if(条件表达式) { // ... } | if(条件表达式): // ... endif; |
| switch(表达式) { // ... } | switch(表达式): // ... endswitch; |
| while(循环条件) { // ... } | while(循环条件): // ... endwhile; |
| for(初始化表达式; 循环条件; 操作表达式) { // ... } | for(初始化表达式; 循环条件; 操作表达式): // ... endfor; |
示例:流程控制替代语句
入口页面(index.php):
<h3>10以内的偶数列表</h3>
<ul>
<?php
for ($i = 0; $i < 10; $i++) {
if ($i % 2 == 0) {
echo "<li>$i</li>";
}
}
?>
</ul>
<h3>10以内的偶数列表</h3>
<ul>
<?php for ($i = 0; $i < 10; $i++): ?>
<?php if($i % 2 == 0): ?>
<li><?php echo $i ?></li>
<?php endif; ?>
<?php endfor; ?>
</ul>示例效果:
include 语句和 require 语句都可以引入一个外部文件。
使用 include 语句引入公共代码的基本用法:
include '完整路径文件名';
include('完整路径文件名');使用 require 语句引入公共代码的基本用法:
require '完整路径文件名';
require('完整路径文件名');示例:include 和 require
工具类(util.php):
<?php
echo "这是工具类 util.php";入口页面(index.php):
<?php
include './util.php';
echo "<br>Hello PHP";示例效果:
include_once 语句和 require_once 语句也可以引入一个外部文件。
示例:include_once 和 require_once
入口页面(index.php):
<?php
echo "<p>使用include引入util.php三次:</p>";
include './util.php';
echo "<br>";
include './util.php';
echo "<br>";
include './util.php';
echo "<br>";
echo "<p>使用include_once引入util.php三次:</p>";
// 上文已经引入util.php,此处不再重复引入
include_once './util.php';
echo "<br>";
include_once './util.php';
echo "<br>";
include_once './util.php';示例效果:
AI 摘要
PHP 是一种运行在服务器端的脚本语言,其语法风格融合了 C、Java 和 Perl 的特点。
PHP 主要用来开发动态网页,它可以将网页中需要动态变化的内容通过程序来生成,PHP 代码还可以嵌入 HTML 中使用,从而在服务端动态生成网页。
PHP 动态网页的处理流程:
PHP 最初为 Personal Home Page(个人主页)的缩写,于 1994 年由拉斯姆斯·勒多夫(Rasmus Lerdorf)创建,用来显示个人履历和统计网页流量。
1995 年 6 月,拉斯姆斯·勒多夫发布了 PHP 1.0,同年又发布了 PHP 2.0,命名为 PHP/FI(PHP/Form Interpreter),该版本可以处理复杂的嵌入式标签语言,同时支持 MySQL 数据库,此时使用 PHP/FI 开发的网站数量迅速增长,提高了其在开发领域的影响力。
1997 年,泽夫·苏拉塞(Zeev Suraski)和安迪·古特曼(Andi Gutmans)加入了 PHP 开发小组,重新编写了底层的解析引擎,很多开发人员也自愿加入到 PHP 的工作中,从此 PHP 成为了真正意义上的开源项目。
1998 年 6 月,PHP 3.0 版本发布,这一版本具有更好的执行效率、更加清晰的结构和更高的可扩展性,开发人员也可以参与到 PHP 扩展模块的开发。
2000 年 5 月,PHP 4.0 版本发布,该版本使用 Zend 引擎为 PHP 提供强大的动力,提高了运行复杂程序的性能。相比 PHP 的前几个版本,PHP 4.0 的性能高出近十倍,此外还更新了一些其他内容,例如支持多种 Web 服务器、丰富的函数库、类和对象的语法等,这一版本中逐渐开始采用面向对象的思想。
2004 年 7 月,PHP 5.0 正式发布,这标志着 PHP 一个新时代的到来,该版本使用第二代 Zend 引擎,引入了完善的面向对象机制。
2007 年,PHP 开发小组开始重构 PHP 6.0 版本,在该版本中进一步完善了面向对象机制,精简数组语法,但是 PHP 6.0 版本没有正式发布。
2015 年 6 月,PHP 7.0 发布,该版本是 10 年来的大改版,在性能上有更大的突破,PHP 7.0 在 PHP 5.0 基础上做了进一步的改进,功能更强大,执行效率更高。
2020 年 11 月,PHP 8.0 发布,该版本包含了很多新功能与优化项,包括命名参数、联合类型、注解、构造器属性提升、match 表达式、nullsafe 运算符、JIT,并改进了类型系统、错误处理、语法一致性。
随着时间的推移,PHP 凭借其特点,在 Web 开发领域占据了重要地位。
根据 TIOBE 公布的 2024 年 4 月编程语言排行榜,PHP 在该榜单中的排名已跌至第 17 位。
在实际应用中,编程语言的选择应根据具体的项目需求、团队技术栈、性能要求等多方面因素来决定。虽然 PHP 的排名有所下降,但它在一些领域仍然被广泛使用,特别是在中小型网站和 Web 内容管理系统中。
使用集成安装的方式,可以快速搭建 PHP 系列开发环境,集成安装可以快速搭建开发环境,免去繁琐的环境安装、配置过程,但集成安装有可能会造成局部环境冲突,需要根据实际情况妥善选择。
常见的集成安装环境有:FlyEnv、UPUPW、PHPStudy、LNMP/LAMP、宝塔等。
FlyEnv 是一款一体化全栈环境管理工具,提供了一个完整的运行环境,通过极速多版本切换、全栈技术支持和无缝跨平台体验,简化开发流程。
FlyEnv:https://www.flyenv.com/
UPUPW 绿色服务器平台是 Windows 下很有特色的一款免费服务器 PHP 套件,包括 Apache、Nginx、MySQL、Redis 等核心应用,支持 PHP、ASP、ASP.NET 解析语言,更适应 Windows 服务器的高效生产工作。
UPUPW:https://www.upupw.net/
LNMP 一键安装包是一个用 Linux Shell 编写的可以为 Linux VPS 或独立主机安装 LNMP(Nginx/MySQL/PHP)、LNMPA(Nginx/MySQL/PHP/Apache)、LAMP(Apache/MySQL/PHP)生产环境的 Shell 程序。
LNMP:https://lnmp.org/
PhpStudy(小皮面板)是国内 12 年老牌公益软件,集安全,高效,功能与一体,已获得全球用户认可安装,运维也高效,支持一键 LAMP、LNMP、集群、监控、网站、FTP、数据库、JAVA 等 100 多项服务器管理功能。
PhpStudy:https://www.xp.cn/
宝塔面板支持一键 LNMP/LAMP/WNMP/WAMP/IIS/SQLServer/MySQL/集群/监控/网站/FTP/数据库/JAVA/PM2 等 100 多项服务器管理功能。
宝塔面板:https://www.bt.cn/
本地开发也可以手动安装 PHP,课程选用 PHP 版本为 8.4。
Windows 系统下载 PHP:https://windows.php.net/download/
Linux 系统下载 PHP:使用 yum/apt 包管理工具安装。
macOS 系统下载 PHP:使用 HomeBrew 包管理工具安装。
Visual Studio Code、IntelliJ IDEA、PHPStorm 均可开发 PHP 项目,建议直接使用 IntelliJ IDEA 作为 PHP 项目开发所使用的 IDE。
在 IntelliJ IDEA 中,有支持 PHP 项目的插件。
在 IntelliJ IDEA 中,还需要配置 PHP 语言级别和 CLI 解释器,以支持 PHP 项目开发。
PHP 开发环境搭建完成后,可以创建一个 PHP 项目,查看 PHP 环境信息。
PHP 内置了一个简单的 Web 服务器,自 PHP 5.4.0 起可用。
使用 PHP 内置 Web 服务器,无需额外安装和配置复杂的 Web 服务器软件(如 Apache、 Nginx),即可快速启动一个简单的服务器来运行 PHP 脚本。
PHP 内置 Web 服务器在功能和效率上不如 Apache、Nginx 等成熟的 Web 服务器,但对于小型项目的开发和调试非常方便。
示例:phpinfo
新建 PHP 项目:
入口页面(index.php):
<?php // 所有的PHP脚本以 <?php 开头
phpinfo(); // 输出PHP环境信息配置 PHP 内置 Web 服务器:
示例效果:
部分语法、新特性,需要通过查阅 PHP 手册来学习。
PHP 手册:https://www.php.net/manual/zh/
AI 摘要
按钮级权限控制不是锦上添花,而是保障系统安全和用户体验的刚需,原因在于:
前端实现按钮级别的权限认证的核心逻辑:先获取用户权限标记集合 ->在渲染按钮时校验权限 -> 最终决定按钮是否显示/禁用。
编写登录用户数据仓库(store/currentUser.js),存储当前登录用户权限标记列表:
import {ref, computed, reactive} from 'vue'
import { defineStore } from 'pinia'
export const useCurrentUserStore = defineStore('currentUser', () => {
// 登录用户信息实体
let currentUser = reactive({})
// 当前用户菜单列表
let currentMenu = reactive([])
// 当前用户权限标记
let currentPerms = reactive([])
// 设置登录用户信息实体
function setCurrentUser(currentUser) {
this.currentUser = currentUser
}
// 设置当前用户菜单列表
function setCurrentMenu(currentMenu) {
this.currentMenu = currentMenu
}
// 设置当前用户权限标记
function setCurrentPerms(currentPerms) {
this.currentPerms = currentPerms
}
function hasPerms(identifier) {
// 判断当前用户是否拥有指定权限标记
return this.currentPerms.includes(identifier)
}
return { currentUser, setCurrentUser, currentMenu, setCurrentMenu, currentPerms, setCurrentPerms, hasPerms }
})编写权限工具类(plugins/PermsUtil.js),优化将用户权限标记存储到仓库中方法:
// 将用户权限菜单存储到仓库中
useCurrentUserStore().setCurrentMenu(toTreeList(response.data, false))
// 将用户权限标记存储到仓库中(包含所有类型的权限)
useCurrentUserStore().setCurrentPerms(response.data.map(perm => perm.identifier))编写页面组件,完善按钮级别的权限认证:
<el-button type="warning" @click="showAddDialog" v-if="useCurrentUserStore().hasPerms('system:users:add')">
添加用户
</el-button>在浏览器中测试:
参考文档:https://sa-token.cc/doc.html#/use/jur-auth、https://sa-token.cc/doc.html#/use/at-check
后端 API 是系统数据和业务操作的唯一入口,前端权限认证仅为体验层防护,后端权限认证才是真正的安全兜底,原因在于:
后端 API 实现权限认证的核心逻辑:登录生成身份凭证 Token -> 接口调用时校验凭证有效性并关联用户 -> 查询用户权限集合与 API 权限要求匹配 -> 匹配成功放行/失败拦截。
编写权限认证是嫌累(cn.duozai.sadmin.config.StpInterfaceImpl),返回一个账号所拥有的权限码集合:
/**
* SaToken权限认证实现类
*/
@Component
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
* @visduo
*
* @param loginId 登录id
* @param loginType 登录类型
* @return 权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 从会话中获取权限列表(获取当前登录用户权限列表时存入)
List<PermsEntity> permsList = (List<PermsEntity>) StpUtil.getSession().get("perms");
// 遍历权限列表,获取权限标识列表
List<String> identifierList = new ArrayList<>();
for (PermsEntity permsEntity : permsList) {
identifierList.add(permsEntity.getIdentifier());
}
// 返回权限标识列表
return identifierList;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
* @visduo
*
* @param loginId 登录id
* @param loginType 登录类型
* @return 角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
return new ArrayList<>();
}
}编写控制器,完善方法级别的权限认证:
@SaCheckPermission("system:users:add") // 注解校验
@Post
@Mapping("/add")
public ResponseResult add() {
// ...
}
]]>AI 摘要
ControlNet(控制网)是由 lllyasviel 团队于 2023 年提出的神经网络架构,核心是为了解决在 Stable Diffusion 中如何让图像生成变得更加可控的问题,是 Stable Diffusion 迈向工业化的非常重要的一步。
ControlNet 通过预处理器提取参考图中的姿态、深度、边缘等结构信息,再由 ControlNet 模型转换为检查点模型能够理解的生成条件,让生成图像精准遵循参考图的布局与结构,彻底解决生图结构失控的痛点,是 Stable Diffusion 中实现精准控图的核心插件。
ControlNet 插件的应用场景:
图生图与 ControlNet 插件的区别:
ControlNet 插件的发展史:
ControlNet 插件的安装与使用:https://github.com/lllyasviel/ControlNet
LiblibAI 已内置 ControlNet 插件,在本地部署的 Stable Diffusion 中使用 ControlNet,需要确保 ControlNet 插件已经安装到 WebUI 中。
ControlNet 仅凭插件本体是无法正常运行的,必须结合特定的 ControlNet 预处理器、模型,以实现不同的功能效果。
ControlNet 面板主要分为图像上传板块、控制类型板块、控制参数板块。
在图像上传板块可以上传参考图,通过输入参考图像来引导 AI 生成在细节、风格、结构等方面更符合创作者期望的图像,实现对图像生成过程的精细控制。
在控制类型(Control Type)板块中,可以选择控制的模式,每一种模式对应不同的预处理器,也对应不同的 ControlNet 模型,在选择时,检查点模型、控制模式、预处理器、ControlNet 模型四者一一对应。
ControlNet 可使用的预处理器非常多,允许创作者通过引入额外的控制信号来引导图像生成的过程,从而生成更精确、更丰富的效果,预处理器就像是给 AI 翻译图像语言的工具。
在控制参数板块中,可以调整相关参数:
ControlNet 支持同时使用多个预处理器(即叠加多个 ControlNet 控制单元),只需在界面中开启多个 ControlNet 选项卡,分别选择不同预处理器、上传对应控制图即可。
以生成一张人物写实图为例,参考生成参数如下。
生成效果:
以上图为例,使用 ControlNet 控制人物姿态,参考插件参数如下。
爆炸运行 & 预览效果:
调整生成参数如下。
生成效果:
OpenPose 是一种基于计算机视觉的人体姿态估计算法,通过检测人体关键点(如关节、面部特征点)并连接成骨骼结构,精确捕捉人物的动作和姿态。
OpenPose 算法通常检测以下关键点:
OpenPose 姿态预处理器允许创作者通过上传姿态参考图或直接绘制骨架来控制生成图像中的人物姿势。
OpenPose 姿态预处理器的应用场景:
OpenPose 姿态预处理器的关键参数:
在 OpenPose 姿态预处理器中,可以打开姿态编辑器调整姿态以重塑动作。
Canny 硬边缘预处理器用于提取图像的边缘轮廓,生成清晰的线条引导,且线条只有黑白两色,便于模型理解和遵循。
Canny 硬边缘预处理器的应用场景:
Canny 硬边缘预处理器的关键参数:
SoftEdge 软边缘预处理器用于处理图像边缘轮廓信息,目标是识别并区分图像中各种形状(如直线、圆弧等)的边缘。
SoftEdge 软边缘预处理器的应用场景:
SoftEdge 软边缘预处理器的关键参数:
Lineart 线稿预处理器是一种用于控制图像生成过程中线稿风格的约束方式,允许创作者输入简单线条或线稿(通常只包含黑白线条,没有色彩和阴影),生成符合轮廓的完整图像。
Lineart 线稿预处理器的应用场景:
Lineart 线稿预处理器的关键参数:
MLSD 是一种基于深度学习的直线检测算法,能够识别图像中的直线段而非简单的边缘,并将其转化为清晰的矢量线条。
Lineart 线稿、Canny 硬边缘、SoftEdge 软边缘、MLSD 直线的异同:
MLSD 直线检测预处理器的应用场景:
MLSD 直线检测预处理器的关键参数:
Depth 即深度,源于三维概念,描述物体间远近关系,图像只有黑白两色,白色表示距离镜头近,黑色表示距离镜头远,深度图能将图像采集器到场景各点的距离作为像素值,体现画面物体三维深度关系。
Depth 深度图预处理器通过传递图片空间信息,指导 AI 图像生成,辅助指定构图、姿势和 3D 结构等,在保持原始构图时生成新颖图像,比如创建有空间感的多层次场景,让 AI 理解动作层次和空间信息。
Depth 深度图预处理器的应用场景:
Depth 深度图预处理器的关键参数:
Tile/Blur 分块/模糊预处理器是 ControlNet 里负责高清修复与大图生成的预处理器,核心作用是拆分图像为多个小块并保留局部细节特征,避免大尺寸生图时出现模糊、重复纹理或细节丢失的问题,同时柔化块与块之间的拼接痕迹,让画面更自然连贯。
Tile/Blur 分块/模糊预处理器与 Tiled Diffusion 插件的异同:
Tile/Blur 分块/模糊预处理器的应用场景:
Tile/Blur 分块/模糊预处理器的关键参数:
Inpaint 局部重绘预处理器用于通过蒙版精准锁定需要修改的区域,对图像的局部区域进行重绘或修复。
Inpaint 局部重绘预处理器与图生图局部重绘的异同:
Inpaint 局部重绘预处理器的应用场景:
Inpaint 局部重绘预处理器的关键参数:
Segmentation 语义分割预处理器可以将图像按语义类别(如人物、天空、建筑、植物、衣物等)进行像素级分割,生成带类别标签的控制图,通过精准锁定特定类别区域实现针对性生成或修改,确保不同语义区域的边界清晰、内容匹配,避免区域混淆或内容错位。
Segmentation 语义分割预处理器的应用场景:
Segmentation 语义分割预处理器的关键参数:
Recolor 重上色预处理器是 ControlNet 中专注于图像色彩重塑的预处理器,核心作用是在严格保留原图构图、轮廓与细节结构的基础上,对图像进行重新上色或色彩优化,无需改动画面主体形态即可实现黑白转彩色、风格调色等效果,同时尽量贴合提示词定义的色彩逻辑,让色彩过渡自然且与内容匹配。
Recolor 重上色预处理器与图生图局部重绘的异同:
Recolor 重上色预处理器的应用场景:
Recolor 重上色预处理器的关键参数:
IP-Adapter(Image Prompt Adapter)风格迁移预处理器通过参考图提取人物形象特征或画面风格特征,无需复杂提示词即可将参考特征融入生成过程,实现一键迁移 IP 形象、统一风格,同时保留模型原生的创意生成能力,兼顾精准度与灵活性。
IP-Adapter 风格迁移预处理器的应用场景:
IP-Adapter 风格迁移预处理器的关键参数:
InstantID 换脸预处理器通过提取参考人脸的 ID 特征与姿态特征,生成带人脸约束的控制信号,在保留目标人脸核心特征的前提下,自由定制生成画面的场景、风格与动作,实现跨角度、跨风格的精准换脸。
InstantID 换脸与 IP-Adapter face_id 风格迁移预处理器的异同:
InstantID 换脸预处理器的应用场景:
InstantID 换脸预处理器的关键参数:
部分 ControlNet 预处理器虽使用频率略低,但能解决特定场景的控图需求,可根据创作目标灵活选用。
AI 摘要
Stable Diffusion 文生图的高分辨率修复(Hires.fix)核心采用低分辨率打底 + 高分辨率重绘的两阶段流程,既能提升分辨率,又能保证构图与细节,是解决大尺寸生成模糊、细节不足等问题的方案。
高分辨率修复分两步完成高清化:
高分辨率修复的核心参数:
高分辨率修复常用的放大算法:
以生成一张人物写实图为例,参考生成参数如下。
生成效果:
调整生成参数如下。
生成效果:
Stable Diffusion 中的附加功能后期处理,也为创作者提供了丰富的图片处理选项,创作者也可以使用附加功能后期处理实现高清放大。
后期处理附加功能放大允许用户自己上传自己的图片,并直接提高图片的分辨率,不会对原图进行任何形式的重绘和修改,而是直接对图片的分辨率进行提升。
后期处理附加功能高清放大的核心参数:
下图原始尺寸为 512x512。
以上图为例进行后期处理附加功能放大,参考生成参数如下。
生成效果:
在 Stable Diffusion 中,高清放大图像还可以借助图生图功能设置图像的分辨率和重绘幅度等参数来实现,但此方法也有尺寸上限的局限性,当分辨率过大时可能会导致无法生图等问题。
SD Upscale 插件是 Stable Diffusion 的专用放大脚本,是早期实现超分放大的标准化工具,在一些本地部署的 Stable Diffusion 中可以使用该内置插件实现高清放大。
SD Upscale 的核心原理是将原图切割成一个个图块,针对每一个图块分别进行高清修复,完成修复后再将这些图块重新拼接,最终得到放大且高清的图像。
在这个过程中,分块重叠像素宽度扮演着关键角色,其本质是为了避免拼接痕迹,提升图像的整体连贯性。由于每个图块在修复时是独立进行的,如果图块之间没有重叠部分,直接拼接可能会在接缝处出现明显的色差、纹理不连续等问题。
设置分块重叠像素宽度后,在修复过程中,这部分重叠区域会被重复处理,模型会综合考虑相邻图块的信息,对重叠部分进行融合优化。当完成所有图块的修复和拼接后,重叠区域经过处理,使得图像过渡自然,大幅减少了拼接产生的违和感,最终呈现出视觉效果更好的放大图像。
Ultimate SD Upscale(USD)是 SD Upscale 的进阶扩展插件,核心优势在于更强的细节控制、无缝拼接与显存适配,适合高倍数、超高清放大、精细细节修复。
Ultimate SD Upscale 插件的安装与使用:https://github.com/Coyote-A/ultimate-upscale-for-automatic1111
Tiled Diffusion 是 Stable Diffusion 的高分辨率生成专用扩展插件,核心逻辑是将目标尺寸的大图,按规则分割成多个独立小图块,分别执行扩散生成、放大计算,最后通过算法无缝拼接,能以更小的计算成本更稳定地输出超高清图像,速度快、细节完整。
Tiled Diffusion 是由 Tiled Diffusion 插件、Tiled VAE 插件组成,Tiled Diffusion 负责高分辨率图像的分块生成与无缝拼接,Tiled VAE 负责分块编码解码以避免画质崩坏,二者是高分辨率生成的配套组合,在使用时必须同时启用才能兼顾低显存占用与高清画质。
Tiled Diffusion 和 SD Upscale 的核心区别:
本地部署的 Stable Diffusion 需要自行安装 Tiled Diffusion 插件、Tiled VAE 插件,LiblibAI 已内置该插件,使用时需要注意部分检查点模型不支持使用 Tiled Diffusion 插件。
Tiled Diffusion 的安装与使用:https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111
Tiled Diffusion 的核心参数:
| 模块 | 名称 | 描述 | 推荐 |
|---|---|---|---|
| Tiled Diffusion 通用 | 方案 | Mixture of Diffusers 适合局部重绘 MultiDiffusion 能确保分块内容一致性,生成大图无明显拼接痕 | MultiDiffusion |
| 潜空间分块宽 / 高 | 用于把超大尺寸图片的运算空间拆成小块分别处理 取值范围 = 16 ~ (检查点模型能生成的最大图片尺寸 / 8) | 96 | |
| 潜空间分块重叠 | 设置相邻分块的重叠区域,消除拼接缝 MultiDiffusion 方案设置为 32 或 48 Mixture of Diffusers 方案设置为 16 或 32 | 48 | |
| 分块单批数量 | 指定一次同时处理多少个拆分好的小块,数量越少越省显存、越稳定 | 1 | |
| 分区提示词控制 | 把图像按潜空间分块划分为多个区域,给每个区域单独写提示词 | - | |
| Tiled Diffusion 文生图 | 覆盖图像尺寸 | 勾选后按目标分辨率计算分块,可突破原生图片尺寸限制 | - |
| Tiled Diffusion 图生图 | 保持输入图像大小 | 控制图生图的输出尺寸是否与原图一致 用于修复细节勾选,用于超清放大取消勾选 | - |
| 放大倍数 | 放大后图片尺寸 = 原图尺寸 x 放大倍数 | - | |
| 放大算法 | 无约束,优先 Lanczos | Lanczos | |
| 噪声反转 | 高清放大必开,细节修复可选 | - | |
| 反转步数 | 越小越贴近原图,越大创作空间越大 | 10 | |
| 修复程度 | 数值越大越贴近原图 | - | |
| 重铺噪声强度 | 数值越大,越能增加噪声随机性,生成的细节更丰富 数值过高会偏离原图 | ≤0.6 | |
| 重铺噪声大小 | 数值越大,噪声覆盖的区域越广,越适合优化大场景细节 | 64 | |
| Tiled VAE | 编码器分块大小 | 控制 VAE 编码阶段的分块尺寸,单位为潜空间单位 用于降低显存峰值占用,实现大尺寸图像编码 建议在 CUDA error: out of memory 报错前尽可能大的设置其值 | 1024 |
| 解码器分块大小 | 控制 VAE 解码阶段的分块尺寸,单位为潜空间单位 用于匹配编码器分块逻辑,延续显存优化策略 | 192 | |
| 快速编码解码器 | 启用轻量化编解码算法,开启后速度提升 30%-50% | 开启 | |
| 快速编码器颜色修复 | 校准分块色偏,优先开启 | 开启 |
以生成一张人物写实图为例,参考生成参数如下。
生成效果:
将上图发送至图生图,参考生成参数如下。
Tiled Diffusion/Tiled VAE 参考插件参数如下。
生成后对比效果:
超清放大是由 LiblibAI 自带的的类似于 Tiled Diffusion 插件的高清放大功能。
超清放大的核心参数:
Layer diffusion 是由 lllyasviel 团队推出的 Stable Diffusion 扩展技术,能让 Stable Diffusion 支持原生生成带 Alpha 通道的透明图像与多图层内容,无需额外抠图,适配 SD 1.5/XL,大幅提升设计类图像的生产效率。
本地部署的 Stable Diffusion 需要自行安装 Layer diffusion 插件,LiblibAI 已内置该插件。
Layer diffusion 的安装与使用:https://github.com/layerdiffusion/sd-forge-layerdiffuse
Layer diffusion 的核心参数:
以生成一张电商产品图为例,参考生成参数如下。
Layer diffusion 参考插件参数如下。
生成效果:
ADetailer(After Detailer)是 Stable Diffusion 的核心细节修复插件,在生成后自动检测人脸、手部等易崩坏区域,通过蒙版 + 局部重绘提升细节,适配 SD1.5/XL,是解决脸崩手残的高效工具。
本地部署的 Stable Diffusion 需要自行安装 ADetailer 插件,LiblibAI 已内置该插件。
ADetailer 的安装与使用:https://github.com/Bing-su/adetailer
ADetailer 的核心参数:
以生成一张人物写实图为例,参考生成参数如下。
生成效果:
调整生成参数如下。
ADetailer 参考插件参数如下。
生成效果:
Inpaint Anything 是一款基于 Segment Anything Model(SAM)的智能局部重绘插件,核心是点击即分割、文本控生成,无需手动精细绘制蒙版,即可精准移除、替换或填充图像中任意物体、区域,适配物体移除、背景替换、局部内容生成等场景。
本地部署的 Stable Diffusion 需要自行安装 Inpaint Anything 插件,LiblibAI 已内置该插件。
Inpaint Anything 的安装与使用:https://github.com/Uminosachi/sd-webui-inpaint-anything
下图原始尺寸为 1024x1024,以下图为例进行局部重绘。
打开 Inpaint Anything 插件,将需要重绘的图片上传至 Inpaint Anything 插件,确认已选好 SAM 模型,点击 Run Segment Anything,生成彩色分割图。
在彩色分割图中,使用画笔工具涂抹或点击分割图中需重绘的目标区域,点击创建蒙版,下方会显示选中的蒙版区域。
在蒙版区域中,根据实际情况修剪、添加蒙版。
切换到仅蒙版标签,点击获取蒙版,再点击发送到图生图重绘,在图生图页面进一步调整参数。
以上图为例进行图生图,参考生成参数如下。
生成效果:
PNG 图片信息是核心实用功能,可以读取由 Stable Diffusion 平台生成的 PNG 图片中内嵌的生成元数据,快速复用这些参数到其他功能模块,不管是复刻自己的作品,还是学习他人的创作参数都很便捷。
只有 Stable Diffusion 生成且未清除元数据的 PNG 图才能读取到这些元信息,非 Stable Diffusion 生成或二次编辑、重新保存导致元数据丢失的图片,无法读取到对应内容。
PNG 图片信息功能仅针对 PNG 图的元数据做读取,并非通过 AI 反推图像参数,和 CLIP 反推、DeepBooru 反推、WD 1.4 标签器等提示词反推功能有着本质区别。
如果想保护自己的创作参数不被他人读取,可通过 Photoshop 等工具重新导出图片,这样会清除图片中的生成元数据。
]]>