PHP基础3(错误处理,正则表达式,反序列化,操作mysql,cookie和session)

发布于:2025-06-29 ⋅ 阅读:(17) ⋅ 点赞:(0)

一.前言

前面说了函数和流程控制那些,今天来说一些进阶一点的,错误处理之类的,上一节内容特别多,本章节内容将会少很多。

二.PHP的错误处理

很多时候,代码如果写的不太好,那么很容易报错。那么如果遇到了错误,我们应该想办法捕获到这个 错误并记录下来,而且最好不要用户看到,不然太尴尬了,而且容易暴漏自己服务端的一些敏感信息, 方便我们后续修改,并且尽量不要让整个程序因为一点小错误而崩溃。

2.1配置项管理 

在php.ini配置文件中。我们可以控制php的错误显示状态。php.ini中有一个专门的配置项:

display_errors

这个选项设置是否将错误信息输出到网页,或者对用户隐藏而不显示。在生产上必须要关闭显示错误, 开发的时候可以打开方便调试。

这个值的状态为on 或者 off,也可以设值为1 或者0。

display_errors的值设为0或者off则不在页面中显示错误,如果设为1或者on则显示错误信息。 

问题:如果没有修改服务器php.ini的状态权限怎么办?

那么可以在每个代码文件中使用ini_set方法来进行设置,其实php.ini中的各种配置都可以在代码中进行 动态控制。

<?php

        ini_set('display_errors' , 0 );

        //$a = $GET['xxxx']; 这个错误就不显示了。

?> 

上面的代码也相当于修改了php.ini中display_errors的值。不过,仅仅在当前php代码中生效。 

问题:想取得php.ini的配置项状态怎么办?

可以使用ini_get(参数项) 得到参数的值。

演示例子:

<?php 
    echo '服务器中display_errors的状态为' . ini_get('display_errors'); 
?>

注:如果我们修改完php.ini文件中的配置,想让配置生效的话,需要在修改完php.ini文件后重启服务器。

2.2 错误级别

【掌握级别的错误类型】 ,可以控制哪些级别的错误可以显示或者记录日志,哪些级别的错误不可以显示或者不记录日志。

错误类型 说明
E_ERROR 错误,文件直接中断
E_WARNING 警告,问题比较严重。但是还会继续向下运行
E_NOTICE 提示,有些小问题不会影响到程序。常发生在项目未定义
E_PARSE 编译时语法解析错误。解析错误仅仅由分析器产生
E_ALL 所有的错误
E_STRICT 启用PHP对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性
E_DEPRECATED 启用后将会对在未来版本中可能无法正常工作的代码给出警告

我们介绍一下其中几种:

error最严重,必须要解决。不然程序无法继续向下执行

warning也很重要。但也必须要解决。如果明确的、故意的可以不用处理。

notice 你可以不用管。但是在有些公司,项目标准特别高。在高标准要求的项目中也必须要解决。因为,notice会影响到PHP的执行效率。通常发生在函数未定义等。

parse错误,是指语法错写错了,必须要解决,代表全部类型的所有错误。 

1、 在php.ini中error_reporting参数。如若error_reporting参数设置为0。整个PHP引擎发错误均不会 显示、输出、记录。在后面要讲的日志记录中,也不会记录。

        如果我们想显示所有错误可以写上:

        error_reporting = E_ALL

        想要显示所有错误但排除提示,可以将这个参数写为:

        error_reporting = E_ALL & ~ E_NOTICE

        显示所有错误,但排除提示、兼容性和未来兼容性。可写为:

        error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

2、在有些情况下我们无权限操作php.ini文件,又想要控制error_reporting怎么办呢?在运行的xxxx.php文件中开始处,我们可以使用error_reporting()函数达到目标。

演示代码如下:

<?php

//关闭了所有的错误显示
error_reporting(0);

//显示所有错误
//error_reporting(E_ALL);

//显示所有错误,但不显示提示
//error_reporting(E_ALL & ~ E_NOTICE);

?>

2.3 错误记录日志

 在一些公司里面,有专门的日志收集系统。日志收集系统会在背后默默的帮你收集错误、警告、提示。 也有些公司没有专门的日志收集系统,通过文件来服务器当中的运行日志。

其中:PHP的错误,警告这些是必须要收信的。那么问题来了——不让用户看到,设置好错误报告级别 好,如何将错误收集到日志系统中呢?

这里有需要使用到php.ini的相关配置项。这两个配置项为:

参数 配置项 说明
log_errors on/off 是否开启错误日志记录功能
log_errors_max_len 整型,默认1024B 单条错误日志的最大记录长度
error_log syslog或文件路径 指定错误日志输出到系统日志/文件

说明:

1.在表格中的log_errors和log_errors_max_len非常好理解。

2.而error_log 指定将错误存在什么路径上。配置项中的syslog可能有点不太好理解。syslog是指系统来 记录。windows系统在电脑的事件查看器--应用程序日志。里面。linux默认在: /etc/syslog.conf

[扩展] 了解知识点。若Linux系统启动或修改了日志收集。可能存储在第三方专用的日志收集服务器中。

此外,PHP还为我们专门准备了一个自定义的错误日志函数:

bool error_log ( string $错误消息 [, int $错误消息类型 = 0 [, string $存储目标]] )

这个函数可以把错误信息发送到web服务器的错误日志,或者到一个文件里。

常用的错误消息类型 

错误消息类型 说明
0 发送至默认的error_log指定位置
1 发送到指定的邮件位置
3 发送至指定的文件位置

示例:

<?php

//无法连接到数据库服务器,直接记录到php.ini中的error_log指定位置
error_log("无法连接到数据库服务器服务器");

//可以发送邮件,但是php.ini必须配置过邮件系统
error_log('可以用邮件报告错误,让运维人员半夜起床干活', 1, 'pig@php.cn');

//记录在指定的位置
error_log("我是一个错误哟", 3, "d:/test/my-errors.log");

?>

一般我们手动搭建的apache的默认日志路径是在,重点昂

linux: /etc/httpd/logs/access_log

windows: /Apache/logs/access_log

三.PHP中的正则表达式 

正则表达示我们其实之前经常看到,它主要用在以下一些地方:匹配邮箱、手机号码、验证码、替换敏 感的关键词。例如:涉及政治和骂人的话。

3.1 定界符

PHP的正则表达示定界符的规定如下:

定界符,不能用a-zA-Z0-9\ 其他的都可以用。必须成对出现,有开始就有结束

类型 示例 状态 说明
标准定界符 /中间写正则/ ✅正确 最常用标准格式(推荐优先使用)
符号定界符 $中间写正则$ ✅正确 允许的特殊符号格式
%中间写正则% ✅正确 非字母数字符号可作为定界符
^中间写正则^ ✅正确 特殊符号需成对出现
错误示范 (中间写正则) ❌错误 括号类符号有特殊含义不可使用
A中间写正则A ❌错误 字母数字不可作为定界符

注:\ 是转义字符,如果在以后正则表达示里面需要匹配/,需要把定界符里面的/ 用转义字符转义一 下,写成 / \/ / ,如果你觉得麻烦,遇到这种需要转义的字符的时候可以把两个正斜线(/ /)定界, 改为其他的定界符(# #)。 

3.2 正则表达式的使用

preg_match ( string $正则 , string $字符串 [, array &$结果] )
功能:根据定界符,比如$正则变量,匹配$字符串变量。如果存在则返回匹配的个数,把匹配到的结果 放到$结果变量里。如果没有匹配到结果返回0。

<?php
// 正则匹配示例
$zz = '/wq/'; //正则表达式写在中间,'/正则表达式/'
$string = 'ssssswqaaawqaaa';

if(preg_match($zz, $string, $matches)) {
    echo '匹配到了,结果为:';
    var_dump($matches);
} else {
    echo '没有匹配到';
}

// 正则替换示例
$a = 'hello jaden';
$b = preg_replace('/jaden/', 'wulaoban', $a);
echo $b; // 输出:hello wulaoban
?>

我们常用的正则函数有:

函数名 功能描述
​preg_filter​ 执行正则表达式搜索和替换
​preg_grep​ 返回匹配模式的数组条目
​preg_match​ 执行正则表达式匹配(单次)
​preg_match_all​ 执行全局正则表达式匹配(全部结果)
​preg_replace_callback_array​ 传入数组,执行正则表达式搜索和替换(使用回调函数处理)
​preg_replace_callback​ 执行正则表达式搜索并使用回调函数进行替换
​preg_replace​ 执行正则表达式的搜索和替换
​preg_split​ 通过正则表达式分隔字符串

大家针对这些函数,对着手册用一下。

四.反序列化函数

4.1 面向对象编程(类) 

<?php
header("Content-Type: text/html; charset=utf-8"); // 设置响应头内容类型和字符集

class Fruit {
    var $name1 = 'apple';  // 定义属性
    var $name2 = 'orange';
    
    function chi() {  // 定义方法
        echo '吃水果'.'<br>';
        echo $this->name1.'<br>';
    }
    
    function bo() {  // 普通方法
        echo '剥皮'.'<br>';
    }
    
    // 魔术方法:对象销毁时自动执行
    function __destruct() {
        echo '对象被销毁了'.'<br>';
    }
}

$f = new Fruit();
$f->chi();  // 调用方法

echo '哈哈'.'<br>';

// 被注释的函数
/*
function add() { 
    $f = new Fruit();
    $f->chi();
}
*/
?>

4.2 序列化和反序列化 

<?php
// 序列化,将其他的数据转换成字符串
$a = array('one', 33, 'two');
var_dump($a); // array(3) {[0]=> string(3) "one"[1]=> int(33) [2]=> string(3) "two"}
echo "<br>";

$b = serialize($a);
var_dump($b); // string(43) "a:3:{i:0;s:3:"one";i:1;i:33;i:2;s:3:"two";}"

// 反序列化将序列化的字符串还原成原来的数据类型
$c = unserialize($b);
var_dump($c);

// 类的序列化
class s {
    var $name = "jaden";
    
    function __destruct() {
        echo $this->name;
        //system('ipconfig');
        //echo '<script>alert(123);</script>';
    }
    
    function chi() {
        echo 'xxxxx';
    }
}

$a = new S();
echo $a->name.'aaaa<br>';
echo $a->chi().'<br>';

$b = serialize($a); // 0:1:"s":1:{s:4:"name";s:5:"jaden";}
$c = unserialize($b);
?>

五.PHP操作mysql 

创建表:
# 注意下面插入数据的时候,不要插入中文数据!!!,因为php连接mysql的编码没有设置,容易乱码。

-- 创建数据库
CREATE DATABASE jaden CHARSET utf8mb4;

-- 创建数据表
CREATE TABLE user(
    id INT NOT NULL AUTO_INCREMENT,
    username CHAR(20),
    password CHAR(32),
    reg_time CHAR(36),
    PRIMARY KEY (`id`)
);

-- 插入测试数据
INSERT INTO user(username, password, reg_time)
VALUES('admin', '123456', CURRENT_TIMESTAMP());

INSERT INTO user(username, password, reg_time)
VALUES('wulaoban', '123456', CURRENT_TIMESTAMP());

查询:

<?php
// 连接数据库
$db = mysqli_connect('localhost', 'root', 'root', 'jaden', 3306); 
# 默认端口如果就是3306,那么其实不用写3306

// 定义SQL查询(安全写法)
$sql = "SELECT * FROM user WHERE username='wulaoban'";

// 被注释的变量写法(存在SQL注入风险)
/*
$u = 'wulaoban';
$sql = "SELECT * FROM user WHERE username='$u'";
*/

// 执行SQL语句
$a = mysqli_query($db, $sql);

// 遍历查询结果
while ($row = mysqli_fetch_assoc($a)) {
    // var_dump($row); // 调试用
    echo "用户名:" . $row['username'] . ",密码:" . $row['password'];
    echo "<br>";
}

// 关闭连接
mysqli_close($db);
?>

其实php连接mysql有三种方式,phpstudy帮我们都内置了:mysql、mysqli、pdo,其中mysql淘汰 了,不安全。

插入数据:

<?php
// 连接MySQL数据库
$db = mysqli_connect('localhost', 'root', 'root', 'jaden');

// 定义插入语句
$sql = "INSERT INTO user(username, password) VALUES('laowang2', '111111')";

// 执行SQL语句
$a = mysqli_query($db, $sql);

// 检查执行结果
if (!$a) {
    echo "SQL语句语法问题";
} else {
    echo "SQL语句执行成功!";
}

// 关闭数据库连接
mysqli_close($db);
?>

删除数据,更新数据和插入数据步骤类似 

六.cookie和session 

登录认证。

只使用cookie

<?php
// 页面跳转(JavaScript方式)
echo "<script>location.href='login.php';</script>";

// 设置Cookie
setcookie('user', 'admin');  // 简单Cookie设置
/* 
等效完整参数写法:
setcookie('user', 'admin', time()+3600, '/', 'example.com', false, true);
*/

// 读取Cookie
$username = $_COOKIE['user'] ?? '未登录';
echo "当前用户:".$username;
?>

cookie结合session

<?php
/* ========== 验证的地方 ========== */
session_start();
if(isset($_SESSION['user'])) {
    // 用户已登录的逻辑处理
}

/* ========== 登录成功设置 ========== */
session_start();
$_SESSION['user'] = $_POST['su'];       // 存储用户名
$_SESSION['login_time'] = time();       // 记录登录时间戳
$_SESSION['d'] = '123';                 // 存储固定标识
$_SESSION['login_status'] = 1;          // 设置登录状态

/* 
 * Session存储位置配置提示:
 * 文件路径在php.ini中的session.save_path参数设置
 */
?>

七.总结

本期讲解了很多PHP稍微进阶的知识,内容不是很多,PHP基础知识就到此为止了,干货满满,期待大家的点赞关注加收藏,共勉。