REC
首页
文章分类
源码资源
技术教程
程序软件
文创娱乐
玄学修炼
关于我们
其他页面
网站统计
友情链接
用户留言
高清壁纸
关于易航
热门文章
Joe再续前缘主题 - 本站同款
易航网址导航系统 – 功能强大,轻量易用
Js自动播放HTML音乐(不受浏览器限制,无需先与浏览器交互,无需对浏览器进行修改)
网易云官方歌曲解析接口
JsonDb-PHP轻量级文件数据库系统
标签搜索
PHP
Web前端
网站源码
PHP源码
Typecho
课程资料
武术内功
HTML源码
Windows程序
Web
Android软件
Typecho插件
Joe主题
国漫
网络协议
MySQL
Python
NodeJs
Windows
小说
发布
登录
注册
找到
45
篇与
PHP
相关的结果
- 第 2 页
2024-12-24
PHP自建MD5解密平台
使用 PHP 构建 MD5 彩虹表生成器的完整过程 在信息安全领域,彩虹表(Rainbow Table) 是一种通过预计算哈希值和对应原始值的方式来破解密码的工具。为了实现一个简单高效的 MD5 彩虹表生成器,我使用了 PHP 和 MySQL,本文将详细介绍整个实现过程,并深入探讨如何解决开发中遇到的问题。 项目背景和需求 在项目的初始阶段,我们需要一个自动化生成 MD5 彩虹表的工具,并将生成的数据存储在 MySQL 数据库中。主要功能包括: 批量生成 MD5 哈希和对应的原始字符串 去重处理,避免重复存储相同的 MD5 哈希 可扩展性,支持任意字符集和字符串长度。 高效插入数据,避免性能瓶颈。 然而,在实现的过程中遇到了两个关键问题: 每次刷新页面时,因没有去重导致重复数据大量生成。 设置批量生成的目标条数(如 10,000 条),但数据量却无法稳定在目标值。 接下来,我们将详细拆解整个解决方案和代码实现。 环境准备 确保开发环境的搭建,包括: PHP 7.x或更高版本 MySQL 5.x或更高版本 Apache或Nginx服务器 数据库设计 在生成彩虹表之前,我们需要设计存储数据的数据库表。 数据表结构 表名为 rainbow_table,包含以下字段: id: 自增主键,用于标识每条记录。s hash: 存储 MD5 哈希值。 original: 存储原始字符串。 unique_hash: 创建唯一约束,确保哈希值不重复。 SQL 表的创建代码如下: CREATE TABLE rainbow_table ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, hash VARCHAR(32) NOT NULL, original VARCHAR(255) NOT NULL, UNIQUE KEY unique_hash (hash) );如果表不存在,我们会在 PHP 脚本中动态创建它,确保代码的鲁棒性。 PHP 脚本实现 核心逻辑概述 字符集配置:可以自由定义生成字符串所使用的字符集,包括大小写字母、数字和特殊符号。 随机生成字符串:通过随机组合字符,生成指定长度的字符串。 MD5 哈希计算:将随机字符串计算为 MD5 哈希值。 数据插入与去重:使用 INSERT IGNORE 避免重复插入。 批量生成与页面自动刷新:每次生成一定数量的数据后自动刷新页面,持续生成。 完整 PHP 代码如下: <?php $servername = "localhost"; $username = "md5"; $password = "123456"; $dbname = "md5"; $tableName = "rainbow_table"; // 创建数据库连接 $conn = new mysqli($servername, $username, $password, $dbname); // 检查连接是否成功 if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 检查表是否存在,如果不存在则创建 $tableExists = $conn->query("SHOW TABLES LIKE '$tableName'")->num_rows > 0; if (!$tableExists) { $createTableSql = "CREATE TABLE $tableName ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, hash VARCHAR(32) NOT NULL, original VARCHAR(255) NOT NULL, UNIQUE KEY unique_hash (hash) )"; if ($conn->query($createTableSql) === TRUE) { echo "表 $tableName 创建成功<br>"; } else { die("创建表错误: " . $conn->error); } } // 彩虹表生成函数 function generateRainbowTable($charset, $batchSize, $conn, $tableName) { $charsetLength = strlen($charset); $count = 0; $maxLength = 18; // 设置随机字符串最大长度 while ($count < $batchSize) { // 随机生成字符串长度 $length = rand(1, $maxLength); $count += generateRandomCombination($charset, $length, $charsetLength, $conn, $batchSize - $count, $tableName); } echo "生成了 $count 条记录\n"; } function generateRandomCombination($charset, $length, $charsetLength, $conn, $remaining, $tableName) { if ($remaining <= 0) return 0; $currentString = ''; for ($i = 0; $i < $length; $i++) { $currentString .= $charset[rand(0, $charsetLength - 1)]; } $hash = md5($currentString); // 使用 INSERT IGNORE 避免重复插入 $stmt = $conn->prepare("INSERT IGNORE INTO $tableName (hash, original) VALUES (?, ?)"); $stmt->bind_param("ss", $hash, $currentString); $stmt->execute(); return $stmt->affected_rows > 0 ? 1 : 0; } // 配置 $charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.@#*?!$%^&()-_=+[]{}|;:,.<>~'; // 定义字符集 $batchSize = 2000; // 每次生成 2000 条 generateRainbowTable($charset, $batchSize, $conn, $tableName); $conn->close(); ?>关键点解析 1. 随机生成字符串 $length = rand(1, $maxLength); $currentString .= $charset[rand(0, $charsetLength - 1)];使用 rand() 随机生成字符串长度,再通过字符集随机组合字符,生成目标字符串。 2. 避免重复插入 $stmt = $conn->prepare("INSERT IGNORE INTO $tableName (hash, original) VALUES (?, ?)");使用 INSERT IGNORE 确保插入数据时,遇到重复哈希值会自动跳过,避免浪费资源。 3. 批量生成与计数 $count += generateRandomCombination($charset, $length, $charsetLength, $conn, $batchSize - $count, $tableName);每次生成一定数量的数据,直到达到目标批量数量。 前端自动刷新页面 为了实现自动化生成,我们在前端页面使用 JavaScript 设置定时刷新,每次刷新生成一批数据: <script> // 页面加载完成后自动刷新 window.onload = function() { setTimeout(function() { location.reload(); }, 1000); // 1秒后刷新页面 }; </script>通过这种方式,可以在页面刷新时持续调用生成函数,直到数据库存储满足预期需求。 问题与优化方案 问题 1:重复数据导致效率低下 最初代码未去重,每次刷新生成的大量数据包含重复项,浪费了存储和计算资源。通过添加 INSERT IGNORE 和数据库唯一索引,解决了此问题。 问题 2:生成数据量不足 由于生成逻辑中可能因重复数据导致插入失败,数据总量无法达到目标条数。通过调整随机生成逻辑,确保生成字符串更加分散,提高了数据覆盖率。 结论 本文通过详细介绍一个 PHP 实现的 MD5 彩虹表生成器,展示了从数据库设计到代码优化的完整流程。通过随机生成字符串、去重插入以及前端自动刷新机制,实现了高效的批量生成工具。 该工具不仅适用于 MD5,还可拓展为其他哈希算法生成器(如 SHA-1 或 SHA-256)。未来可进一步优化数据生成算法,提高生成速度和覆盖范围。 最后我的MD5解密平台:隐藏内容,请前往内页查看详情 图片 项目地址 隐藏内容,请前往内页查看详情
源码资源
技术教程
# 网站源码
# PHP源码
# PHP
易航
1年前
1
33
1
2024-12-17
全新重构聚支付系统免费版
全新重构聚支付系统最新内测版意外流出! 而且是免费版本,没有授权什么的乱七八糟的东西 源码简介 全新超好看后台UI,有图有真相,必须赞一波 巨好看的后台全面统计 有数据大屏功能和数据地区统计功能 支持订单投诉和投诉管理 支持用户组功能并且用户可以自定义购买套餐 全新首页模板高达12个并且支持自定义切换 支持支付封控检测高达三十多种支付插件,支持支付通道轮训 商户系统支持个人实名和企业实名功能 总之就是彩虹易支付该有的功能都有,彩虹易支付没有的功能也有 环境配置 PHP:8.1 MySql:5.6+ 源码截图 图片 图片 图片 源码下载 隐藏内容,请前往内页查看详情
免费资源
源码资源
# 网站源码
# PHP源码
# PHP
易航
1年前
3
54
0
2024-12-10
PHP 实现 Wget 在线仿站工具
引言 项目的核心是使用PHP处理用户请求,通过SSH连接服务器执行爬取命令,并将结果发送到用户邮箱。 功能概述 该工具具备以下功能: 输入有效的URL和邮箱。 验证URL格式。 通过SSH连接执行Wget命令抓取网页。 生成ZIP文件并通过邮箱通知用户。 页面结构 页面使用Bootstrap框架实现响应式设计。以下是页面的基本HTML结构示例: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>在线仿站工具</title> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css"> </head> <body> <nav class="navbar sticky-top navbar-expand-lg navbar-light bg-white border-bottom"> <div class="container"> <a class="navbar-brand" href="./">在线仿站工具</a> </div> </nav> <div class="container mt-5"> <div class="row"> <div class="col-md-8 offset-md-2"> <input type="text" id="url" class="form-control" placeholder="请输入有效的网址" required /> <input type="text" id="email" class="form-control mt-2" placeholder="请输入有效的邮箱" required /> <input id="submit" type="button" value="提交任务" class="btn btn-primary btn-block mt-3" /> </div> </div> </div> <script src="./assets/js/common.js"></script> </body> </html>图片 后端逻辑 后端使用PHP实现,主要功能集中在api.php文件中。以下是该文件的核心代码示例: 1. 请求处理 首先,我们检查请求方法是否为POST,并获取URL和邮箱: <?php if ($_SERVER['REQUEST_METHOD'] !== 'POST') { exit(json_encode(array('code' => '-1', 'msg' => '仅支持POST请求'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); } $url = $_POST['url']; $email = $_POST['email'];2. URL验证 使用正则表达式验证输入的URL格式,确保用户输入的是有效的URL: $preg = "/^http(s)?:\\/\\/.+/"; if (!preg_match($preg, $url)) { log_error("Invalid URL format: $url"); exit(json_encode(array('code' => '-1', 'msg' => '域名请带上协议头!如(http:// 或 https://)'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); }3. 生成文件名 生成唯一的文件名以便于后续的下载: $timestamp = time(); $file = "website_$timestamp.zip";4. 执行SSH命令 通过自定义的SSH类连接到服务器并执行Wget命令: $ssh = new Components_Ssh($host, $user, $pass, $port, $log); $command = escapeshellcmd("bash /www/wwwroot/{$site_url}/wget_site.sh {$url} {$file} >/dev/null && echo \"success\""); $result = $ssh->cmd($command);5. 检查文件生成状态 检查文件是否成功生成,若未生成,则记录错误信息: if (!file_exists('./down/' . $file)) { log_error("File generation failed for: $url"); exit(json_encode(array('code' => '-1', 'msg' => '爬取失败,请稍后再试。'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); }6. 发送邮件通知 发送爬取结果到用户邮箱的代码如下: $content = '爬取成功,下载链接:' . $site_url . '/down/' . $file; $wz = $smtpapi . "?adress=" . urlencode($email) . "&isHTML=false&title={$site_url}爬取成功&content=" . urlencode($content); $response = @file_get_contents($wz);7. 错误日志记录 使用自定义的log_error函数记录所有错误信息,确保系统的可维护性: function log_error($message) { error_log(date('Y-m-d H:i:s') . " - " . $message . "\n", 3, '/path/to/error.log'); }8. SSH连接类 以下是一个简单的SSH连接类示例,供后续使用: class Components_Ssh { private $connection; public function __construct($host, $user, $pass, $port = 22) { $this->connection = ssh2_connect($host, $port); ssh2_auth_password($this->connection, $user, $pass); } public function cmd($command) { $stream = ssh2_exec($this->connection, $command); stream_set_blocking($stream, true); return stream_get_contents($stream); } }9. Wget脚本示例 wget_site.sh脚本负责执行实际的爬取操作,代码示例如下: #!/bin/bash url=$1 file=$2 wget --mirror --convert-links --adjust-extension --page-requisites --no-parent $url -P /www/wwwroot/your_site/down/ zip -r /www/wwwroot/your_site/down/$file /www/wwwroot/your_site/down/*10. 处理返回结果 处理执行命令后的返回结果以便后续使用: if ($result === 'success') { exit(json_encode(array('code' => '1', 'msg' => '爬取任务已提交,请查看邮箱。'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); } else { log_error("Command execution failed: $command"); exit(json_encode(array('code' => '-1', 'msg' => '命令执行失败,请重试。'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); }11. 提交任务前的提示 在前端添加任务提交前的提示,增强用户体验: document.getElementById('submit').onclick = function() { const url = document.getElementById('url').value; const email = document.getElementById('email').value; if (url === '' || email === '') { alert('请填写所有字段!'); return; } fetch('api.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `url=${encodeURIComponent(url)}&email=${encodeURIComponent(email)}` }) .then(response => response.json()) .then(data => { if (data.code === '-1') { alert(data.msg); } else { alert('任务已提交,请查看您的邮箱!'); } }); };12. 邮件发送状态检查 检查邮件发送状态以确保用户能够及时收到通知: if ($response === false) { log_error("Email failed to send to: $email"); exit(json_encode(array('code' => '-1', 'msg' => '邮件发送失败,请检查邮箱地址。'), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); }核心技术 PHP:后端逻辑处理,包括请求处理和SSH命令执行。 SSH:使用SSH连接到服务器进行远程操作。 Wget:爬取网页及其资源的工具。 Bootstrap:用于简化前端布局和样式。 总结 这个在线仿站工具允许用户快速爬取并下载网站资源。关键在于安全地处理用户输入、稳定地执行后端爬取操作,并确保系统的可维护性。
技术教程
# PHP
易航
1年前
0
47
1
2024-12-08
PHP8.1 推出了 fiber,fiber可以实现什么样的操作 ?
PHP 8.1 引入了新的特性 fiber,也称为协程(Coroutines),它为 PHP 提供了一种轻量级的并发编程方式,使得开发者可以更方便地实现异步和并发操作。 Fiber 可以实现以下一些新的操作和用途: 轻量级线程:Fiber 允许在一个单独的 PHP 进程中创建多个轻量级线程,这些线程可以独立地执行不同的任务,实现并发处理,而不需要创建额外的进程或线程。 非阻塞 IO:通过使用 Fiber,可以实现非阻塞的 IO 操作,例如异步读写文件、网络请求等,从而提高 IO 操作的效率,避免程序在 IO 等待时被阻塞。 并发任务处理:Fiber 可以用于处理并发任务,例如在同时进行多个网络请求、数据库查询等任务时,可以使用 Fiber 来管理和协调这些任务的执行,提高处理效率。 轻量级同步:Fiber 可以用于实现轻量级的同步操作,例如在多个 Fiber 之间进行数据交换或共享数据,而不需要使用传统的锁机制。 嵌套调用:Fiber 可以进行嵌套调用,允许在一个 Fiber 中调用另一个 Fiber,从而实现更复杂的异步调用和逻辑。 异步编程:Fiber 可以与异步编程模式结合,例如配合事件循环库,实现更高效的异步编程。 通过引入 Fiber,PHP 可以在单个进程中实现高效的并发处理,而不需要依赖于多线程或多进程,从而减少资源开销和复杂性。这使得 PHP 能够更好地应对高并发和IO密集型的应用场景,例如网络编程、Web服务等。 以下是几个示例代码,展示了 Fiber 可以实现的一些新操作: 1 异步任务处理: 使用 Fiber 可以方便地实现异步任务处理,允许在一个单独的 PHP 进程中并发执行多个任务,提高处理效率。在下面的示例中,我们创建了两个 Fiber 来同时处理两个耗时任务,并在结束后输出结果。 <?php use Fiber\Fiber; function task1() { echo "Task 1 started.\n"; Fiber::suspend(); echo "Task 1 resumed.\n"; Fiber::suspend(); echo "Task 1 finished.\n"; } function task2() { echo "Task 2 started.\n"; Fiber::suspend(); echo "Task 2 resumed.\n"; Fiber::suspend(); echo "Task 2 finished.\n"; } $fiber1 = new Fiber('task1'); $fiber2 = new Fiber('task2'); $fiber1->start(); $fiber2->start(); $fiber1->resume(); $fiber2->resume(); $fiber1->resume(); $fiber2->resume(); ?>2 协程嵌套: Fiber 允许在一个 Fiber 中调用另一个 Fiber,实现协程的嵌套调用。在下面的示例中,我们创建了两个 Fiber,其中一个 Fiber 内部调用了另一个 Fiber。 <?php use Fiber\Fiber; function task1() { echo "Task 1 started.\n"; Fiber::suspend(); echo "Task 1 resumed.\n"; Fiber::suspend(); echo "Task 1 finished.\n"; } function task2() { echo "Task 2 started.\n"; $fiber = new Fiber('task1'); $fiber->start(); $fiber->resume(); echo "Task 2 resumed.\n"; $fiber->resume(); echo "Task 2 finished.\n"; } $fiber2 = new Fiber('task2'); $fiber2->start(); $fiber2->resume(); $fiber2->resume(); ?>3 非阻塞 IO: 使用 Fiber 可以实现非阻塞的 IO 操作,例如异步读写文件。在下面的示例中,我们使用 Fiber 来实现异步读取文件的操作。 <?php use Fiber\Fiber; function readFileAsync() { $file = fopen('example.txt', 'r'); echo "Start reading file.\n"; while (!feof($file)) { echo "Read: " . fgets($file); Fiber::suspend(); } fclose($file); echo "Finish reading file.\n"; } $fiber = new Fiber('readFileAsync'); $fiber->start(); while ($fiber->status() !== Fiber::STATUS_FINISHED) { echo "Resuming fiber...\n"; $fiber->resume(); } echo "Fiber finished.\n"; ?>在上述示例中,我们使用 Fiber 来异步读取文件,每次读取一行数据后就暂停 Fiber,等待下一次恢复。这样可以实现在文件读取过程中不阻塞其他操作的效果。 这些示例只是 Fiber 的一部分用法,实际上 Fiber 提供了更多灵活的协程编程方式,可以用于解决并发问题和异步编程等场景。由于 Fiber 是一个相对较新的特性,它在 PHP 中的使用需要根据具体需求和场景进行谨慎考虑。
技术教程
# PHP
易航
1年前
0
76
0
2024-12-04
PHP 纤程:它真的能实现异步执行吗?
图片 PHP 8.1 引入了 Fibers,这让许多开发者好奇:它能否打破 PHP 作为单线程同步语言的固有局限,让它像 JavaScript 和 Node.js 那样实现异步操作?答案并非简单的肯定或否定:Fibers 本身并不提供真正的异步执行,但它为更高效的任务管理提供了强大的机制。下文将深入探讨这一概念。 什么是 PHP 纤程? PHP 纤程是一种协作式多任务处理机制。它允许你暂停和恢复代码的特定部分,而不会阻塞整个 PHP 进程。你可以把纤程想象成一种特殊的函数,它能够将执行控制权交回主程序,并在需要时从之前暂停的地方继续执行。 纤维的主要特点 可启动、暂停和恢复执行。 在单一的 PHP 进程内运行,不涉及多线程。 尤其适用于构建非阻塞代码。 当纤程暂停时会发生什么? 当使用 Fiber::suspend() 暂停纤程时,执行控制权会返回主 PHP 脚本。这意味着: 主程序可以继续执行其他部分。 纤程的执行暂停,直到被 resume() 唤醒。 例如: $fiber = new Fiber(function () { echo "Fiber started\n"; Fiber::suspend(); echo "Fiber resumed\n"; }); echo "Before Fiber\n"; $fiber->start(); echo "After Fiber Start\n"; $fiber->resume(); echo "After Fiber Resume\n";输出: Before Fiber Fiber started After Fiber Start Fiber resumed After Fiber Resume以下是具体情况 1、Fiber::suspend() 暂停纤程,并将执行控制权返回到启动纤程的主脚本 ($fiber->start() 之后的代码)。 2、主脚本继续执行。 3、当调用 resume() 时,纤程从暂停处恢复执行,直至完成。 恢复纤程是否会阻塞主进程? 调用 Fiber::resume() 恢复纤程会暂时阻塞主进程。这意味着: 在纤程完成或再次暂停之前,脚本的其他部分(或其他纤程)无法执行。 由于 PHP 的单线程特性,纤程的执行仍然是阻塞式的。 尽管纤程提供了更灵活的控制,但它并没有改变 PHP 的底层执行模型。 例如: $fiber = new Fiber(function () { echo "Processing Fiber...\n"; sleep(2); // Simulates a blocking task echo "Fiber Done\n"; }); echo "Before Fiber\n"; $fiber->start(); echo "Between Fiber Start and Resume\n"; $fiber->resume(); echo "After Fiber\n";输出: Before Fiber Processing Fiber... Fiber Done Between Fiber Start and Resume After Fiber在此示例中,纤程在调用 sleep(2) 期间会阻塞主进程。 因此,尽管纤程提供了一种更有效地组织代码的方式,但它们并不会神奇地实现并行处理或真正的异步执行。 它们只是提供了一种在单线程环境下更精细地控制执行流程的机制。 光纤如何仍然“不阻塞”? 纤程的“非阻塞”并非指并行执行,而是指其更优的任务管理能力。纤程暂停时不会阻塞主进程,而是将控制权交还给主脚本或事件循环。 这在基于事件驱动的库或框架(如 ReactPHP 或 Amp)中尤为有用: 长时间运行或等待的任务(例如数据库查询、API 调用)可以被暂停。 其他任务可以同时进行。 当任务准备好后,纤程会被恢复并继续执行。 这使得在单线程环境下能够模拟异步行为,从而提升效率。 事件循环和纤程 纤程通常与事件循环结合使用才能实现真正的非阻塞操作。事件循环负责跟踪多个任务并决定下一步执行哪个任务。其工作原理如下: 当遇到阻塞任务(例如数据库查询)时,纤程自动暂停。 事件循环选择并处理其他任务。 阻塞任务完成后,事件循环恢复相应的纤程。 像 Amp 和 ReactPHP 这样的库正是利用纤程和事件循环来实现异步任务处理。 为什么 Fiber 不是真正异步的 与 JavaScript 或 Node.js 中的异步编程(任务可以通过线程或事件循环并行运行)不同,PHP 纤程: 在单个 PHP 进程内同步执行。 通过允许开发者手动控制任务的暂停和恢复来实现协作式多任务处理。 换句话说: 纤程不引入并行性(任务仍然按顺序逐个执行)。 它们是一种更有效地管理和构建非阻塞代码的工具,而非真正的并行机制。 它们提供了一种在单线程环境下模拟异步行为的方式。 尽管 PHP 纤程本身并不能使 PHP 真正实现异步,但它们仍然是该语言的有力补充。原因如下: 1、改进的任务管理:纤程允许暂停和恢复任务,从而释放主进程去处理其他工作。 2、非阻塞工作流: 与事件循环结合使用时,纤程可以实现非阻塞任务处理,提升程序的并发性能。 3、同步执行的便利性: 恢复时,纤程同步执行,简化了代码逻辑,尽管会暂时阻塞进程。 这使得开发者无需处理复杂的回调或 Promise,就能以更线性的方式编写异步代码。 对于需要高效多任务处理的 PHP 应用(例如实时应用、后台作业或 API),纤程是一项重要的改进。它能够更好地管理任务并模拟异步行为。 然而,要实现真正的并行处理,仍然需要依赖外部解决方案,例如扩展或单独的进程来实现多线程。
技术教程
# PHP
易航
1年前
0
52
0
2024-12-03
PHP 8.4 正式发布!🧨
图片 PHP 8.4 第一个正式发布版本今天发布。PHP 8.4 在很大程度上向后兼容 PHP 8.0 到 8.4,并带来了一些新功能。 PHP 8.4 新增/变更功能 curl_getinfo 支持 CURLINFO_POSTTRANSFER_TIME_T curl_version() 支持 feature_list 新增 http_(get|clear)_last_response_headers 函数 新增 CURLOPT_PREREQFUNCTION 选项 新增 CURLOPT_DEBUGFUNCTION 选项 新增 CURLOPT_SERVER_RESPONSE_TIMEOUT 选项,以替换 CURLOPT_FTP_RESPONSE_TIMEOUT 新增 CURLOPT_TCP_KEEPCNT 选项 新增round()函数 新增 mb_trim、mb_ltrim 和 mb_rtrim 函数 DateTime(Immutable) 类新增 createFromTimestamp 方法 phpinfo 显示 PHP 整数大小信息 DateTime(Immutable) 类新增 get/setMicrosecond 方法 新增函数 request_parse_body PCRE2 升级及相关正则表达式变化 PHP 8.4 语法/功能变更 OpenSSL:最低要求的 OpenSSL 版本提升至 1.1.1 MBString:Unicode 字符数据库更新至版本 16 exit/die 从语言构造变为函数 CURLOPT_DNS_USE_GLOBAL_CACHE 不再有效 密码哈希:默认 Bcrypt 成本从 10 变为 12 PHP_ZTS 和 PHP_DEBUG 常量值类型从 int 变为 bool Opcache:JIT 启用方式的 INI 变更 round() 函数:无效的舍入模式将抛出 \ValueError 异常 Curl:最低要求的 libcurl 版本提升至 7.61.0 PHP 8.4 弃用功能 隐式可为空的参数声明被弃用 E_STRICT 常量被弃用 调用 session_set_save_handler() 时使用超过 2 个参数被弃用 CSV:必须提供 $escape 参数 CURLOPT_BINARYTRANSFER 被弃用 PHP 8.4 移除功能 Pspell 扩展从 PHP 核心移至 PECL IMAP 扩展从 PHP 核心移至 PECL OCI8 和 PDO-OCI 扩展从 PHP 核心移至 PECL
技术教程
# PHP
易航
1年前
1
109
0
2024-11-30
PHP 8.4 新功能
图片 PHP 8.4 的正式发布计划于下周,即 2024 年 11 月 21 日发布。在此次发布之前,一系列预发布版本(Alpha、Beta 和候选版本)允许社区测试新功能并进行最后一刻的调整。PHP 8.4 引入了多项改进,包括用于操作数组的新功能、受其他语言启发的属性钩子以及简化的语法。让我们一起回顾一下此版本中要记住的新功能。 Property Hooks Property Hooks 是 8.4 版中引入的主要功能之一。PHP 实现的灵感来自其他语言(如 Kotlin、C#、Swift、Javascript 或 Python)中的现有实现。让我们举几个例子来说明 Property Hooks 的用途以及如何使用它们: <?php declare(strict_types=1); class Foo { private string $id; public function getId(): string { return $this->id; } public function setId(string $id): void { $this->id = $id; } }从 PHP 8 开始,由于 Constructor Property Promotion,可以通过以下方式进行简化: <?php class Foo { function __construct(public string $id) {} }在我们必须保留访问器 (getter/setter) 的情况下,我们会考虑包含业务逻辑的丰富模型,我们失去了更轻量级语法的优势。PHP 版本 8.4 和引入的 Property Hooks 修复了这个问题: <?php class Foo { public function __construct( public string $id { get { return '#' . $this->id; } set(string $id){ $this->id = mb_strtoupper($id); } }, ){} }乍一看,语法似乎令人困惑,但就像任何语法演变一样,随着时间的推移,您会习惯它。 Property Hooks 引入的另一种可能性是能够在 property 上定义接口。 使用这个新版本的 PHP,我们可以编写以下定义: <?php interface HasId { public string $id { get; set; } } // Les fonction fléchées peuvent être aussi utilisées pour raccourcir la syntaxe class Foo implements HasId { function __construct( public string $id { get => '#' . $this->id; set (string $id) => $this->id = mb_strtoupper($id); }, ) {} } // Le contrat d’interface est également respecté sans l’utilisation des Property Hooks en déclarant publiquement la propriété class Bar implements HasId { function __construct(public string $id) {} }一个完整的案例 <?php declare(strict_types=1); interface HasId { public string $id { get; set; } } class Foo implements HasId { function __construct( public string $id { get => '#' . $this->id; set (string $id) => $this->id = mb_strtoupper($id); }, ) {} } class Bar implements HasId { function __construct(public string $id) {} } class Baz { public function display(HasId $object): void { echo $object->id . PHP_EOL; } public function update(HasId $object, string $id): void{ $object->id = $id; $this->display($object); } } $foo = new Foo(id: 'FOO'); $bar = new Bar(id: 'BAR'); $baz = new Baz(); $baz->display($foo); $baz->update($foo, 'foo'); $baz->display($bar); $baz->update($bar, 'bar');设置具有非对称可见性的类属性的可见性 非对称可见性 允许您根据相关操作是读取还是写入属性,对同一属性设置不同的可见性。然后,可以定义读取访问的公共可见性和写入访问的更受限的可见性(受保护或私有)。接下来的两个类是等效的,随着非对称可见性的引入,语法更加简洁。 <?php class Foo { function __construct(private string $id,) { // } public function getId(): string { return $this->id; } } class Bar { function __construct( public private(set) string $id, ) {} }不对称可见性附带一些规则,这些规则很容易理解: 属性必须被类型化(来自 PHP 实现的约束) 只关注对象属性,静态属性不能从中受益(这也是 PHP 实现产生的约束)。 对于对象属性,如果该属性设置为 private(set),则不能在与当前类不同的范围内修改链接对象。但是,如果链接对象的属性被定义为 Properties,则可以对其进行修改。 对于数组类型属性,如果该属性已设置为 private(set),则无法在当前类的范围之外操作数组(添加元素、删除元素等)。 set 的可见性不能比 get 的可见性更宽。 对于类继承或接口协定,可见性不能更严格,也可以更广泛。 在 readonly中定义的属性(在 PHP 8.1 中引入)和 public private(set) 中定义的属性之间的差异非常小,但值得一提。上面定义的不对称可见性将具有相同的效果,只是它允许内部更改。换句话说, readonly 限制了 mutation,并且在实例化期间还具有唯一写入的效果。 管独立于 Property Hook 运行,但这两种机制可以结合使用。此处提供了这两种功能的示例。 对惰性对象的原生支持 惰性对象 是其实际实例化将被推迟到实际需要的时间(因为它们的实例化通常很昂贵)的对象。出于性能原因,它们在 Doctrine 和 Symfony 中被大量使用。 Martin Fowler 在他的理论定义中建立了四种可能的实现。其中两个是不需要修改现有对象的实现:Ghost 和 Proxy。这些是通过在 PHP Reflection API 中添加方法保留和访问的。 在这两种情况下,都会创建一个初始化函数。对于 Ghosts,该函数将直接作用于对象。对于 Proxy,它是实例化惰性对象的函数,然后将交互反馈给真实实例。 在这两种情况下,实例化机制都是通过访问真实对象的 state 来触发的:读取或写入属性、测试属性是否具有值、克隆等。可以通过特定函数对特定属性禁用此行为,在某些情况下,可以定义或参数化,例如用于调试或序列化。 由于它是为非常有限且根据定义相当抽象的用例保留的,因此我们邀请您阅读 RFC 以发现代码示例和两种不同实现的详细功能。 不带括号的类实例化 更有趣的是,这种演变通过在实例化新对象时使括号变得多余,从而减轻了语法的负担。 <?php // Avant et toujours valide $o = (new Operation(0))->add(10)->multiply(2); // Depuis PHP 8.4 $o = new Operation(0)->add(10)->multiply(2);解析 HTML5 创建了一个新的 DOM\HTMLDocument 类来允许 HTML5 解析,为了确保与 HTML4 的向后兼容性,当前类将保持不变。这两个类保持相同的 API,因此可以以相同的方式使用。只有构造逻辑已更改,并且需要使用其中一个可用的工厂。用 C 语言编写的底层库是 Lexbor。 新的函数 添加了四个作用于数组的新函数,它们补充了现有函数。 array_find array_find 将返回传递给它的回调函数的第一个匹配项 <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_find($array, static fn(string $value): bool => strlen($value) > 2);// returns AAA array_find($array, static fn(string $value): bool => strlen($value) > 3);// returns null array_find($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns 1array_find_key array_find_key 的工作方式与上一个函数相同,但返回 key 而不是 value: <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_find_key($array, static fn(string $value): bool => strlen($value) > 2); // returns 2 array_find_key($array, static fn(string $value): bool => strlen($value) > 3); // returns null array_find_key($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns Aarray_any 如果数组中至少有一个元素与回调函数匹配,array_any 将返回布尔值 true: <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_any($array, static fn(string $value): bool => strlen($value) > 2)); // returns true array_any($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns truearray_all 如果数组中的所有元素都与回调函数匹配,array_all 将返回布尔值为 true <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_all($array, static fn(string $value): bool => strlen($value) < 4)); // returns true array_all($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns true改进和错误修复 除其他事项外,我们保留了以下更改: 添加了新的多字节函数来操作字符串 mb_trim、mb_ltrim、mb_rtrim、mb_ucfirst mb_lcfirst。 添加了用于从时间戳创建 DateTime 对象的新函数。 exit 和 die 的元素失去了它们的地位,取而代之的是特殊功能。在不破坏向后兼容性的情况下,这允许对函数进行类似的操作,例如,更精确地键入输入参数。 以下扩展正在从核心中移出以加入 PECL:Pspel、IMAP、OCI8 和 PDO-OCI。 为舍入功能添加了四种新的舍入模式 在 Sodium 中添加了两种新的加密算法,并升级了 OpenSSL。 添加了 cURL 的新选项。 完整的更新日志:https://www.php.net/ChangeLog-8.php
技术教程
# PHP
易航
1年前
0
55
0
2024-11-20
提升PHP技术:18个实用高级特性
掌握PHP基础知识只是第一步。 深入了解这18个强大的PHP特性,将显著提升您的开发效率和代码质量。 超越 __construct() 的魔法方法 虽然 __construct() 为大多数开发者所熟知,PHP 却提供了更多强大的魔术方法,例如: class DataObject { private array $data = []; // 设置不可访问的属性时调用 public function __set($name, $value) { $this->data[$name] = $value; } // 获取不可访问的属性时调用 public function __get($name) { return $this->data[$name] ?? null; } // 对不可访问的属性使用 isset() 时调用 public function __isset($name) { return isset($this->data[$name]); } // 序列化对象时调用 public function __sleep() { return ['data']; } }生成器和收益 使用生成器迭代大型数据集,显著降低内存消耗 function readHugeFile($path) { $handle = fopen($path, 'r'); while (!feof($handle)) { yield trim(fgets($handle)); } fclose($handle); } // 用法 foreach (readHugeFile('large.txt') as $line) { echo $line . PHP_EOL; }匿名类 可以使用匿名类创建无需正式声明的单例实例 $logger = new class { public function log($message) { echo date('Y-m-d H:i:s') . ": $message\n"; } }; $logger->log('发生了一些事');属性(PHP 8+) 代码的元数据注释: #[Route("/api/users", methods: ["GET"])] #[Authentication(required: true)] class UserController { #[Inject] private UserService $userService; #[Cache(ttl: 3600)] public function getUsers(): array { return $this->userService->getAllUsers(); } }纤程并发 PHP 8.1+中的协作式多任务处理: $fiber = new Fiber(function(): void { $value = Fiber::suspend('suspended'); echo "Value: $value\n"; }); $value = $fiber->start(); echo "Fiber suspended with: $value\n"; $fiber->resume('resumed');带有空合并的方法链 优雅地处理可能返回 null 的方法链调用 class User { public function getProfile() { return new Profile(); } } $user = null; $result = $user?->getProfile()?->getName() ?? 'Anonymous';动态属性访问 变量属性和方法名称: class DataAccess { private $name = 'John'; private $age = 30; public function getValue($property) { $getter = 'get' . ucfirst($property); return $this->$getter(); } public function getName() { return $this->name; } }可调用函数和闭包 高级功能处理: $multiply = Closure::bind( function($x) { return $x * $this->multiplier; }, new class { public $multiplier = 2; } ); echo $multiply(5); // 输出: 10特征组成 在类之间复用复杂的业务逻辑 trait Timestampable { private $createdAt; private $updatedAt; public function touch() { $this->updatedAt = new DateTime(); } } trait SoftDeletable { private $deletedAt; public function softDelete() { $this->deletedAt = new DateTime(); } } class User { use Timestampable, SoftDeletable { Timestampable::touch insteadof SoftDeletable; } }命名参数 使用PHP 8更清晰的函数调用: function createUser( string $name, string $email, ?string $role = null, bool $active = true ) { // 实现 } createUser( email: 'john@example.com', name: 'John', active: false );一等可调用函数 PHP 8.1 的简化调用语法: class Math { public function add($a, $b) { return $a + $b; } } $math = new Math(); $add = $math->add(...); echo $add(5, 3); // 输出: 8枚举 PHP 8.1中的类型安全枚举: enum Status: string { case DRAFT = 'draft'; case PUBLISHED = 'published'; case ARCHIVED = 'archived'; public function color(): string { return match($this) { Status::DRAFT => 'gray', Status::PUBLISHED => 'green', Status::ARCHIVED => 'red', }; } }属性类型强制转换 自动类型转换: class Config { private int $timeout = '60'; // 自动将字符串转换为 int private float $rate = '0.5'; // 自动将字符串转换为浮点数 }引用返回值 通过函数返回修改值: class Collection { private array $items = []; public function &getItem($key) { return $this->items[$key]; } } $collection = new Collection(); $item = &$collection->getItem('key'); $item = 'new value'; // 修改原始数组后期静态绑定 静态调用的正确继承: class Parent { public static function who() { return static::class; } } class Child extends Parent { } echo Child::who(); // 输出: Child操作码缓存 通过字节码缓存进行性能优化: // php.ini configuration opcache.enable=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.validate_timestamps=0预加载 永久内存类加载(PHP 7.4+): // preload.php opcache_compile_file(__DIR__ . '/vendor/autoload.php'); opcache_compile_file(__DIR__ . '/app/Models/User.php');反射API 运行时代码检查与修改: class Inspector { public static function getPropertyTypes($class) { $reflection = new ReflectionClass($class); $properties = []; foreach ($reflection->getProperties() as $property) { $type = $property->getType(); $properties[$property->getName()] = $type ? $type->getName() : 'mixed'; } return $properties; } }结论 掌握这些高级PHP特性,将显著提升您的代码质量、开发效率和问题解决能力,从而构建更优雅、高效且易于维护的PHP应用程序。
技术教程
# PHP
易航
1年前
0
36
0
2024-11-14
PHP函数对象编程 FOP 的替代方案是什么?
函数对象编程(FOP)是一种利用函数作为对象的编程模式。它通常用于定义回调函数,用于在事件触发或其他条件满足时执行特定操作。 虽然 FOP 在某些情况下非常有用,但它也有一些缺点,包括可维护性差、可读性差以及难以调试。 以下是一些函数对象编程的替代方案: 匿名函数 匿名函数是一种没有名称的函数。它们可以使用 lambda 表达式或箭头函数来定义。匿名函数对于快速定义和使用小函数非常有用。 // lambda 表达式 $sum = function(int $a, int $b) { return $a + $b; }; // 箭头函数 $sum = fn(int $a, int $b) => $a + $b;类方法 类方法可以用来定义回调函数。类方法的好处是它们具有更好的可维护性并且更容易调试。 class MyClass { public function sum(int $a, int $b) { return $a + $b; } } $myClass = new MyClass(); $sum = [$myClass, 'sum'];闭包 闭包是一种函数,可以访问它的作用域之外的变量。闭包非常适合在多个函数之间共享状态。 $x = 10; $closure = function() use ($x) { return $x + 2; };实战案例 假设我们想要定义一个回调函数,用于打印字符串。我们可以使用以下方法: 函数对象编程: $callback = new class { public function __invoke(string $message) { echo $message; } }; 匿名函数: $callback = fn(string $message) => echo $message; 闭包: $callback = function(string $message) { echo $message; }; 类方法: class MyClass { public function printMessage(string $message) { echo $message; } } $myClass = new MyClass(); $callback = [$myClass, 'printMessage'];哪种方法最适合取决于具体情况。一般来说,匿名函数和闭包对于小型回调函数是最好的选择,而类方法对于大型回调函数或需要访问外部状态的回调函数是最好的选择。
技术教程
# PHP
易航
1年前
0
22
0
上一页
1
2
3
...
5
下一页