当今最强大的PHP技巧,让你成为编程巨匠

PHP 简单介绍

1、语言介绍

标题描述
Web开发PHP在Web开发领域非常强大。它具有丰富的内置函数和库,使得开发Web应用程序变得高效和简单。PHP可以轻松处理表单处理、数据验证和数据库操作等任务,并与各种数据库系统(如MySQL)无缝集成。
快速开发HP的语法简单易学,开发速度相对较快。它提供了丰富的框架和工具,如Laravel、Symfony和CodeIgniter等,可以加快应用程序的开发过程。
社区支持PHP拥有庞大的开发者社区,提供丰富的文档、教程和资源。这使得开发者能够轻松获取支持和解决问题,共享经验和知识。
特色它拥有良好的扩展性和可维护性,可以通过面向对象编程和模块化设计来构建可扩展的应用程序。开源的,可以免费使用和分发。这使得它成为许多开发者和组织的首选语言之一。
缺点PHP是解释执行的语言,每次请求都需要解析和执行代码。尽管PHP在性能方面有所改进,但在处理大量并发请求或高负载情况下可能表现不佳。

2、运行模式

名称介绍
CLI模式CLI模式是在命令行终端中直接运行PHP脚本的模式。它适用于编写命令行脚本、系统管理任务和工具开发等场景。
Web服务器模式PHP最常见的用途是在Web服务器上运行,处理来自Web浏览器的HTTP请求。在这种模式下,PHP脚本通过Web服务器(如Apache、Nginx)与浏览器进行交互,生成并返回动态的Web页面。
CGI模式CGI模式是一种通过Web服务器将HTTP请求传递给PHP解释器的方式。在这种模式下,PHP解释器作为独立的进程执行,并将结果返回给Web服务器,再由Web服务器传递给浏览器。
FastCGI模式FastCGI是一种改进的CGI模式,通过保持PHP解释器进程的持久性来提高性能。在FastCGI模式下,PHP解释器作为一个独立的后台进程运行,并通过与Web服务器之间的通信管道处理HTTP请求。
模块模式在某些Web服务器(如Apache)中,PHP可以作为一个模块(例如mod_php)嵌入到Web服务器中。在这种模式下,PHP解释器与Web服务器共享同一个进程空间,提供更快的性能和更好的集成。

详细模式使用方法可以参考官方文档:PHP: PHP 手册 - Manual

3、运行环境搭建及IDE推荐

3.1 PHP&Mysql 版本推荐:8.0 +
3.2 运行服务器环境选: Apache 或者 Nginx
  • 如果您需要一个成熟稳定、功能丰富且具有广泛扩展性的Web服务器,以及良好的.htaccess支持,那么Apache可能是更合适的选择。
  • 如果您关注高性能、低内存消耗和高度可扩展性,并且对简洁易懂的配置语法有需求,那么Nginx可能是更适合的选择。
3.3 集成环境选择
名称适配系统官网
WampWindowswww.wampserver.com
MampMacoswww.mamp.info
LampLinux具体需要根据Linux系统查找
XamppWin/Macoswww.apachefriends.org

PHP基础知识

1、标记风格

<?php echo "Hello Php"; ?>

推荐使用

<? echo "Hello Php"; ?>

这 是一种短标记风格,用于在PHP中嵌入代码块。它是一种较早期的标记风格,但在一些PHP配置中可能被禁用或不推荐使用。

2、分号、空白、换行符

在PHP中分号“ ;”用作语句的结束符号。每个语句应该以分号结尾,以表示语句的结束。

空白和换行符(包括空格、制表符和换行符)通常被解释器忽略,因此它们在大多数情况下对代码的执行没有直接影响。

提示: 通过在适当的位置使用空白和换行符,可以使代码更易于阅读和理解,并且有助于代码的组织和格式化。

3、注释

//............ 单行注释

#.............. 单行注释

/*..................*/ 多行注释

4、内容输出

  1. echo语句:echo是PHP中最常用的输出方法之一,用于将内容输出到浏览器或命令行。

    `echo "Hello Php!";`
    
  2. print语句:print是另一种常见的输出方法,与echo类似,用于将内容输出到浏览器或命令行。

    print "Hello Php!";
    
  3. print_r函数:print_r函数用于打印复杂数据类型(如数组、对象)的可读性较好的表示形式。

    $demoArr = ['apple','banana','orange];
    print_r($demoArr);
    
  4. var_dump函数:var_dump函数用于打印变量的详细信息,包括数据类型和值。

    $name = "John_lee";
    var_dump($name);
    
  5. printf函数:printf函数用于格式化输出字符串,可以根据指定的格式打印变量的值。

    $number = 42;
    printf("The answer is %d", $number);
    

    5.1 常用的占位符:

    占位符说明
    %d带符号的十进制数
    %u不带符号的十进制数
    %o不带符号的八进制数
    %x不带符号的十六进制数(小写字母)
    %X不带符号的十六进制数(大写字母)
    %f浮点数(本地设置)
    %F浮点数(不本地设置)
    %e科学计数法(小写e)
    %E科学计数法(大写E)
    %s字符串
    %cASCII码值相应的字符
    %b二进制数
    %a十六进制数(小写字母)
    %A十六进制数(大写字母)
  6. sprintf函数:sprintf函数与printf函数类似,但它返回格式化后的字符串 (用变量保存),而不是直接将其打印出来。

$number = 42;
$formattedString = sprintf("The answer is %d", $number);
echo $formattedString;

5、变量与常量

5.1 变量命名规则

在PHP中,变量名必须以美元符号“ ”开头,后面跟着变量名。变量名可以包含字母、数字和下划线,但必须以字母或下划线开头。此外, P H P 是区分大小写的,因此 ‘ ”开头,后面跟着变量名。变量名可以包含字母、数字和下划线,但必须以字母或下划线开头。此外,PHP是区分大小写的,因此` 开头,后面跟着变量名。变量名可以包含字母、数字和下划线,但必须以字母或下划线开头。此外,PHP是区分大小写的,因此name$Name`是两个不同的变量。

5.2 变量声明

PHP是一种动态弱类型语言,这意味着您无需显式声明变量的类型。变量的类型是根据其值自动确定的。例如:

$name = "John"; // 字符串类型
$age = 25; // 整数类型
$isStudent = true; // 布尔类型
5.3 变量赋值

要为变量赋值,只需使用赋值操作符(=)将值分配给变量。例如:

$name = "John";
$age = 25;
5.4 变量输出

要在PHP中输出变量的值,可以使用echo语句或print函数。例如:

$name = "John";
echo $name; // 输出:John
5.5 变量类型
字符串(String)

字符串是由一串字符组成的数据类型。可以使用单引号或双引号来定义字符串。例如:

$name = "John";
$message = 'Hello, World!';
整数(Integer)

整数是不带小数点的数字。例如:

$age = 25;
浮点数(Float)

浮点数是带有小数点的数字。例如:

$pi = 3.14;
布尔(Boolean)

布尔类型表示真或假的值。可以是truefalse。例如:

$isStudent = true;
数组(Array)

数组是一种用于存储多个值的数据结构。可以使用array()函数或简化的[]语法来创建数组。例如:

$fruits = array("apple", "banana", "orange");
// 或者
$fruits = ["apple", "banana", "orange"];
对象(Object)

对象是类的实例。对象具有属性和方法。例如:

class Person {
    public $name;
    public function sayHello() {
        echo "Hello, my name is " . $this->name;
    }
}$person = new Person();
$person->name = "John";
$person->sayHello(); // 输出:Hello, my name is John
空(Null)

null表示变量没有值。例如:

$foo = null;
5.6 变量作用域

变量的作用域指的是变量在程序中有效的区域。在PHP中,有以下几种作用域:

5.6.1 局部作用域

局部作用域是指在函数或代码块内部声明的变量。这些变量只在其声明的函数或代码块内部可见。例如:

function myFunction() {
    $name = "John"; // 局部变量
    echo $name;
}myFunction(); // 输出:John
echo $name; // 错误:变量$name在该作用域外部不可见
5.6.2全局作用域

全局作用域是指在函数外部声明的变量。这些变量在整个程序中都可见。例如:

$name = "John"; // 全局变量function myFunction() {
    global $name; // 使用global关键声明全局变量
    echo $name;
}myFunction(); // 输出:John
echo $name; // 输出:John
5.6.3 静态作用域

静态作用域用于在函数调用之间保持变量的持久性。静态变量在函数内部声明,但在函数调用之间保持其值。例如:

function myFunction() {
    static $count = 0; // 静态变量
    $count++;
    echo $count;
}myFunction(); // 输出:1
myFunction(); // 输出:2
myFunction(); // 输出:3
5.7 变量技巧
5.7.1 变量的引用传递

默认情况下,PHP中的变量是通过值传递的,这意味着在函数内部对变量的更改不会影响函数外部的变量。但是,您可以使用引用传递来让函数修改外部变量。例如:

function increment(&$num) {
    $num++;
}$count = 0;
increment($count);
echo $count; // 输出:1

在函数参数前加上&符号将参数声明为引用。

5.7.2 变量的动态变量名

在PHP中,您可以使用变量的值作为另一个变量的名称。这被称为动态变量名。例如:

$fruit = "apple";
$apple = "A delicious fruit";
echo $$fruit; // 输出:A delicious fruit

$$fruit将使用$fruit的值作为变量名称,即$apple

5.8 超全局变量

PHP提供了一些特殊的全局变量,称为超全局变量。这些变量在脚本的任何地方都可用,并且不需要使用global关键字来访问。一些常见的超全局变量包括$_GET$_POST$_SERVER等。例如:

echo $_GET['name']; // 输出URL参数中的name值
echo $_POST['email']; // 输出表单提交中的email值
echo $_SERVER['REMOTE_ADDR']; // 输出客户端IP地址
超全局变量说明
$_GET地址栏 GET 提交
$_POST表单 POST 提交
$_FILES文件上传变量
$_SESSION会话变量
$_COOKIEcookie 值变量
$_GLOBALS全局变量
$_REQUEST包含$_GET,$_POST,$_COOKIE
$_SERVER服务器环境变量
5.9 常量命名和规则
常量命名规则

在PHP中,常量名通常使用大写字母,并且建议使用下划线来分隔单词。

  • 常量前面没有定义变量符号 ”$“
  • 常量只能用 define() 函数定义,而不能通过赋值语句
  • 常量一旦定义就不能被重新定义或者取消定义
  • 常量的值用来定义 整型,浮点,字符串,布尔值,数组
  • 常量可以不用理会变量范围的可以在任何位置访问

例如:

define("PI", 3.14);
define("MAX_SIZE", 100);//---------------------------------------define("FRUITS", ["apple", "banana", "orange"]);
echo FRUITS[0]; // 输出:apple
echo FRUITS[1]; // 输出:banana
echo FRUITS[2]; // 输出:orange
5.9.1 常量声明

在PHP中,可以使用define()函数来定义常量。define()函数接受两个参数。例如:

define("PI", 3.14);

自PHP 7.3起,常量默认是大小写敏感的,并且不再支持通过第三个参数来声明大小写不敏感的常量。

5.9.2常量使用

定义常量后,可以在整个脚本中使用它们,无论是在函数内部还是在函数外部。要访问常量的值,只需使用常量名称即可。例如:

define("PI", 3.14);
echo PI; // 输出:3.14
5.9.3预定义常量

PHP还提供了一些预定义的常量,它们在整个脚本中都可用。一些常见的预定义常量包括:

  • __FILE__: 当前脚本的文件名(包含完整路径)
  • __LINE__: 当前脚本中的行号
  • __DIR__: 当前脚本所在的目录
  • __FUNCTION__: 当前函数的名称
  • __CLASS__: 当前类的名称
  • __METHOD__: 当前方法的名称

例如:

echo __FILE__; // 输出当前脚本的文件名
echo __LINE__; // 输出当前脚本中的行号
5.10常量用例
5.10.1 存储配置信息

常量非常适合存储配置信息,例如数据库连接信息、API密钥等。通过将这些敏感信息存储为常量,可以确保它们在整个脚本中不会被更改。

define("DB_HOST", "localhost");
define("DB_USERNAME", "myuser");
define("DB_PASSWORD", "mypassword");
5.10.2 枚举值

常量可以用于定义枚举值,即一组相关的命名常量。您可以使用这些常量来表示不同的颜色。例如,假设您想定义一些颜色常量:

define("COLOR_RED", "red");
define("COLOR_GREEN", "green");
define("COLOR_BLUE", "blue");
5.10.3 数学常量

PHP提供了一些内置的数学常量,方便在数学运算中使用,具体可以查阅PHP手册。例如:

echo M_PI; // 输出圆周率π的值
echo M_E; // 输出自然对数的底数e的值
5.10.4条件编译

常量还可以用于条件编译。根据不同的条件,您可以定义不同的常量值。然后,您可以根据这些常量的值来执行不同的代码块。例如:

define("DEBUG_MODE", true);if (DEBUG_MODE) {
    // 执行调试模式下的代码
} else {
    // 执行非调试模式下的代码
}

6、运算符

6.1 算术运算符
运算符说明
$a+$b加法$a 和$b 的和
$a-$b减法 $a 和$b 的差
$a*$b乘法 $a 和$b 的积
$a/$b除法 $a 除以$b 的商
$a%$b取模 $a 除以$b 后的余
++$a前加 $a 的值先加一,然后进行操作
$a++后加 $a 的值先进行操作,后加一
--$a前减 $a 的值先减一,然后进行操作
$a--后减 $a 的值先进行操作,后减一
$a = 5;
$b = 3;
$result = $a + $b; // $result 的值为 8
$a = 5;
$b = 3;
$result = $a - $b; // $result 的值为 2
$a = 5;
$b = 3;
$result = $a * $b; // $result 的值为 15
$a = 10;
$b = 2;
$result = $a / $b; // $result 的值为 5
$a = 10;
$b = 3;
$result = $a % $b; // $result 的值为 1
$a = 2;
$b = 3;
$result = $a ** $b; // $result 的值为 8
$a = 5;
echo ++$a; // 输出:6
echo $a;   // 输出:6
$a = 5;
echo $a++; // 输出:5
echo $a;   // 输出:6
$a = 5;
echo $a--; // 输出:5
echo $a;   // 输出:4
$a = 5;
echo --$a; // 输出:4
echo $a;   // 输出:4
6.2 赋值运算符
运算符说明
=右边值赋值给左边变量
+=左边值加上右边值赋值给左边变量
-=左边值减掉右边值赋值给左边变量
*=左边值乘以右边值赋值给左边变量
/=左边值除以右边值赋值给左边变量
.=左边字符串连接到右边变量后面
%=左边值对右边值取余数后赋值给左边变量
6.3 字符串运算符
运算符说明
.它返回其左右参数连接后的字符串
.=左边字符串连接到右边变量后面
6.4 比较运算符
运算符说明
$a==$b等于 TRUE,如果 a 等于 a 等于 a等于b
$a===$b全等于 TRUE,如果 a 等于 a 等于 a等于b,并且类型也相同
$a!=$b不等 TRUE,如果 a 不等于 a 不等于 a不等于b
$a<>$b不等 TRUE,如果 a 不等于 a 不等于 a不等于b
$a!==$b非全等 TRUE,如果 a 不等于 a 不等于 a不等于b,或者类型不同
$a<$b小于 TRUE,如果 a 严格小于 a 严格小于 a严格小于b
$a>$b大于 TRUE,如果 a 严格 a 严格 a严格b
$a<=$b小于等于 TRUE,如果 a 小于或者等于 a 小于或者等于 a小于或者等于b
$a>=$b大于等于 TRUE,如果 a 大于或者等于 a 大于或者等于 a大于或者等于b
6.5 逻辑运算符
运算符说明
$a and $b逻辑与 TRUE,如果 $a 与 $b 都为 TRUE
$a or $b逻辑或 TRUE,如果 $a 或 $b 任一为 TRUE
!$a逻辑非 TRUE,如果 $a 不为 TRUE
$a && $b逻辑与 TRUE,如果 $a 与 $b 都为 TRUE
`$a
6.6 三元表达式
变量 = 条件 ? 值1 : 值2;

当表达式的条件 true 时, 变量 = 值 1 否则 变量 = 值 2

变量?? "默认值";

??操作符是空合并运算符,它用于简化对变量是否为null的判断,并在变量为null时提供一个默认值。 注意是:null

$s1 = null;
echo $s1?? "888"; //结果:888$s2 = 0;
echo $s2?? 888; // 结果为:0$s3 = flase;
echo $s3?? 888; // 结果为:不显示$s4 = true;
echo $s4?? 888; // 结果为:1

7、流程控制

7.1 if/elseif/else

用于执行条件分支的控制结构。它们可以根据条件的真假执行不同的代码块

if (条件1) {
    // 当条件1为真时执行的代码块
} elseif (条件2) {
    // 当条件1为假而条件2为真时执行的代码块
} else {
    // 当所有条件都为假时执行的代码块
}$age = 25;
if ($age < 18) {
    echo "未成年人";
} elseif ($age >= 18 && $age < 65) {
    echo "成年人";
} else {
    echo "老年人";
}
7.2 switch

用于执行多个条件分支的控制结构。根据表达式的值选择不同的代码块进行执行

switch (表达式) {
    case1:
        // 当表达式的值等于值1时执行的代码块
        break;
    case2:
        // 当表达式的值等于值2时执行的代码块
        break;
    // 可以有多个case块
    default:
        // 当表达式的值与所有case的值都不匹配时执行的代码块
        break;
}
$day = "Monday";switch ($day) {
    case "Monday":
        echo "星期一";
        break;
    case "Tuesday":
        echo "星期二";
        break;
    case "Wednesday":
        echo "星期三";
        break;
    case "Thursday":
        echo "星期四";
        break;
    case "Friday":
        echo "星期五";
        break;
    default:
        echo "周末";
        break;
}

注意:如果在 switch 语句的 case 块中没有使用 break 语句,程序将会继续执行后续的 case 块,而不会跳出 switch 语句。

$day = "Monday";
switch ($day) {
    case "Monday":
        echo "Today is Monday.";
    case "Tuesday":
        echo "Tomorrow is Tuesday.";
    case "Wednesday":
        echo "The day after tomorrow is Wednesday.";
    default:
        echo "Other days.";
}/** 
结果为:  Today is Monday.
        Tomorrow is Tuesday.
        The day after tomorrow is Wednesday.
        Other days.
*/
7.3 while

是一种常用的循环控制结构,用于在满足条件的情况下重复执行一段代码块。

while (条件) {
    // 循环体中的代码
}
$count = 1;
while ($count <= 5) {
    echo $count . " ";
    $count++;
}
7.4 do while

是一种循环控制结构,类似于 while 循环,但它会先执行一次循环体中的代码,然后再检查条件是否为真,如果条件为真,则继续执行循环。

do {
    // 循环体中的代码
} while (条件);$count = 1;
do {
    echo $count . " ";
    $count++;
} while ($count <= 5);
7.5 for

是一种常用的循环控制结构,用于在指定的条件下重复执行一段代码块,并控制循环变量的增量。

for (初始表达式; 条件表达式; 增量表达式) {
    // 循环体中的代码
}for ($i = 1; $i <= 5; $i++) {
    echo $i . " ";
}

注意: 循环的时候必须设置停止循环的条件,不然呵呵~ 死机了吧!

7.6 breakcontinue
  • break 语句用于立即终止当前循环(例如 forwhiledo while 循环),并跳出循环体,继续执行循环后的代码。它可以用于提前结束循环,无论是否满足循环条件。当程序执行到 break 语句时,循环会立即结束,不再执行循环体内剩余的代码。

  • continue 语句用于跳过当前循环的剩余代码,立即进入下一次循环迭代。当程序执行到 continue 语句时,循环会跳过当前迭代的剩余代码,直接进入下一次迭代。它可以用于跳过某些特定条件下的迭代操作。

for ($i = 1; $i <= 10; $i++) {
    if ($i == 5) {
        break;
    }
    echo $i . " ";
}for ($i = 1; $i <= 5; $i++) {
    if ($i == 3) {
        continue;
    }
    echo $i . " ";
}

8、日期时间

8.1 时区
  1. PHP.ini 配置 date.timezone = PRC` (不推荐)

  2. 脚本中修改 (推荐使用)

    date_default_timezone_get() //取得当前使用时区
    date_default_timezone_set() //设定当前使用时区
    
8.2 DateTime

PHP提供了一个内置的DateTime类和一些相关的函数,用于处理日期和时间的创建、格式化、计算等操作。

//获取当前日期和时间:
$timeNow = new DateTime(); // 当前日期和时间
$dateNow = $timeNow->format('Y-m-d'); // 当前日期
$timeNow = $timeNow->format('H:i:s'); // 当前时间//格式化日期和时间:
$dateTime = new DateTime('2021-12-01 14:30:00');
$formattedDateTime = $dateTime->format('Y-m-d H:i:s'); // 格式化为字符串//解析日期和时间:
$dateString = '2021-12-01 14:30:00';
$dateTime = DateTime::createFromFormat('Y-m-d H:i:s', $dateString); // 解析字符串为日期对象//计算日期和时间:
$dateTime = new DateTime('2021-12-01');
$dateTime->modify('+1 day'); // 添加一天
$newDate = $dateTime->format('Y-m-d'); // 修改后的日期//比较日期和时间
$dateTime1 = new DateTime('2021-12-01');
$dateTime2 = new DateTime('2022-01-01');if ($dateTime1 < $dateTime2) {
    // 日期1早于日期2
}//格式化输出相对时间:
$dateTime = new DateTime('2021-12-01');
$now = new DateTime();
$diff = $dateTime->diff($now); // 计算日期差
$relativeTime = $diff->format('%y years, %m months, %d days'); // 格式化为相对时间

9、文件引入

includerequireinclude_oncerequire_once是用于在脚本中包含其他文件的语句。它们的功能类似,但在文件包含的方式和错误处理方面有一些不同。

include`:用于包含指定文件,并在包含过程中产生一个警告(非致命错误),如果包含的文件不存在或发生其他错误,脚本会继续执行。

include 'file.php';

require:用于包含指定文件,并在包含过程中产生一个致命错误,如果包含的文件不存在或发生其他错误,脚本会停止执行

require 'file.php';

include_once:与include类似,但是如果同一个文件已经被包含过,include_once会检查并确保文件不会被重复包含。这避免了重复定义函数、类或变量等问题。

include_once 'file.php';

require_once:与require类似,但是如果同一个文件已经被包含过,require_once会检查并确保文件不会被重复包含。这避免了重复定义函数、类或变量等问题。

require_once 'file.php';

使用includerequire语句时,可以包含任何PHP文件,包括库文件、模块文件等。被包含的文件可以是相对于当前脚本文件的路径或绝对路径。

需要注意以下几点:

  • includerequire语句在包含文件时,会创建一个新的局部作用域,包含的文件中定义的函数、类和变量在包含语句后可用。
  • 如果包含的文件中有语法错误或其他错误,include会产生一个警告并继续执行,require会产生一个致命错误并停止执行。
  • include_oncerequire_once语句在包含文件时,会检查文件是否已经被包含过,避免重复包含相同文件。
  • 推荐在包含文件时使用requirerequire_once,因为如果被包含文件是必需的(例如核心库文件),则应该确保它们存在,以避免脚本出现严重错误。

PHP数组知识

1、数组介绍

在PHP中,数组是一种用于存储多个值的数据结构。它是一种有序的、可变长度的容器,可以在其中存储不同类型的数据,包括整数、字符串、对象、甚至其他数组。

在 PHP 中有两种数组:索引数组和关联数组

  • 索引(indexed)数组的索引值是整数,以 0 开始。当通过位置来标识东西时用索引数组。
  • 关联(associative)数组以字符串做为索引值,关联数组更像操作表。索引值为列名,用于访问列的数据

在 PHP 中数组分:一维数组和多维数组

$arr = [1,2,3,4,5]; //索引数组 (一维数组)$arr[0]; // 读取 结果:1$arrg = ['name' => '张飞','age' => 18, 'ap'=> 89, 'mp' => 100]; //关联数组 (一维数组)$arrg['name'];// 读取 结果:'张飞'//索引数组 (多维数组)
$arrs = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]; $arrs[1][2]; // 读取 结果:6
//关联数组 (多维数组)
$arrgs = [
    [  'name' => '张飞','age' => 18, 'ap'=> 89, 'mp' => 100],
    [  'name' => '刘备','age' => 28, 'ap'=> 69, 'mp' => 100],
    [  'name' => '关羽','age' => 38, 'ap'=> 99, 'mp' => 100],
  ];$arrgs[1]['name'];  // 读取 结果:'刘备'

2、遍历数组

2.1 使用指针读取数组的值 current() ,next(), prev(), reset(),end(),key(),each()
  1. reset(): 将数组的内部指针重置到数组的第一个元素,并返回该元素的值。
  2. next(): 将数组的内部指针移动到下一个元素,并返回该元素的值。
  3. prev(): 将数组的内部指针移动到上一个元素,并返回该元素的值。
  4. end(): 将数组的内部指针移动到最后一个元素,并返回该元素的值。
  5. key(): 返回数组的当前指针位置的键。
  6. current(): 返回数组的当前指针位置的值。
  7. each(): 返回当前指针位置的键值对,并将指针移动到下一个元素。
$arr = [1,2,3,4,5,6];echo current($arr);  //结果为: 1
echo next($arr); // 结果为: 2
echo next($arr); // 结果为: 3
echo next($arr); // 结果为: 4
echo next($arr); // 结果为: 5
echo next($arr); // 结果为: 6
echo prev($arr); // 结果为: 5
echo prev($arr); // 结果为: 4
echo prev($arr); // 结果为: 3
echo prev($arr); // 结果为: 2
echo prev($arr); // 结果为: 1
echo prev($arr); // 结果为: false
reset($arr); //重置指针为第一位置
echo current($arr);
.....
    
 $arrgs = [
    [  'name' => '张飞','age' => 18, 'ap'=> 89, 'mp' => 100],
    [  'name' => '刘备','age' => 28, 'ap'=> 69, 'mp' => 100],
    [  'name' => '关羽','age' => 38, 'ap'=> 99, 'mp' => 100],
];while($arrg = current($arrgs)){
    
    echo "武将:".$arrg['name'].'武力值:'.$arrg['ap'];
    echo "</br>";
    next($arrgs);
}
//武将:张飞武力值:89
//武将:刘备武力值:69
//武将:关羽武力值:99
    
    
    

使用指针读取数组数据的一个主要优点是它提供了一种灵活而高效的方式来遍历和访问数组的元素。下面是指针读取数组数据的一些优点:

  1. 直接访问元素:通过使用指针,可以直接访问数组中的特定元素,而无需使用索引或键。这使得代码更简洁和易读。
  2. 灵活的遍历:指针使得遍历数组变得更加灵活。可以自由地在数组中移动指针,访问下一个或上一个元素,或者重置指针到数组的开头。这使得可以根据需要自定义迭代逻辑。
  3. 节省内存:使用指针读取数组数据通常比创建额外的数组副本更节省内存。当处理大型数组时,避免复制整个数组可以减少内存占用。
  4. 高效的数据处理:指针读取数组数据通常比使用循环和索引访问更高效。这是因为指针直接访问内存中的元素,而不需要额外的索引计算或循环迭代。
  5. 支持多维数组:指针读取数组数据对于处理多维数组非常有用。通过移动多个指针,可以轻松地访问多维数组中的元素。

需要注意的是,使用指针读取数组数据也需要小心操作,确保在移动指针时不会超出数组的范围。此外,指针读取数组数据通常适用于线性遍历。

如果需要随机访问数组元素,使用索引或键可能更为适合。

2.2 foreach(), for(), list()
$arrgs = [
    [  'name' => '张飞','age' => 18, 'ap'=> 89, 'mp' => 100],
    [  'name' => '刘备','age' => 28, 'ap'=> 69, 'mp' => 100],
    [  'name' => '关羽','age' => 38, 'ap'=> 99, 'mp' => 100],
];foreach($arrgs as $key=>$value){    echo "key".$key.'--------'.$value['name'].'-'.$value['ap'].'</br>';
}
for($i=0;$i<count($arrgs);$i++){
    echo "key".$i.'--------'.$arrgs[$i]['name'].'-'.$arrgs[$i]['ap'].'</br>';
}$arr = ['张飞','刘备','关羽'];list($name1,$name2,$name) = $arr;  // list(,,$name) = $arr;
// list(,,$name) = $arr;
// echo $name; 结果: 关羽
echo $name1; // 张飞 注意接收变量的数量需要跟数组元素个数

3、数组常用函数

3.1 数组添加删除元素

array_unshift 在数组开头插入一个或多个元素

array_push 将一个或多个元素压入数组的末尾

array_shift 将数组开头的元素移出数组

array_pop 弹出数组最后一个元素

以上操作都时传址操作!!

$arr = [1,2,3,4,5];array_unshift($arr,100);
print_r($arr);
echo "</br>";array_push($arr,99);
print_r($arr);
echo "</br>";array_pop($arr);
print_r($arr);
echo "</br>";array_shift($arr);
print_r($arr);
echo "</br>";/*结果
Array ( [0] => 100 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 )
Array ( [0] => 100 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 99 )
Array ( [0] => 100 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 )
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )
*/
3.2 计算数组元素个数

count

$num = [1,2,3];
echo count($num); // 结果为:3
3.3 判断元素是否存在数组种

in_array

$image = ['jpg','gif','bmp'];
echo in_array('jpg',$image); //结果为:1 ,即为 true
3.4 判断数组里是否有指定的键名或索引

array_key_exists

$image = ['jpg','gif','bmp'];
$name = ['name'=>'张三','age'=>88,'sex'=>'男'];
$res = array_key_exists(3, $image);
$resName = array_key_exists('name',$name);echo  $res;  //结果为:null
echo '</br>';
echo $resName;  //结果为:1
3.5 函数返回包含数组中所有键名的一个新数组

array_keys

$name = ['name'=>'张三','age'=>88,'sex'=>'男'];
$resName = array_keys($name);
print_r($resName);//Array ( [0] => name [1] => age [2] => sex )
3.6 用回调函数过滤数组中的元素

array_filter

$name =[
    ['name'=>'张三','age'=>12,'sex'=>'男'],
    ['name'=>'张三','age'=>18,'sex'=>'男'],
    ['name'=>'张三','age'=>35,'sex'=>'男'],
    ['name'=>'张三','age'=>45,'sex'=>'男']
] ;$res = array_filter($name,function ($item){
  return $item['age'] < 40;
});print_r($res);/*
Array
(
    [0] => Array
        (
            [name] => 张三
            [age] => 12
            [sex] => 男
        )    [1] => Array
        (
            [name] => 张三
            [age] => 18
            [sex] => 男
        )    [2] => Array
        (
            [name] => 张三
            [age] => 35
            [sex] => 男
        ))
*/
3.7 为数组的每个元素应用回调函数,结果生成新数组

array_map

$name =[
    ['name'=>'张三','age'=>12,'sex'=>'男'],
    ['name'=>'李四','age'=>18,'sex'=>'男'],
] ;$resNewName = array_map(function($item){
    $newArray = [];
    $newArray['name'] = $item['name'];
    $newArray['age'] = $item['age'] + 10 ;
    $newArray['sex'] = $item['sex'];
    return  $newArray;}, $name);print_r($resNewName);
print_r($name);/*
新数组增加了10岁
Array
(
    [0] => Array
        (
            [name] => 张三
            [age] => 22
            [sex] => 男
        )    [1] => Array
        (
            [name] => 李四
            [age] => 28
            [sex] => 男
        ))原数组不变
Array
(
    [0] => Array
        (
            [name] => 张三
            [age] => 12
            [sex] => 男
        )    [1] => Array
        (
            [name] => 李四
            [age] => 18
            [sex] => 男
        ))*/
3.8 获取数组中所有的值

array_value

$name =[
    ['name'=>'张三','age'=>12,'sex'=>'男'],
    ['name'=>'李四','age'=>18,'sex'=>'男'],
    ['name'=>'王五','age'=>35,'sex'=>'男'],
    ['name'=>'老六','age'=>45,'sex'=>'男']
] ;foreach ($name as $n){
    print_r(array_values($n));
}/*
Array
(
    [0] => 张三
    [1] => 12
    [2] => 男
)
Array
(
    [0] => 李四
    [1] => 18
    [2] => 男
)
Array
(
    [0] => 王五
    [1] => 35
    [2] => 男
)
Array
(
    [0] => 老六
    [1] => 45
    [2] => 男
)*/
3.9 合并一个或多个数组

array_merge

$database = [
    'host'=>'localhost','port'=>3306,'user'=>'user','password'=>''];print_r(
    array_merge($database, ['user'=>'root','password'=>'admin888'])
);
/*Array
(
    [host] => localhost
    [port] => 3306
    [user] => root
    [password] => admin888
)
     假如数组key相同,会被覆盖值!!
*/  
3.10 是 PHP 中的一个内置函数,用于将数组的所有键名(key)转换为指定的大小写格式。它返回一个新的数组,其中包含转换后的键名。

可选参数,指定转换后的大小写格式。可以取两个值之一:

  • CASE_LOWER(默认值):将键名转换为小写形式。
  • CASE_UPPER:将键名转换为大写形式。

array_change_key_case

$data = array(
    'FirstName' => 'John',
    'LastName' => 'Doe',
    'Age' => 30
);$result = array_change_key_case($data, CASE_LOWER);print_r($result);

如果需要比数组的值转大小写则需要手动实现

function changeValueCase($array, $case) {
    foreach ($array as &$value) {
        if (is_array($value)) {
            $value = changeValueCase($value, $case);
        } else {
            $value = ($case === CASE_LOWER) ? strtolower($value) : strtoupper($value);
        }
    }
    unset($value);
    return $array;
}$data = array(
    'Name' => 'John',
    'Age' => 30,
    'Email' => 'JOHN@EXAMPLE.COM'
);$result = changeValueCase($data, CASE_LOWER);print_r($result);/*Array
(
    [Name] => john
    [Age] => 30
    [Email] => john@example.com
)*/
3.11 对数组中的每个成员递归地应用用户函数,本函数会递归到更深层的数组中去。

array_walk_recursive

参数说明:

  • &$array:要遍历的数组,需要传递一个引用。
  • $callback:回调函数,用于处理数组中的每个元素。它可以是一个匿名函数、一个函数名或一个类方法。
  • $userdata:可选参数,用户自定义数据,可以在回调函数中使用。
array_walk_recursive(array &$array, callable $callback, mixed $userdata = null): bool
    
    
    function double(&$value)
{
    $value *= 2;
}$data = array(
    'numbers' => array(1, 2, 3),
    'names' => array('John', 'Jane', 'Jim'),
    'nested' => array(
    'colors' => array('red', 'green', 'blue'),
    'ages' => array(10, 20, 30)
    )
);array_walk_recursive($data, 'double');print_r($data);
    
/*
Array
(
    [numbers] => Array
        (
            [0] => 2
            [1] => 4
            [2] => 6
        )    [names] => Array
        (
            [0] => John
            [1] => Jane
            [2] => Jim
        )    [nested] => Array
        (
            [colors] => Array
                (
                    [0] => red
                    [1] => green
                    [2] => blue
                )            [ages] => Array
                (
                    [0] => 20
                    [1] => 40
                    [2] => 60
                )        ))*/
3.12 用于生成一个可用于表示变量的合法 PHP 代码的字符串。它将变量的值转换为字符串,并包含了该值的 PHP 表示形式。

var_export

$data = array(
    'name' => 'John',
    'age' => 30,
    'colors' => array('red', 'green', 'blue')
);$result = var_export($data, true);echo $result;/*
array (
  'name' => 'John',
  'age' => 30,
  'colors' => 
  array (
    0 => 'red',
    1 => 'green',
    2 => 'blue',
  ),
)
*/
3.13 用于将变量序列化为字符串。序列化是将变量的值转换为可存储或传输的格式的过程。序列化后的字符串可以存储到文件中,也可以通过网络传输,并在需要时重新反序列化为原始的 PHP 变量形式。

**serialize ** unserialize

$data = array(
    'name' => 'John',
    'age' => 30,
    'colors' => array('red', 'green', 'blue')
);$resStr = serialize($data);echo $resStr;/*
a:3:{s:4:"name";s:4:"John";s:3:"age";i:30;s:6:"colors";a:3:{i:0;s:3:"red";i:1;s:5:"green";i:2;s:4:"blue";}}
*/$newStr = unserialize($resStr);/*
Array
(
    [name] => John
    [age] => 30
    [colors] => Array
        (
            [0] => red
            [1] => green
            [2] => blue
        )
)
*/

php 函数知识

1、函数是介绍

在PHP中,函数是一段可重复使用的代码块,用于执行特定的任务。函数封装了一系列的代码,可以接收参数、执行特定的操作,并返回一个值(可选)。函数的主要目的是提高代码的可维护性和可重用性。

函数可以通过函数名进行调用,并可以传递参数给函数。函数可以执行各种操作,例如计算、数据处理、输出、数据库操作等。通过将一系列操作封装在函数中,可以使代码更加模块化和可读性更高。

在文件头部定义declare(strict_types=1) 为严格模式,这样会对函数参数类型进行严格约束。

declare(strict_types=1);function  函数名称(类型 参数1,类型 参数2 …):返回值类型 {
	//逻辑代码
	return 返回值; //如需函数有返回值时使用,否则函数返回值为null
}

它是函数在程序代码中的识别名称,函数名可以是以字母或下划线开头后跟零个或多个字母、下划线和数字的任何字符串。函数名不区分大小写。

function myFunc(){}MYFUNC();
myfeunc();
MyFunC()vardump(function_exists('myFunc'));  //判断函数是否存在

2、参数传递

按值传递参数

在PHP中,函数默认按值传递参数。这意味着函数在接收参数时会创建它们的副本,并在函数内部使用这些副本进行操作,而不会直接修改原始参数的值。

按址传递参数(用“&”符号实现)

在PHP中,函数默认是按值传递参数的,但你可以使用引用(&)来实现按引用传递参数,也称为按地址传递参数。

按引用传递参数允许函数直接访问和修改原始变量的值,而不是创建副本。这意味着在函数内部对参数的修改将影响到原始变量。

$number = 5;
function increment(int $num):void {
    $num = $num + 1;
    echo "函数内Number: " . $num . "\n";
}
echo "原Number: " . $number . "\n";
increment($number);
echo "传参后Number: " . $number . "\n";//原Number: 5 函数内Number: 6 传参后Number: 5$number = 5;
function increment(int &$num):void {
    $num = $num + 1;
    echo "函数内Number: " . $num . "\n";
}echo "原Number: " . $number . "\n";
increment($number);
echo "传参后Number: " . $number . "\n";
//原Number: 5 函数内Number: 6 传参后Number: 6

点语法

当传递的参数数量确定时,可以使用…与变量名。函数的所有参数会成为变量的数组元素。

参数默认值

php 支持函数的默认方式调用。如果在调用函数时没有指定参数的值,在函数中会使用参数的默认值。 默认参数必须列在所有没有默认值参数的后面。

function sum(...$args)
{
    return array_sum($args);
}
echo sum(1, 2, 3);function say(string $name="张飞"):void{    echo $name;
    
}say("马云"); //马云
say();// 张飞

返回值类型

  • int:整数类型

  • float:浮点数类型

  • bool:布尔类型

  • string:字符串类型

  • null:表示无返回值或返回空值

  • array:数组类型

  • object:对象类型

  • callable:可调用类型,包括函数、方法和闭包

  • iterable:可遍历类型,包括数组和实现了Traversable接口的对象

  • 类名:指定返回值类型为特定的类或其子类

  • 接口名:指定返回值类型为特定的接口或其实现类

  • 通过使用typedef关键字创建的自定义类型

  • void:表示函数没有返回值。

  • mixed:表示函数可以返回任意类型的值。

3、变量范围

局部变量

在函数之中声明的变量就是局部变量,并且该变量只有在函数范围之中才能加以使用。如果其它程序局部需要调用使用该变量值时,必须透过「return」指令,来将其传回至主程序区块以作后续处理。

局部变量的作用域仅限于其声明的作用域内部。一旦超出作用域范围,局部变量将不再可用,并且在内存中被释放。这使得局部变量在控制程序的状态和封装数据时非常有用。

function myFunction():void {
    $name = 'John'; // 声明一个局部变量
    echo $name;
}myFunction(); // 输出:John
echo $name; // 错误,无法访问函数内的局部变量

全局变量

在函数范围之外声明的变量为全局变量,在函数无法直接使用全局变量,函数要使用全局变量,必须要利用 global 引入或 $GLOBALS 超全局数组引入。

注意的是,全局变量的使用应该谨慎,因为它们可以在程序的任何地方被修改,而不受局部作用域的限制。在大型程序中滥用全局变量可能导致代码的可读性和维护性下降。为了避免全局变量的滥用,可以使用面向对象编程的原则,封装数据并通过方法访问和操作数据。

$name = 'John'; // 声明一个全局变量function myFunction() {
    global $name; // 使用 global 关键字引用全局变量
    echo $name;
}myFunction(); // 输出:John

静态变量

PHP 支持声明函数变量为静态的(static)。一个静态变量在所有对该函数的调用之间共享,并且仅在脚本的执行期间函数第一次被调用时被初始化。要声明函数变量为静态的用关键字 static。通常,静态变量的第一次使用时赋予一个初始值。

注意的是,静态变量的生命周期会持续到程序执行结束,除非显式重置或重新赋值。此外,静态变量可以在类之间共享信息,可以用于记录全局状态或跟踪某些计数器等。然而,滥用静态变量可能会导致代码的可读性和维护性下降,因此应该谨慎使用。

function myFunction() {
    static $count = 0;  // 声明一个静态变量
    $count++;
    echo $count;
}myFunction(); // 输出:1
myFunction(); // 输出:2
myFunction(); // 输出:3

变量函数

在PHP中,变量函数是一种特殊的功能,允许将函数名存储在变量中并使用该变量调用函数。这种灵活性使得可以根据运行时的条件动态地选择要调用的函数。

function greet() {
    echo "Hello, World!";
}
$funcName = "greet"; // 将函数名存储在变量中
$funcName(); // 使用变量函数调用函数,输出:Hello, World!
//例子二function add($a, $b) {
    return $a + $b;
}function subtract($a, $b) {
    return $a - $b;
}function multiply($a, $b) {
    return $a * $b;
}function divide($a, $b) {
    if ($b != 0) {
        return $a / $b;
    } else {
        return "分母不能为零!";
    }
}$operator = "multiply"; // 根据需要设置运算符$a = 10;
$b = 5;switch ($operator) {
    case "add":
        $result = add($a, $b);
        break;
    case "subtract":
        $result = subtract($a, $b);
        break;
    case "multiply":
        $result = multiply($a, $b);
        break;
    case "divide":
        $result = divide($a, $b);
        break;
    default:
        $result = "无效运算";
        break;
}echo "结果是: " . $result;

递归函数

递归函数是一种在函数内部调用自身的函数。通过递归,函数可以重复执行相同的操作,直到满足特定的条件为止。在编程中,递归函数通常用于解决可以被分解为相同问题的子问题的情况。注意:使用时必须设置跳出递归的条件,不然就呵呵….

function factorial($n) {
    if ($n === 0 || $n === 1) {
        return 1;
    } else {
        return $n * factorial($n - 1);
    }
}$result = factorial(5); // 计算 5 的阶乘
echo $result; // 输出:120

PHP命名空间的使用及注意要点

PHP 命名空间是一种组织和管理 PHP 代码的方式。它提供了一种避免命名冲突的机制,特别是当多个开发者或多个代码库在同一个应用程序中使用相同的类名、函数名或常量名时。简单理解就好像操作系统目录文件的概念,同一目录里不能存在两个相同的文件。这个原理就应用到PHP程序设计领域就是命名空间的概念。

基本使用

默认情况下常量、类和函数名都放在全局空间下。命名空间通过 namespace 来声明。

注意:

  1. namespace 必须定义在文件头部,并在declare(strict_types=1) 语句下面。

  2. 实际上,当你在 PHP 代码中没有显式指定命名空间时,会使用默认的全局命名空间,也称为全局作用域。全局作用域中的类、函数和常量可以在任何地方被访问和使用,不需要使用命名空间限定符。

  3. 如果命名空间中的函数或常量未定义,将会使用全局命名空间。

declare(strict_types=1) //严格模式
namespace Person;class Person {
    // 类的定义
}function myFunction() {
    // 函数的定义
}const MY_NAME = '张飞';//使用方法
use MyNamespace\Person;
use function Person\myFunction;
use const Person\MY_NAME;$obj = new Person();  // 使用完全限定的类名
myFunction();          // 使用完全限定的函数名
echo MY_NAME;      // 使用完全限定的常量名

引用的方式

使用 use 关键字:通过 use 关键字来导入特定的类、函数或常量,以便在当前文件中直接使用。

use MyNamespace\MyClass;
use function MyNamespace\myFunction;
use const MyNamespace\MY_CONSTANT;$obj = new MyClass();  // 使用导入的类
myFunction();          // 使用导入的函数
echo MY_CONSTANT;      // 使用导入的常量

使用完全限定的名称:如果没有使用 use 关键字导入命名空间,也可以通过完全限定的名称来访问命名空间中的类、函数和常量。

$obj = new MyNamespace\MyClass();  // 使用完全限定的类名
MyNamespace\myFunction();          // 使用完全限定的函数名
echo MyNamespace\MY_CONSTANT;      // 使用完全限定的常量名

使用别名(Alias):可以通过 use 关键字为命名空间或类创建别名,以便在代码中使用更简短的名称。

use MyNamespace\MyClass as MyClassAlias;
use MyNamespace\myFunction as functionAlias;
use MyNamespace\MY_CONSTANT as CONSTANT_ALIAS;$obj = new MyClassAlias();  // 使用别名类名
functionAlias();            // 使用别名函数名
echo CONSTANT_ALIAS;        // 使用别名常量名

注意:

多个引入,可以使用多行 use 或用逗号分隔多个类(空间)形式处理多个导入的情况,并使用逗号分隔。

自动加载

在 PHP 中,可以通过使用 spl_autoload_register() 函数来注册自定义的自动加载函数。该函数接受一个回调函数作为参数,当 PHP 遇到未定义的类时,会调用该回调函数来加载类文件。自动加载能够根据类的命名约定自动找到并加载所需的类文件,提高了代码的可维护性和可扩展性。

spl_autoload_register(function ($className) {
    // 转换命名空间分隔符为目录分隔符
    $filePath = str_replace('\\', '/', $className) . '.php';    if (file_exists($filePath)) {
        require_once($filePath);
    }
});

注意:

自动加载函数的实现可以根据你的项目结构和命名约定进行调整。

例如,你可以将类文件存放在特定目录下,或者使用其他命名约定来匹配类名和文件路径。

推荐使用composer管理项目和自动加载

composer的安装搭建可以自行研究,这不难~

使用方法:

1、进入项目的根目录,并初始化

composer init

2、修改配置文件

个性 composer.json 配置文件,其中 autoload配置项是自动加载设置。

  • files 是自动加载文件列表,适合于加载函数
  • psr-4 自动加载命名空间与目录对应关系

在这里插入图片描述

修改配置文件后执行 composer install 生成 vendor,如果修改过配置文件需要执行 composer update

3、配置

在项目中使用以下代码即可完成自动加载。

include 'vendor/autoload.php';

PHP文件与目录

disk_total_space 返回目标磁盘总空间

disk_free_space返回目标磁盘剩余空间

$diskSpaceRes = disk_total_space(__DIR__ ) / pow(1024, 3);
$diskFreeRes =  number_format( disk_free_space(__DIR__)/pow(1024,3), 3);
echo sprintf( "%.3f"."</br>", $diskSpaceRes);
echo $diskFreeRes;

filesize 返回目标文件大小(单位:字节)

$file = number_format(filesize('./test.mp4') / pow(1024, 1), 2) ."KB";
echo $file; // 712.05KB

常用简单函数

函数名用途
is_writable判断给定的文件名是否可写
is_readable判断给定文件名是否可读
file_exists检查文件或目录是否存在
is_file判断给定文件名是否为一个正常的文件
is_dir判断给定文件名是否是一个目录。
filemtime回文件中的数据块上次被写入的时间(时间戳)
basename返回路径中的文件名部分
dirname返回路径中的目录部分
mkdir支持递归的目录创建,参数分别是:目录、权限位、递归创建
rmdir删除指定的目录,该目录必须是空的,而且要有相应的权限。
rename重命名一个文件或目录,也可以进行文件移动。
copy复制文件

fopen 用于打开文件或 URL 的函数。它用于创建一个文件指针,使您能够对文件进行读取、写入和其他操作。

mode说明
‘r’只读方式打开,将文件指针指向文件头。
‘r+’读写方式打开,将文件指针指向文件头。
‘w’写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
‘w+’读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
‘a’写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
‘a+’读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
‘x’创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。
‘x+’创建并以读写方式打开,其他的行为和 ‘x’ 一样。
// 打开一个只读模式的文件
$handle = fopen('file.txt', 'r');// 打开一个只写模式的文件,并将内容写入其中
$handle = fopen('file.txt', 'w');
fwrite($handle, 'Hello, World!');
fclose($handle);// 打开一个追加模式的文件,并将内容追加到末尾
$handle = fopen('file.txt', 'a');
fwrite($handle, 'More content.');
fclose($handle);

注意:fopen() 打开文件后切记关闭文件指针! fclose();

fread 所读取的字符串, 或者在失败时返回 FALSE

function fread($stream, int $length): string|false {}  

fseek 可以在打开的文件中移动文件指针的位置,以便在不同位置进行读取和写入操作。

0 表示成功,返回 -1 表示失败

  • $handle:打开的文件指针资源。

  • $offset:要移动的字节数。

  •   $whence
    

    (可选):指定偏移量的基准位置。可使用以下常量之一:

    • SEEK_SET:从文件开头开始计算偏移量。
    • SEEK_CUR:从当前位置开始计算偏移量。
    • SEEK_END:从文件末尾开始计算偏移量。
$file = fopen('file.txt', 'r');
// 将文件指针移动到文件的第 10 个字节处
fseek($file, 10, SEEK_SET);
// 从当前位置向后移动 5 个字节
fseek($file, 5, SEEK_CUR);
// 从文件末尾向前移动 20 个字节
fseek($file, -20, SEEK_END);
fclose($file);
//例子:
$data = "./test.txt";
$f = fopen($data,'r');
fseek($f,200, 0);
$content = "";
while (!feof($f)){
    $content .= fread($f , 1024);
}
fclose($f);
echo $content;

**fwrite 写入文件,返回写入的字符数,出现错误时则返回 **FALSE

fclose 关闭一个已打开的文件指针

feof 测试文件指针是否到了文件结束的位置

$handle = fopen('./text.txt','w+');
fwrite($handle,'Hello php');
fseek($handle, 0);
echo fread($handle, 999);
fclose($handle);

fgetc 读取一个字符

fgets 读取一行内容

fgetss 从文件指针中读取一行并过滤掉 HTML 标记。参数分别表示:资源对象、读取数量、允许标签。

fgetcsv 从文件指针中读入一行并解析 CSV 字段。

readfile 读取文件全部内容 (大文件慎用)

$data = './test.txt';
$handle = fopen($data,'r+');
while ($s = fgetc($handle)){
    echo $s;
}
while ($s = fgets($handle)){
    echo $s;
}
fclose($handle);
$handle = fopen('index.html','rb');
while(!feof($handle)){
    echo fgetss($handle,20,'<h1><title>');
}
fclose($handle);
$data = './customer.csv';
$handle = fopen($data,'r');
while (($res = fgetcsv($handle) )!== false){
    print_r($res);
}
fclose($handle);
header('Content-type:image/jpeg');
readfile('user.jpeg');

flock 锁定文件操作,如果使用flock 锁定文件,必须保证在所有使用文件地方执行 flock 才有意义。如果过早的系统因为不支持锁定操作,函数执行将没有效果如 FAT 系统。

锁定方式说明
LOCK_SH取得共享锁定(读取的程序)
LOCK_EX取得独占锁定(写入的程序)
LOCK_UN释放锁定(无论共享或独占)
LOCK_NB无法建立锁定时,此操作可不被阻断,马上返回进程。通常与 LOCK_SH 或 LOCK_EX 做 OR(|)组合使用。(Windows 系统上还不支持)
//写锁 LOCK_SH
// 1.php
$handle = fopen('demo.txt','rb');
$stat = flock($handle,LOCK_SH);
sleep(5);
echo fgetss($handle);
flock($handle,LOCK_UN);//2.php
$handle = fopen('demo.txt','rb');
$stat = flock($handle,LOCK_SH);
echo fgetss($handle);
flock($handle,LOCK_UN);
//读锁 LOCK_EX
//1.php
$handle = fopen('demo.txt','rb');
$stat = flock($handle,LOCK_EX);
sleep(5);
echo fgetss($handle);
flock($handle,LOCK_UN);//2.php
$handle = fopen('demo.txt','rb');
$stat = flock($handle,LOCK_SH);
echo fgetss($handle);
flock($handle,LOCK_UN);

防止阻塞

//1.php
$handle = fopen('demo.txt','ab');
$stat = flock($handle,LOCK_EX);
sleep(5);
echo fgetss($handle);
flock($handle,LOCK_UN);
//2.php
$handle = fopen('demo.txt','ab');
$stat = flock($handle,LOCK_SH | LOCK_NB,$wouldblock);
if($stat){
    $d = fwrite($handle,'Hello Php!');
    echo fgetss($handle);
}else{
    echo 'file is locked';
}
flock($handle,LOCK_UN);

file_put_contents 将一个字符串写入文件。

file_get_content 将整个文件读入一个字符串,如果打开远程文件需要开启 php.ini 中的 allow_url_fopen 选项。

file_put_contents('demo.txt','hello php',FILE_APPEND); //FILE_APPEND 文件后面追加
file_get_contents('demo.txt');
file_get_contents('https://bing.com');

var_export

输出或返回一个变量的字符串表示。

下面是将数组保存到文件中的代码,并支持 include 获取数组数据。

$user = [
    ['name'=>'刘备'],
    ['name'=>'关羽'],
     ['name'=>'张飞']
];
$content =var_export($user,true);
file_put_contents('users.php','<?php return '.$content.';');

opendir 函数类似于 fopen 操作方式,可能获取目录指针读取目录

scandir 列出指定路径中的文件和目录

$handle = opendir('../php');
while (false!==($file = readdir($handle))) {
    if (!in_array($file, ['.','..'])) {
        echo filetype($file)."\t".$file.'<br/>';
    }
}
closedir($handle);
foreach (scandir('../php') as $file) {
    if (!in_array($file, ['.','..'])) {
        echo filetype($file)."\t\t".$file.'<hr/>';
    }
}

glob 寻找与模式匹配的文件路径。

选项说明
GLOB_MARK在每个返回的项目中加一个斜线
GLOB_NOSORT按照文件在目录中出现的原始顺序返回(不排序)
GLOB_NOCHECK如果没有文件匹配则返回用于搜索的模式
GLOB_ERR停止并读取错误信息(比如说不可读的目录),默认的情况下忽略所有错误
GLOB_BRACE设置多个匹配模式,如:{.php,.txt}

遍历目录

$files = glob('../../*');
print_r($files);

指定检索文件类型

$files = glob('*.php', GLOB_ERR);

设置多个匹配模式

$files = glob("{*.php,*.txt}", GLOB_BRACE);
print_r($files);

目录大小

function dirSize($dir):int
{
    $size= 0;
    foreach (glob($dir.'/*') as $file) {
        $size += is_file($file)?filesize($file):dirSize($file);
    }
    return $size;
}
echo round(dirSize('/home/vagrant')/1024/1024).'MB';

删除目录

function delDir($dir):bool
{
    if (!is_dir($dir)) {
        return true;
    }
    foreach (glob($dir.'/*') as $file) {
        is_file($file)?unlink($file):delDir($file);
    }
    return rmdir($dir);
}
delDir('../php2');

复制目录

function copyDir($dir, $to):bool
{
    is_dir($to) or mkdir($to, 0755, true);
    foreach (glob($dir.'/*') as $file) {
        $target = $to.'/'.basename($file);
        is_file($file)?copy($file, $target):copyDir($file, $target);
    }
    return true;
}
copyDir('../php', '../php2');

移动目录

移动目录分两步执行,第一步是复制目录,第二步是删除目录,所以使用上面两个函数的综合即可以。

function moveDir($dir, $to):bool
{
    copyDir($dir, $to);
    return delDir($dir);
}

PHP文件上传下载

1、环境配置

修改 PHP.ini 配置文件可以定制上传机制,通过 phpinfo() 函数可以查看到 PHP.ini 文件所在位置。

配置说明
file_uploads是否允许上传文件,On 开启 Off 禁止上传
upload_tmp_dir文件上传过程中临时保存的目录,默认保存位置为 /tmp
upload_max_filesize允许上传的最大文件大小,可以使用 K、M、G 单位如 2M
post_max_sizePHP 将接受的最大 POST 数据大小,包括上传文件、表单数据。所以 post_max_size 要大于 upload_max_filesize
max_file_uploads单个请求时,允许上传的最大文件数量

2、超全局数组

上传的文件保存在 $_FILES 超全局数组中,具体参数说明如下:

选项说明
tmp_name临时文件名
name上传文件原文件名
type文件 MIME 类型
error错误编号
size文件大小,单位字节
//index.html 
<form action="./server.php" enctype="multipart/form-data" method="post">
        <label>
            <input type="file" name="files" value="" >
        </label>
        <button type="submit">提交</button>
 </form>
     
 //server.php
   print_r($_FILES); /*Array
(
    [files] => Array
        (
            [name] => Key.txt
            [full_path] => Key.txt
            [type] => text/plain
            [tmp_name] => C:\wamp64\tmp\php665C.tmp
            [error] => 0
            [size] => 54
        ))*/
    

3、错误说明

上传出错会在$_FILES[‘error’] 选项中体现,具体错误说明如下:

  • UPLOAD_ERR_OK (0): 没有错误,文件上传成功。

  • UPLOAD_ERR_INI_SIZE (1): 上传的文件大小超过了php.ini中upload_max_filesize指令所设置的大小限制。

  • UPLOAD_ERR_FORM_SIZE (2): 上传的文件大小超过了HTML表单中MAX_FILE_SIZE指令所设置的大小限制。

  • UPLOAD_ERR_PARTIAL (3): 文件只有部分被上传。

  • UPLOAD_ERR_NO_FILE (4): 没有文件被上传。

  • UPLOAD_ERR_NO_TMP_DIR (6): 找不到临时文件夹。

  • UPLOAD_ERR_CANT_WRITE (7): 文件写入失败。

  • UPLOAD_ERR_EXTENSION (8): 由于PHP扩展的限制,文件上传被停止。

4、上传安全

检测文件是否是合法的上传文件,以保证安全。

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 检查文件是否成功上传
    if (isset($_FILES['file_name']) && $_FILES['file_name']['error'] === UPLOAD_ERR_OK) {
        // 文件上传成功
        $tempFilePath = $_FILES['file_name']['tmp_name'];
        $fileName = $_FILES['file_name']['name'];        // 执行进一步的处理操作
        // ...        echo "文件上传成功!";
    } else {
        // 文件上传失败或未选择文件
        echo "文件上传失败!";
    }
}
?>

5、处理类

下面是支持单文件、多文件上传的处理类。

index.html

<form action="./server.php" method="post" enctype="multipart/form-data">
        <input type="file" name="image">
        <input type="file" name="image[]">
        <input type="file" name="image[]">
        <button class="btn">提交</button>
</form>

server.php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 检查是否有文件上传
    if (isset($_FILES['images'])) {
        $fileCount = count($_FILES['images']['name']);
        
        // 遍历每个上传的文件
        for ($i = 0; $i < $fileCount; $i++) {
            // 检查文件是否成功上传
            if ($_FILES['images']['error'][$i] === UPLOAD_ERR_OK) {
                $tempFilePath = $_FILES['images']['tmp_name'][$i];
                $fileName = $_FILES['images']['name'][$i];                // 执行进一步的处理操作
                // ...                echo "文件 $fileName 上传成功!<br>";
            } else {
                // 文件上传失败或未选择文件
                echo "文件上传失败!<br>";
            }
        }
    } else {
        // 没有文件被上传
        echo "没有文件被上传!<br>";
    }
}

6、文件下载

$file = "dog.jpg";
$fileName = basename($file);
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename={$fileName}");
header("Accept-ranges: bytes");
header("Content-Length: " . filesize($file));
readfile($file);

PHP错误处理和异常处理

1、错误处理的分类

语法错误: 违背了PHP程序语言的规则错误,称之为语法错误。

运行错误: 经过语法错误检测后,将开始运行 PHP 代码,在此发生的错误为运行时错误。

逻辑错误: 逻辑错误是指程序开发过程中由于业务逻辑造成错误。

print_r(数组类型)   //没有以分号结束语句,报语法错误/*
加载不存在文件
连接数据库失败
远程请求失败
函数或类不存在
*/require 'request.php'; //因为加载不存在文件,所以会发生运行时错误echo (10/0); //逻辑错误,这IDE都会检测到,一般都有提示//逻辑错误
for ($i = 0; $i < 5; $i--) {
    echo $i;
}

2、常见错误报告类型

常量描述
1E_ERROR致命的运行时错误。这类错误一般是不可恢复的情况,例如内存分配导致的问题。后果是导致脚本终止不再继续运行
2E_WARNING运行时警告 (非致命错误)。仅给出提示信息,但是脚本不会终止运行。
8E_NOTICE运行时通知。表示脚本遇到可能会表现为错误的情况。
64E_COMPILE_ERROR致命编译时错误。类似 E_ERROR
2048E_STRICT启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
8192E_DEPRECATED运行时通知。启用后将会对在未来版本中可能无法正常工作的代码给出警告。
8191E_ALL所有错误和警告,除级别 E_STRICT 以外。

注意:修改 php.ini 配置文件, display_errors = On 即开启或者关闭错误显示。

关闭警告与致命错误

error_reporting(~E_WARNING & ~E_COMPILE_ERROR);
require('a');

显示除通知外的所有错误

error_reporting(E_ALL & ~E_NOTICE);
echo $arrays;

关闭错误显示

error_reporting(0);

3、异常处理

基本语法:

try{
    //逻辑代码
}catch(){
    //捕获异常时候的处理
}

注意: 需要手动抛出异常,这与其他语言不同,异常使用 try…cache 触发。

手动抛出异常的方法:

throw new 错误类型($message, $code)

注意:可以设置多个catch,参数Exception 或者继承Exception的类

Exception 类的方法:

方法说明重写
getFile产生异常错误的文件NO,final
getCode错误码NO,final
getLine错误行号NO,final
getMessage错误消息NO,final
__toString对象转字符串后输出内容YES

finally: 需要放在 catch 后,finally无论是否抛出异常都会执行。

登录异常处理的例子:

class LoginException extends Exception {
    // 构造函数
    public function __construct($message, $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
    
    // 将异常对象转为字符串
    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }
    
    // 自定义异常处理函数
    public function logError() {
        // 记录登录错误日志
        error_log("登录异常: " . $this->getMessage());
    }
}function loginUser($username, $password) {
    // 模拟登录逻辑
    if ($username !== "admin" || $password !== "password") {
        throw new LoginException("无效的用户名或密码。");
    }
    
    // 登录成功
    return true;
}try {
    $loggedIn = loginUser("guest", "pass123"); // 尝试登录
    if ($loggedIn) {
        echo "登录成功!";
    }
} catch (LoginException $e) { // 捕获登录异常
    echo "登录失败:" . $e->getMessage() . "\n";
    $e->logError(); // 调用自定义异常处理函数,记录登录错误日志
} catch (Exception $e) { // 捕获其他异常
    echo "发生了一个错误:" . $e->getMessage() . "\n";
}

操作数据库多表联动时捕获异常回滚数据:

try {
    // 连接数据库
    $db = new PDO("mysql:host=localhost;dbname=mydatabase", "username", "password");    // 开始事务
    $db->beginTransaction();    // 执行一系列数据库操作
    $db->exec("INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com')");
    $db->exec("INSERT INTO orders (user_id, product_id, quantity) VALUES (1, 1, 2)");    // 提交事务
    $db->commit();
} catch (PDOException $e) { // 捕获 PDO 异常
    // 回滚事务
    $db->rollBack();    // 记录异常日志
    error_log("数据库操作异常: " . $e->getMessage());
    
    // 输出错误信息
    echo "发生了一个数据库操作异常:" . $e->getMessage() . "\n";
}

总结:

  1. 异常处理应该是有针对性的:捕获和处理那些你知道如何处理的异常类型,而将未知或不可处理的异常传递给更上层的代码进行处理。

  2. 使用合适的异常类型:PHP 中有许多内置的异常类型,如 ExceptionInvalidArgumentExceptionRuntimeException 等。选择合适的异常类型可以更好地组织和识别代码中的异常情况。

  3. 按照异常类型的顺序进行捕获:在 catch 块中,应该按照特定异常类型到更一般异常类型的顺序进行排序。这样可以确保异常被正确捕获,并且避免特定的异常被更一般的异常类型捕获导致无法执行特定的异常处理逻辑。

  4. 使用多个 catch 块进行处理:根据不同的异常类型,使用多个 catch 块来处理不同类型的异常。这样可以更细粒度地处理异常,并根据需要执行特定的逻辑。

  5. 考虑添加日志或错误记录:在异常处理过程中,可以将异常信息记录到日志文件或错误日志中,以便后续的故障排查和分析。

  6. 避免过度捕获异常:不要过度捕获异常,这可能导致隐藏潜在的问题或掩盖错误。只捕获你知道如何处理的异常,并将其他未处理的异常传递给更上层的代码进行处理。

  7. 使用 finally 块(可选):finally 块中的代码无论是否发生异常都会执行。它通常用于释放资源或执行清理操作,以确保在异常发生时资源得到正确处理。

  8. 抛出自定义异常:通过定义自定义异常类,可以更好地组织和标识特定类型的异常。这样可以使代码更加清晰,并提供更丰富的异常信息。

PHP操作MYSQL数据库

PHP 操作数据库的方式有多种如 mysqlmysqliPDO,目前主要使用的是 PDO 处理。

MySQLi或PDO扩展来操作MySQL数据库。这两个扩展提供了一组函数和方法,用于连接到数据库、执行查询、插入、更新和删除数据等操作。

PDO 提供了一个数据访问抽象层,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

// 数据库连接配置
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$database = "your_database";try {
    // 创建数据库连接
    $conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password);    // 设置错误模式为异常
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    // 执行查询
    $sql = "SELECT * FROM your_table";
    $stmt = $conn->query($sql);    // 处理查询结果
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($result as $row) {
        echo "ID: " . $row['id'] . ", Name: " . $row['name'] . "<br>";
    }
} catch (PDOException $e) {
    echo "连接失败: " . $e->getMessage();
}// 关闭数据库连接
$conn = null;

PDO的错误处理

错误类型说明
PDO::ERRMODE_SILENT不显示错误
PDO::ERRMODE_WARNING显示警告错误
PDO::ERRMODE_EXCEPTION抛出异常

MySQLi扩展连接到MySQL数据库,并执行查询操作:

// 数据库连接配置
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$database = "your_database";// 创建数据库连接
$conn = new mysqli($servername, $username, $password, $database);// 检查连接是否成功
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}// 执行查询
$sql = "SELECT * FROM your_table";
$result = $conn->query($sql);// 处理查询结果
if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo "ID: " . $row["id"] . ", Name: " . $row["name"] . "<br>";
    }
} else {
    echo "没有结果";
}// 关闭数据库连接
$conn->close();

常见的MySQLi错误类型:

  1. 连接错误(Connection Errors):
    • mysqli_connect_errno():返回连接错误的错误代码。
    • mysqli_connect_error():返回连接错误的错误消息。
  2. 查询错误(Query Errors):
    • mysqli_errno($conn):返回最近一次查询错误的错误代码。
    • mysqli_error($conn):返回最近一次查询错误的错误消息。
  3. 语法错误(Syntax Errors):
    • mysqli_sqlstate($conn):返回最近一次查询的SQL状态码,用于识别语法错误等。
  4. 预处理错误(Prepared Statement Errors):
    • mysqli_stmt_errno($stmt):返回预处理语句错误的错误代码。
    • mysqli_stmt_error($stmt):返回预处理语句错误的错误消息。

下面是PDO的常用函数:

连接时设置错误类型

$pdo =  new PDO($dns, $config['user'], $config['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

使用 setAttribute 方法设置错误处理方式

$pdo =  new PDO($dns, $config['user'], $config['password']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

exec执行SQL

$pdo->exec("INSERT INTO news (title) VALUES('php_project')");
echo "自增主键:".$pdo->lastInsertId();$affectedRows = $pdo->exec("DELETE FROM news WHERE id>3");
echo "受影响的条数:".$affectedRows;

fetchAll 一次获取所有结果

...
$query = $pdo->query("select * from goods");
$rows = $query->fetchAll();
print_r($rows);
...

fetch 每次获取结果中的一条数据

...
$pdo =  new PDO($dns, $config['user'], $config['password']);
$query = $pdo->query("select * from goods");
while ($field = $query->fetch(PDO::FETCH_ASSOC)) {
	echo sprintf("编号:%s\t名称:%s<br/>", $field['id'], $field['title']);
}

SQL 注入

$query = $pdo->query("SELECT * FROM news WHERE id={$_GET['id']}");

如果 GET 参数如下将产生 SQL 注入

http://ss-s.cc/test/1.php?id=1 or id>1

使用预准备

下面使用参数绑定来执行预准备的查询操作

$sql = "SELECT * FROM news WHERE id=:id";
$sth = $pdo->prepare($sql);
$sth->execute(['id' => $_GET['id']]);
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($rows);

下面使用参数绑定形式的预准备操作执行添加操作

$sql = "INSERT INTO news (title) VALUES(:title)";
$sth = $pdo->prepare($sql);
$sth->execute(['title'=>'ss-s.cc']);
echo $pdo->lastInsertId();

占位符

使用问号占位符是另一种使用预准备的方式

$sth = $pdo->prepare("SELECT * FROM news WHERE id>?");
$sth->execute([3]);
print_r($sth->fetchAll());

使用占位符来执行添加操作

$sql = "INSERT INTO news (title) VALUES(?)";
$sth = $pdo->prepare($sql);
$sth->execute(['ss-s.cc']);
echo $pdo->lastInsertId();

以下是封装好链式调用的一个类:

class QueryBuilder
{
    protected $pdo;
    protected $table;
    protected $select = '*';
    protected $where = '';
    protected $groupBy = '';
    protected $orderBy = '';    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }    public function table($table)
    {
        $this->table = $table;
        return $this;
    }    public function select($columns)
    {
        $this->select = $columns;
        return $this;
    }    public function where($condition)
    {
        $this->where = "WHERE $condition";
        return $this;
    }    public function groupBy($column)
    {
        $this->groupBy = "GROUP BY $column";
        return $this;
    }    public function orderBy($column, $direction = 'ASC')
    {
        $this->orderBy = "ORDER BY $column $direction";
        return $this;
    }    public function get()
    {
        $sql = "SELECT {$this->select} FROM {$this->table} {$this->where} {$this->groupBy} {$this->orderBy}";        $stmt = $this->pdo->query($sql);
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);        return $result;
    }
}// 使用示例
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$database = "your_database";try {
    $pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    $query = new QueryBuilder($pdo);    $result = $query->table('your_table')
                    ->select('id, name, email')
                    ->where('age > 18')
                    ->groupBy('gender')
                    ->orderBy('name', 'ASC')
                    ->get();    foreach ($result as $row) {
        echo "ID: " . $row['id'] . ", Name: " . $row['name'] . ", Email: " . $row['email'] . "<br>";
    }} catch (PDOException $e) {
    echo "错误: " . $e->getMessage();
}

COOKIE&SESSION

1、COOKIE 介绍

Cookie是在客户端(通常是浏览器)存储小型数据的一种方式。当用户访问一个网站时,服务器可以通过在HTTP响应中设置一个名为"Set-Cookie"的头部来发送一个Cookie给客户端。客户端会将这个Cookie存储在本地,并在随后的请求中包含在HTTP头部的"Cookie"字段中发送给服务器。服务器可以读取这个Cookie并使用其中的信息来识别用户。

Cookie可以用于多种目的,例如跟踪用户的会话状态、存储用户偏好设置或者记录用户的浏览历史。Cookie可以设置过期时间,可以是会话级别的,也可以是持久性的。持久性Cookie在指定的过期时间之前会一直保存在客户端,而会话级别的Cookie只在用户关闭浏览器时失效。

然而,Cookie也存在一些限制。由于Cookie是存储在客户端的,因此客户端有可能篡改Cookie的值,这可能导致安全问题。此外,每个请求都会包含所有的Cookie数据,这可能增加网络流量,尤其是当Cookie数据很大或者存在大量的Cookie时。

2、SESSION 介绍

Session是在服务器端存储用户状态的一种机制。当用户访问一个网站时,服务器会为每个用户创建一个唯一的会话标识(session ID),并将这个会话标识存储在服务器上,通常存储在内存中或者数据库中。服务器会将这个会话标识发送给客户端,通常通过Cookie的方式,存储在名为"session ID"的Cookie中。

客户端在随后的请求中会将这个session ID发送给服务器,服务器通过session ID可以找到对应的会话数据,并根据需要更新或读取会话状态。会话数据可以包含用户的身份验证信息、会话变量、购物车内容等。服务器端可以根据需要设置会话的过期时间,以控制会话的有效期。

相比于Cookie,Session的数据存储在服务器端,因此更加安全。客户端只需要保存一个session ID,而不需要保存大量的数据。然而,使用Session也会增加服务器的负担,因为服务器需要存储和管理会话数据,并确保会话的可靠性和一致性。

在实际应用中,Cookie和Session通常一起使用。服务器使用Cookie来发送session ID给客户端,客户端将session ID存储在Cookie中,并在随后的请求中发送给服务器。服务器通过session ID来查找对应的会话数据,从而实现用户状态的跟踪和管理。

3、使用方法

PHP 中使用 setcookie() 函数用户客户端 cookie 数据。

setcookie ( string $name [, string $value = "" [, int $expires = 0 [, string $path = "" [, string $domain = "" [, bool $secure = FALSE [, bool $httponly = FALSE ]]]]]] ) : bool
  1. name(必需):Cookie的名称,作为字符串传递。
  2. value(可选):Cookie的值,作为字符串传递。
  3. expires(可选):Cookie的过期时间,可以是一个Unix时间戳(秒数)或一个表示日期和时间的字符串。默认情况下,Cookie是会话级别的(当浏览器关闭时失效)。
  4. path(可选):Cookie的有效路径。默认情况下,Cookie在设置它的目录及其子目录下可用。
  5. domain(可选):Cookie的有效域名。默认情况下,Cookie在设置它的域名及其子域名下可用。
  6. secure(可选):指示是否只在通过HTTPS协议发送请求时才发送Cookie。默认为false。
  7. httponly(可选):指示Cookie是否只能通过HTTP协议访问,而无法通过JavaScript访问。默认为false。
<?php
$cookieName = "username";
$cookieValue = "JohnDoe";
$cookieExpiration = time() + 3600; // 过期时间为当前时间加1小时
$cookiePath = "/"; // Cookie在整个网站中可用
$cookieDomain = "example.com";
$cookieSecure = true; // 仅通过HTTPS发送Cookie
$cookieHttpOnly = true; // 禁止JavaScript访问Cookiesetcookie($cookieName, $cookieValue, $cookieExpiration, $cookiePath, $cookieDomain, $cookieSecure, $cookieHttpOnly);
?>

注意: 设置COOKIE信息后,客户端每次访问浏览器会自动发送COOKIE数据到服务端,只需加上服务端逻辑就可以到达想要的结果

setcookie('token',base64_encode('张三/管理员/20231206')); // cookie保存token,实际项目需要把token进行hash_hmac,不然容易给解密setcookie('token',base64_encode('张三/管理员/20231206'), time()+60*60*24*30);//+30天内有效期setcookie('token',base64_encode('张三/管理员/20231206'), time()+60*60*24*30,'/public'); //+只能再public路径下使用setcookie('token',base64_encode('张三/管理员/20231206'), time()+60*60*24*30,'/public','baidu.com'); //+限定域名使用setcookie('token',base64_encode('张三/管理员/20231206'), time()+60*60*24*30,'/public','baidu.com',true); //+限制https访问
    
setcookie('token',base64_encode('张三/管理员/20231206'), time()+60*60*24*30,'/public','baidu.com',true,true); //+不允许JS操作cookie 

4、读取COOKIE

print_r($_COOKIE);

5、SESSION的开启方式

1、session_start();

2、通过修改 php.ini 配置项 session.auto_start,自动开启会话(不建议使用)

session_start();
// 设置会话数据
$_SESSION['username'] = 'john';// 获取会话数据
$username = $_SESSION['username'];// 删除会话数据
unset($_SESSION['username']);// 销毁整个会话
session_destroy();

6、常用函数

  1. session_start(): 启动会话,必须在访问会话数据之前调用。
  2. session_destroy(): 销毁当前会话中的所有数据,并释放会话资源。注意,这个函数不会立即删除会话文件,而是在会话结束后才会删除。
  3. session_unset(): 删除会话中的所有数据,但会话仍然保持活动状态。它等效于$_SESSION = array()
  4. session_id(): 获取当前会话的ID。
  5. session_regenerate_id(): 重新生成会话ID,常用于增加会话的安全性。在生成新ID之前,会话中的数据会被保留。
  6. session_save_path(): 获取或设置会话数据的保存路径。

7、应用实例

<?php
// 用户登录处理
if (isset($_POST['LoginSubmit'])) {
    $username = $_POST['username'];
    $password = $_POST['password'];    // 验证用户名和密码(正式项目需要对客户传过来的Password进行password_hash 和 password_verify
    if ($username === 'admin' && $password === 'password') {
        // 登录成功,设置登录状态
        session_start();
        $_SESSION['username'] = $username;        // 设置登录状态的Cookie,有效期为1小时
        $cookieName = 'login_status';
        $cookieValue = 'logged_in';
        $cookieExpiration = time() + 3600; // 过期时间为当前时间加1小时
        $cookiePath = '/'; // Cookie可在整个域名下使用
        $cookieDomain = ''; // Cookie限定域名为空,表示当前域名及其子域名均可使用
        $cookieSecure = false; // 在非HTTPS连接下也可使用
        $cookieHttpOnly = true; // 禁止通过JavaScript访问Cookie
        setcookie($cookieName, $cookieValue, $cookieExpiration, $cookiePath, $cookieDomain, $cookieSecure, $cookieHttpOnly);
        // 重定向到登录后的页面
        header('Location: profile.php');
        exit();
    } else {
        // 登录失败
        echo "Invalid username or password.";
    }
}// 检查是否已登录
session_start();
if (isset($_SESSION['username'])) {
    $username = $_SESSION['username'];
    echo "Welcome, $username!";
    //跳转到登录后的页面例如:主页等
} else {    //跳转到登录页面}

PHP处理图像

PHP是一种功能强大的服务器端脚本语言,也可以用于处理图像。以下是PHP处理图像的一些优势:

  1. 广泛的图像处理库支持:PHP提供了许多图像处理库和扩展,如GD库、Imagick扩展等,这些库提供了丰富的函数和方法,用于图像的创建、修改、裁剪、缩放、旋转、添加水印等操作。

  2. 简单易用:PHP的图像处理函数和方法通常具有简单和直观的语法,使开发人员能够轻松地处理图像,无需深入了解复杂的图像处理算法。这使得即使对图像处理不熟悉的开发人员也能够快速上手。

  3. 与Web开发的紧密集成:由于PHP是一种服务器端脚本语言,与Web开发紧密集成。这使得在Web应用程序中处理和生成图像变得非常方便。你可以根据需要动态地生成图像,将其用作验证码、缩略图、图像合成等。

配置环境

1、在 windows 系统中修改 php.ini 文件,删除 extension=php_gd2.dll 前面的;开启图像处理支持。

2、phpinfo(); 查看是否GD库开启

3、var_dump(extension_loaded(“GD”));

流程

设置HTTP头信息 –> 创建画布 –> 绘图 –> 输出图像 —> 释放资源

  1. 调整图像大小和缩放:

    • imagecreatefromjpegimagecreatefrompngimagecreatefromgif:从不同的图像文件格式创建图像资源。

    • imagescale:调整图像的大小。

    • imagecopyresampled:缩放图像并保持较好的质量。

  2. 裁剪和剪切图像:

    • imagecrop:根据指定的参数裁剪图像。

    • imagecopyresampled:剪切并调整图像的大小。

  3. 添加水印和文字:

    • imagestringimagestringup:在图像上绘制文本。

    • imagecopyimagecopymerge:复制和合并图像,包括添加水印。

  4. 图像旋转和翻转:

    • imagerotate:按指定角度旋转图像。

    • imageflip:水平或垂直翻转图像。

  5. 图像滤镜和效果:

    • imagefilter:应用各种滤镜效果,如灰度、反色、模糊等。

    • imageconvolution:应用卷积滤波器,如边缘检测。

  6. 保存和输出图像:

    • imagejpegimagepngimagegif:将图像保存为不同的文件格式。

    • imagegdimagegd2:以 GD 图像格式输出图像。

  7. 创建画布:

    • imagecreatetruecolor:将根据参数宽高创建画布。
  8. 创建画布:

    • imagecreatetruecolor:将根据参数宽高创建画布。
  9. 设置颜色:

    • imageFill: (x,y)表示从哪个点开始填充颜色的坐标(默认是黑色)。
  10. 绘制图形:

    • imageRectangleimageFilledRectangle :绘制空心矩形或者实心矩形图像并填充颜色。

    • imageEllipseimageFilledEllipse : 绘制空心圆形或者实心圆形图像并填充颜色。

    • imageLine: 绘制线条。

    • imagesetpixel: 绘制像素。

  11. 输出图像:

    • imagegif(img_resource[,filename])

    • imagejpeg(img_resource[,filename])

    • imagepng(img_resource[,filename])

    • imagebmp(img_resource[,filename])

​ 当设置第二个参数时表示储存文件,如果存在同名文件会覆盖

  1. 释放图像

    • imageDestroy:释放图像资源
  2. 输入文本

imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text )

图像资源,字体尺寸,角度,第一个字符的基本点(大概是字符的左下角),Y 坐标(字体基线的位置),颜色 ,字体文件,文本字符串(UTF-8 编码)

imagettfbbox : 文本范围的盒子大小,可以方便控制文本输出位置

变量位置
0左下角 X 位置
1左下角 Y 位置
2右下角 X 位置
3右下角 Y 位置
4右上角 X 位置
5右上角 Y 位置
6左上角 X 位置
7左上角 Y 位置
  1. 外部图像

  2. 打开图片文件

    • imageCreateFromgif(filename/url)

    • imageCreateFromjpeg(filename/url)

    • imageCreateFrompng(filename/url)

    • imageCreateFrombmp(filename/url)

      返回一个资源类型

  3. 获得信息

    • imagesx(img_resource) 取得图像宽度

    • imagesy(img_resource) 取得图像高度

  4. getimagesize(img_file)

    • array getimagesize ( string KaTeX parse error: Expected 'EOF', got '&' at position 19: …ename [, array &̲imageinfo ] )
  5. 图像复制

  6. 拷贝图像的一部分

    • imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )
  7. 拷贝并合并图像的一部分

    • imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )
  8. 图片缩放

拷贝部分图像并调整大小

imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )

应用例子:

生成验证码

class Captcha {
    private $width; 
    private $height;
    private $length;
    private $image;
    private $text;    public function __construct($width = 120, $height = 40, $length = 6) {
        $this->width = $width;
        $this->height = $height;
        $this->length = $length;
    }    public function generate() {
        // 创建画布
        $this->image = imagecreatetruecolor($this->width, $this->height);        // 设置背景颜色
        $backgroundColor = imagecolorallocate($this->image, 255, 255, 255);
        imagefill($this->image, 0, 0, $backgroundColor);        // 生成验证码文本
        $this->text = $this->generateText();        // 在画布上绘制验证码文本
        $textColor = imagecolorallocate($this->image, 0, 0, 0);
        $font = __DIR__ . '/arial.ttf'; // 字体文件路径
        imagettftext($this->image, 20, 0, 10, 30, $textColor, $font, $this->text);        // 添加干扰线
        $this->addNoise();        // 输出图像
        header('Content-Type: image/png');
        imagepng($this->image);        // 销毁画布释放资源
        imagedestroy($this->image);
    }    public function getText() {
        return $this->text;
    }    private function generateText() {
        $characters = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 可选字符集
        $text = '';
        $max = strlen($characters) - 1;        for ($i = 0; $i < $this->length; $i++) {
            $text .= $characters[mt_rand(0, $max)];
        } //随机生成验证码        return $text;
    }    //生成干扰线
    private function addNoise() {
        $noiseColor = imagecolorallocate($this->image, 200, 200, 200);
        for ($i = 0; $i < 10; $i++) {
            imageline($this->image, mt_rand(0, $this->width), mt_rand(0, $this->height),
                mt_rand(0, $this->width), mt_rand(0, $this->height), $noiseColor);
        }
    }
}// 示例用法
$captcha = new Captcha();
$captcha->generate();
$code = $captcha->getText();

添加水印

class Watermark {
    private $image; // 原始图像路径
    private $watermark; // 水印图像路径
    private $position; // 水印位置
    private $opacity; // 水印透明度    /**
     * 创建一个 Watermark 实例
     *
     * @param string $imagePath 原始图像路径
     * @param string $watermarkPath 水印图像路径
     * @param string $position 水印位置(可选,默认为 'bottom-right')
     * @param float $opacity 水印透明度(可选,默认为 0.5)
     */
    public function __construct($imagePath, $watermarkPath, $position = 'bottom-right', $opacity = 0.5) {
        $this->image = $imagePath;
        $this->watermark = $watermarkPath;
        $this->position = $position;
        $this->opacity = $opacity;
    }    /**
     * 将水印添加到图像上
     *
     * @param string|null $outputPath 输出路径(可选,默认为 null,直接输出到浏览器)
     */
    public function addWatermark($outputPath = null) {
        // 创建图像资源
        $image = $this->createImageResource($this->image);
        $watermark = $this->createImageResource($this->watermark);        // 获取图像和水印的宽度和高度
        $imageWidth = imagesx($image);
        $imageHeight = imagesy($image);
        $watermarkWidth = imagesx($watermark);
        $watermarkHeight = imagesy($watermark);        // 根据位置计算水印的坐标
        $position = $this->calculatePosition($this->position, $imageWidth, $imageHeight, $watermarkWidth, $watermarkHeight);        // 将水印合并到图像中
        imagecopymerge($image, $watermark, $position['x'], $position['y'], 0, 0, $watermarkWidth, $watermarkHeight, $this->opacity * 100);        // 输出或保存图像
        if ($outputPath !== null) {
            imagepng($image, $outputPath);
        } else {
            header('Content-Type: image/png');
            imagepng($image);
        }        // 销毁图像资源
        imagedestroy($image);
        imagedestroy($watermark);
    }    /**
     * 创建图像资源
     *
     * @param string $imagePath 图像路径
     * @return resource 图像资源
     * @throws Exception 当图像格式不受支持时抛出异常
     */
    private function createImageResource($imagePath) {
        $extension = strtolower(pathinfo($imagePath, PATHINFO_EXTENSION));        switch ($extension) {
            case 'jpg':
            case 'jpeg':
                return imagecreatefromjpeg($imagePath);
            case 'png':
                return imagecreatefrompng($imagePath);
            case 'gif':
                return imagecreatefromgif($imagePath);
            default:
                throw new Exception('Unsupported image format');
        }
    }    /**
     * 计算水印的位置坐标
     *
     * @param string $position 水印位置
     * @param int $imageWidth 图像宽度
     * @param int $imageHeight 图像高度
     * @param int $watermarkWidth 水印宽度
     * @param int $watermarkHeight 水印高度
     * @return array 水印坐标
     * @throws Exception 当水印位置无效时抛出异常
     */
   private function calculatePosition($position, $imageWidth, $imageHeight, $watermarkWidth, $watermarkHeight) {
        $x = 0;
        $y = 0;        switch ($position) {
            case 'top-left':
                $x = 0;
                $y = 0;
                break;
            case 'top-right':
                $x = $imageWidth - $watermarkWidth;
                $y = 0;
                break;
            case 'bottom-left':
                $x = 0;
                $y = $imageHeight - $watermarkHeight;
                break;
            case 'bottom-right':
                $x = $imageWidth - $watermarkWidth;
                $y = $imageHeight - $watermarkHeight;
                break;
            case 'center':
                $x = ($imageWidth - $watermarkWidth) / 2;
                $y = ($imageHeight - $watermarkHeight) / 2;
                break;
            default:
                throw new Exception('Invalid watermark position');
        }        return ['x' => $x, 'y' => $y];
    }
}// 示例用法
$watermark = new Watermark('image.jpg', 'watermark.png', 'bottom-right', 0.5);
$watermark->addWatermark('output.png');

缩略图

<?php
function createThumbnail($sourcePath, $thumbnailPath, $thumbnailWidth, $thumbnailHeight) {
    // 获取原始图像的信息
    list($originalWidth, $originalHeight) = getimagesize($sourcePath);    // 计算缩略图的比例
    $thumbnailRatio = $thumbnailWidth / $thumbnailHeight;
    $originalRatio = $originalWidth / $originalHeight;    // 根据比例计算缩略图的实际大小
    if ($originalRatio > $thumbnailRatio) {
        $thumbnailActualWidth = $thumbnailWidth;
        $thumbnailActualHeight = $thumbnailWidth / $originalRatio;
    } else {
        $thumbnailActualWidth = $thumbnailHeight * $originalRatio;
        $thumbnailActualHeight = $thumbnailHeight;
    }    // 创建原始图像和缩略图的资源
    $originalImage = imagecreatefromjpeg($sourcePath);
    $thumbnailImage = imagecreatetruecolor($thumbnailWidth, $thumbnailHeight);    // 调整图像大小并将原始图像复制到缩略图中
    imagecopyresampled($thumbnailImage, $originalImage, 0, 0, 0, 0, $thumbnailActualWidth, $thumbnailActualHeight, $originalWidth, $originalHeight);    // 将缩略图保存到文件
    imagejpeg($thumbnailImage, $thumbnailPath);    // 释放图像资源(养成好习惯释放资源)
    imagedestroy($originalImage);
    imagedestroy($thumbnailImage);
}
//使用方法
$sourcePath = 'path/to/original_image.jpg';
$thumbnailPath = 'path/to/thumbnail.jpg';
$thumbnailWidth = 200; // 缩略图的宽度
$thumbnailHeight = 150; // 缩略图的高度createThumbnail($sourcePath, $thumbnailPath, $thumbnailWidth, $thumbnailHeight);

总结:

在使用 PHP 处理图像时,有一些重要的注意点需要考虑:

  1. 安装 GD 库:PHP 的 GD 库是用于图像处理的常见库。在使用之前,确保你的 PHP 环境已安装并启用了 GD 库。你可以在 phpinfo() 中查看是否启用了 GD 库。

  2. 图像格式支持:GD 库支持多种图像格式,包括 JPEG、PNG、GIF 等。根据你的需求选择适合的图像格式,并使用相应的 GD 函数来处理。

  3. 错误处理:在图像处理过程中,可能会发生错误,如无法打开图像文件、内存不足等。确保在代码中进行错误处理,例如使用 try-catch 块捕获异常或使用 imagecreatetruecolor()imagecopyresampled() 函数时检查返回值。

  4. 图像尺寸调整:在创建缩略图或调整图像尺寸时,要确保维持图像的比例,避免图像变形。根据需要,可以裁剪图像、添加边框或在保持比例的同时填充空白区域。

  5. 内存限制:图像处理可能需要大量的内存,特别是处理大尺寸的图像。确保 PHP 配置中的 memory_limit 设置足够大,以便处理所需的图像大小。

  6. 图像优化:在保存图像时,可以使用图像优化工具来减小文件大小,例如使用 JPEG 图像时可以调整图像质量参数来平衡图像质量和文件大小。

  7. 安全性考虑:接受用户上传的图像时,要进行适当的验证和过滤,以防止安全漏洞,如文件包含、路径遍历等。

  8. 扩展功能:PHP 的 GD 库提供了一系列的函数和方法来处理图像,包括裁剪、旋转、水印、滤镜等。根据具体需求,可以深入了解这些功能并灵活运用。

在实际生成开发中还是避免重复造轮子,用第三方库吧~

PHP面向对象编程

PHP面向对象编程(简称OOP)是一种编程范式,通过使用类、对象、继承、封装、多态等概念来组织和管理代码。PHP从版本5开始引入了全面的面向对象支持,并提供了丰富的面向对象编程特性。

PHP面向对象编程的特点(或者说OOP基本都具有得特点):

  1. 类:类是面向对象编程的基本构建块,用于定义对象的属性(成员变量)和行为(方法)。类可以看作是对象的蓝图或模板。

  2. 对象:对象是类的实例化,具体的实体。对象具有类定义的属性和方法,并可以通过对象访问和操作它们。

  3. 封装:封装是一种将数据和相关操作封装在类中的机制,通过访问控制(public、private、protected)来控制对类的成员的访问。

  4. 继承:继承允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展或重写父类的功能,实现代码的复用和层次化结构。

  5. 多态:多态允许使用统一的接口来处理不同类的对象。通过继承和接口实现,可以在不同的类中使用相同的方法名称,但具体的实现可能不同。

  6. 抽象类:抽象类是一种不能被实例化的类,用于作为其他类的基类。它可以定义抽象方法和具体方法,子类必须实现抽象方法。

  7. 接口:接口定义了一组方法的规范,但不包含具体实现。类可以实现一个或多个接口,实现接口的类必须实现接口中定义的所有方法。

PHP面向对象编程提供了更模块化、可维护和可扩展的代码结构。它可以帮助开发者组织和管理复杂的应用程序,并提供了更高的代码重用性和灵活性。

除了面向对象编程还有面向过程:

程序员设计好程序代码流程图,辅助程序设计。优点:用什么功能就编写什么函数 缺点:数据管理上比较混乱 ,主要集中在函数成面上,面向对象把属性和方法进行封装,更好的可重用性和可扩展性。

面向过程的编程语言有:C语言、Fortran、Pascal(也可以OOP)、COBOL

类与对象

万物皆对象,将构成问题的事务分解到各个对象上,建立对象的目的不是为了完成一个工作,而是为了描述某个事务在解决问题中的行为,更符合人的思维习惯,代码重用性高,可扩展性好。面向对象是由一系统具有属性和方法的对象构成,对象之间相互交互 ,从而实现业务需求。

简单理解:先要有类,然后生成对象,对象有属性和方法。

属性:在类中定义的变量,即为成员属性,用于描述对象静态特性的数据可以通过对象来访问和修改。

方法:函数定义在类中即为成员方法,用于描述对象动态特性的操作行为。

生命周期:创建后,生命周期开始,当程序结束后或程序员清除对象后即销毁,或者PHP自动销毁对象。

命名规范:首字母大写,一般一个类放一个文件中。

class Person{
    public string $name = '啊小';
    public int $age = 18;
    public string $sex = '女';
    public function say():void
    {
        //说话的方法
    }    public function run():void
    {
        //奔跑的方法
    }
}$anoxia = new Person; // $xiaoxiao 就是一个对象,通过关键字 new 生成。echo $anoxia->name; //以下是访问属性和方法的调用方式
echo $anoxia->age;
echo $anoxia->sex;
$anoxia->say();
$anoxia->run();

** t h i s ∗ ∗ : 对象中使用 ‘ this**: 对象中使用 ` this:对象中使用this` 指针可以访问属性或方法。

class Person {
    public string $name = '啊小';
    public int $age = 18;
    public string $sex = '女';    public function say(): void {
        echo "{$this->name}说:我性别是{$this->sex}的,今年{$this->age}岁了";
    }    public function run(): void {
        echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
    }
}$anoxia = new Person();echo $anoxia->name . PHP_EOL;
echo $anoxia->age . PHP_EOL;
echo $anoxia->sex . PHP_EOL;
$anoxia->say();
$anoxia->run();

注意: PHP_EOL 是预定义常量,它表示换行符(line break)。

不同操作系统使用不同的换行符来表示新行。例如,Windows 系统使用回车符和换行符(“\r\n”),Unix/Linux 系统使用换行符(“\n”),Macintosh 系统使用回车符(“\r”)。

以下结果是PHP CLI模式下输出得结果:

在这里插入图片描述

类的继承

php通过使用 extends 可以继承父类的属性与方法,在 PHP 中继承是单一的。(多继承可以通过Trait)

class Person {
    public string $name = '迪迦';
    public int $age = 1000;
    public string $sex = '难';    public function say(): void {
        echo "{$this->name}说:我是{$this->sex}的,今年{$this->age}岁了";
    }    public function run(): void {
        echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
    }
}
class SupperMan extends Person {
    public int $ap = 99;
    public int $mp = 100;
    public string $special_move = "动感光波";    public function attacks():void
    {        echo "超人:{$this->name},攻击力:{$this->ap},能量值:{$this->mp},必杀技:{$this->special_move}";    }}$supperMan = new SupperMan();
$supperMan->say();
echo PHP_EOL;
$supperMan->run();
echo PHP_EOL;
$supperMan->attacks();

输出的结果是:

在这里插入图片描述

子类调用父类、方式重写、禁止重写

class Person {
    public string $name = '迪迦';
    public int $age = 1000;
    public string $sex = '难';    public function say(): void {
        echo "{$this->name}说:我是{$this->sex}的,今年{$this->age}岁了";
    }    public function run(): void {
        echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
    }//    public final function run(): void {
//        echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
//    }
}
class SupperMan extends Person {
    public int $ap = 99;
    public int $mp = 100;
    public string $special_move = "动感光波";    public function attacks():void
    {
        echo "超人:{$this->name},攻击力:{$this->ap},能量值:{$this->mp},必杀技:{$this->special_move}";
    }    public function fly():void{        echo "超人:{$this->name},除了再地面对战还可以飞";
    }    public function run(): void
    {
        parent::run(); // 直接用parent::方法名 调用父类的方法        echo  "超人:{$this->name},特有的跑步姿势!帅";
    }}$supperMan = new SupperMan();
$supperMan->run();
echo PHP_EOL;

注意:当子类与父类方法名一致时即方法重写,如果想调用父类可以用直接用parent::方法名 调用父类的方法,当父类方法使用了final声明,那么子类就不能重写父类方法。

封装

名称介绍
public 公有在类的内部与外部或子类都可以访问,是最开放的权限
private 私有定义类的属性和方法,在类的内部可以访问,在类的外部或子类都不可以访问
protected 受保护定义类的属性和方法,在类的内部或子类可以访问,类的外部不可以访问

多继承(Trait)

Trait 是一种代码复用机制,它允许开发者在不同类之间共享方法的集合。当使用多个 Trait 时,可以通过逗号分隔的方式在类中引入多个 Trait。可能会遇到方法命名冲突或访问控制的问题,可以使用 insteadof 关键字来明确指定使用哪个 Trait 中的方法。

trait TraitA {
    public function foo() {
        echo "TraitA's foo\n";
    }
}trait TraitB {
    protected function foo```php
trait TraitA {
    public function foo() {
        echo "TraitA's foo\n";
    }
}trait TraitB {
    protected function foo() {
        echo "TraitB's foo\n";
    }
}trait TraitC {
    protected function foo() {
        echo "TraitC's foo\n";
    }
}class MyClass {
    use TraitA, TraitB, TraitC {
        TraitC::foo as public bar; // 将TraitC的foo方法重命名为bar,并设置为public访问权限
        TraitB::foo insteadof TraitA, TraitC; // 解决TraitA、TraitC和TraitB之间的冲突
    }
}$obj = new MyClass();
$obj->foo(); // 输出:TraitB's foo
$obj->bar(); // 输出:TraitC's foo

抽象方法

抽象方法是一种在抽象类中声明但不提供具体实现的方法。抽象方法只能存在于抽象类中,而抽象类本身不能被实例化,只能被继承。

要声明一个抽象方法,需要在方法前面加上 abstract 关键字,并且不需要提供具体的实现。子类继承抽象类后,必须实现父类中的所有抽象方法,否则子类也必须声明为抽象类。

<?phpabstract class Animal {
    abstract public function makeSound();
}class Dog extends Animal {
    public function makeSound() {
        echo "Woof!\n";
    }
}class Cat extends Animal {
    public function makeSound() {
        echo "Miao!\n";
    }
}$dog = new Dog();
$dog->makeSound(); // 输出:Woof!$cat = new Cat();
$cat->makeSound(); // 输出:Miao!

静态方法

在PHP中,静态方法是属于类本身而不是类的实例的方法。可以通过类名直接调用静态方法,而无需创建类的实例。

要声明一个静态方法,需要在方法前面加上 static 关键字。静态方法可以直接访问类的静态属性,并且不能访问非静态属性。

class MathUtils {
public static function sum(int $a, int $b):int
{
return $a + $b;
}public static function multiply(int $a, int $b):int
{
return $a * $b;
}public  function sub(int $a, int $b):int
{return self::multiply($a, $b) - self::sum($a,$b);
}
}// 调用静态方法
echo MathUtils::sum(5, 3); // 输出:8
echo MathUtils::multiply(5, 3); // 输出:15
$m = new MathUtils();
echo($m->sub(5, 3)); //输出:7

static

  • 需要一个数据对象只服务于类,即类内部可用,对外不可用时。建对象是极其耗费资源的,因此当一个方法具有比较强的公用性的时候,没有必要为了调用这个方法而重新再生成该类的实例。定义的方法或变量在程序第一次加载时即驻留内存,程序结束释放。

static 变量:

  • 通过 static 声明的成员变量为静态变量或叫类变量,是该类的公共变量,在第一次使用时即生成,对于该类的所有对象只有一份,是属于类的,不是属于对象的。static 变量是属于类而不属于对象,可以在任何地方通地类来访问,是类的全局变量,类创建时即存入内存。对多个对象来说,静态数据成员只存储一处,可以节省内存。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值。

static 方法:

  • 用 static 声明的方法为静态方法或叫类方法,执行该方法时不会将对象引用传给函数,所以我们不能访问非静态成员,只能访问静态方法或静态变量。只能使用关于类的方式如 self static parent 等。使用时不用生成对象即可执行

类常量:

使用 const 来定义类常量,常量使用 self::来调用。

类的魔术方法

PHP中的魔术方法(Magic Methods)是一组特殊的方法,用于在特定的情况下自动调用。这些方法以两个下划线(__)开头和结尾,它们允许您拦截并响应类的内部事件,例如实例化、属性访问、方法调用等。

方法名备注
__construct()当一个对象被实例化时自动调用的构造方法。
__destruct()当一个对象不再被引用时自动调用的析构方法。
__get($property)在访问一个不存在或不可访问的属性时自动调用,可以用于动态获取属性的值。
__set($property,$value)在给一个不存在或不可访问的属性赋值时自动调用,可以用于动态设置属性的值。
__isset($property)在使用 isset()empty() 检查一个不存在或不可访问的属性时自动调用。
__call($method, $arguments)在调用一个不存在或不可访问的方法时自动调用。
__callStatic($method, $arguments)在调用一个不存在或不可访问的静态方法时自动调用。
__unset($property)在使用 unset() 删除一个不存在或不可访问的属性时自动调用。
__sleep()在使用 serialize() 时自动调用,用于准备对象序列化过程中需要保存的属性列表。
__wakeup()在使用 unserialize() 时自动调用,用于重新初始化对象。
__toString()当将对象作为字符串进行输出时自动调用。
__set_state($data)在使用 var_export() 导出类时自动调用,用于返回类的代码表示。
__clone()当通过 clone 关键字克隆一个对象时自动调用。
__debugInfo()在使用 var_dump()print_r() 打印对象时自动调用,用于返回调试信息的数组。
class User {
    private $data = [];    public function __construct($name, $email) {
        $this->data['name'] = $name;
        $this->data['email'] = $email;
    }    public function __get($property) {
        if (isset($this->data[$property])) {
            return $this->data[$property];
        }        return null;
    }    public function __set($property, $value) {
        $this->data[$property] = $value;
    }    public function __toString() {
        return "User: " . $this->data['name'] . " (" . $this->data['email'] . ")";
    }    public function __call($method, $arguments) {
        if ($method === 'greet') {
            $name = isset($arguments[0]) ? $arguments[0] : 'Guest';
            echo "Hello, $name! Nice to meet you!";
        }
    }
}$user = new User('John Doe', 'john@example.com');
echo $user->name; // 输出:John Doe
echo $user->email; // 输出:john@example.com$user->age = 25;
echo $user->age; // 输出:25echo $user; // 输出:User: John Doe (john@example.com)$user->greet('Alice'); // 输出:Hello, Alice! Nice to meet you!

抽象类与抽象方法

抽象类和抽象方法是面向对象编程中的概念,用于实现抽象和多态性的特性。具有抽象方法的类为抽象类,抽象方法即为没有内容的空方法,要求子类进行完善内容,抽象类不能实例化,只能继承,通过 extends 来实现,抽象类中也可以定义普通方法。

  • 当父类为抽象类时,子类必须重写父类的抽象方法
  • 抽象类里不一定非要写抽象方法,但有抽象方法的类必须定义为抽象类
  • 抽象类必须继承使用
  • 抽象方法不能有主体即{}

注意:

抽象类(Abstract Class)是不能被实例化的类,它只能被用作其他类的基类。抽象类可以包含具体的方法实现,也可以包含抽象方法的声明。抽象类通过 abstract 关键字进行声明。

抽象方法(Abstract Method)是在抽象类中声明的方法,没有具体的实现代码。它只是定义了方法的名称、参数列表和返回类型,而具体的方法实现需要在继承的子类中完成。抽象方法通过在方法声明中使用 abstract 关键字进行声明。

abstract class AbstractClass
{
   // 强制要求子类定义这些方法
	abstract protected function getValue();	abstract protected function prefixValue($prefix);   // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue();
    }
}

接口(interface )

接口(Interface)是一种定义了一组方法的抽象类型,它只定义了方法的签名(名称、参数和返回类型),而没有具体的实现。接口可以被类实现(implement),一个类可以实现一个或多个接口。

接口与抽象类的区别:

​ 1 接口只能用 implements 实现 抽象类用 extends 继承实现。

​ 2 接口没有数据成员,可以定义常量,抽象类可以有。

​ 3 接口没有构造函数,抽象类可以定义构造函数。

​ 4 接口方法都是 public 抽象类方法可以用 protected private public 来修饰。

​ 5 一个类可以实现多个接口,但只能继承一个抽象类。

​ 6 接口中不可以有成员方法,抽象类可以有成员方法。

例子:

interface Logger {
    public function log($message);
}class DbOperate implements Logger {
    public function log($message) {
        echo "Logging message to a file: $message\n"; //实现log接口方法
    }
}class CreateGoods implements Logger {
    public function log($message) {
        echo "Logging message to a createGoods: $message\n"; //实现log接口方法
    }
}$fileLogger = new DbOperate();
$fileLogger->log("Error Info"); // 输出:Logging message to a file: Error Info$databaseLogger = new CreateGoods();
$databaseLogger->log("Warning"); // 输出:Logging message to a createGoods: Warning

事件,例如实例化、属性访问、方法调用等。

方法名备注
__construct()当一个对象被实例化时自动调用的构造方法。
__destruct()当一个对象不再被引用时自动调用的析构方法。
__get($property)在访问一个不存在或不可访问的属性时自动调用,可以用于动态获取属性的值。
__set($property,$value)在给一个不存在或不可访问的属性赋值时自动调用,可以用于动态设置属性的值。
__isset($property)在使用 isset()empty() 检查一个不存在或不可访问的属性时自动调用。
__call($method, $arguments)在调用一个不存在或不可访问的方法时自动调用。
__callStatic($method, $arguments)在调用一个不存在或不可访问的静态方法时自动调用。
__unset($property)在使用 unset() 删除一个不存在或不可访问的属性时自动调用。
__sleep()在使用 serialize() 时自动调用,用于准备对象序列化过程中需要保存的属性列表。
__wakeup()在使用 unserialize() 时自动调用,用于重新初始化对象。
__toString()当将对象作为字符串进行输出时自动调用。
__set_state($data)在使用 var_export() 导出类时自动调用,用于返回类的代码表示。
__clone()当通过 clone 关键字克隆一个对象时自动调用。
__debugInfo()在使用 var_dump()print_r() 打印对象时自动调用,用于返回调试信息的数组。
class User {
    private $data = [];    public function __construct($name, $email) {
        $this->data['name'] = $name;
        $this->data['email'] = $email;
    }    public function __get($property) {
        if (isset($this->data[$property])) {
            return $this->data[$property];
        }        return null;
    }    public function __set($property, $value) {
        $this->data[$property] = $value;
    }    public function __toString() {
        return "User: " . $this->data['name'] . " (" . $this->data['email'] . ")";
    }    public function __call($method, $arguments) {
        if ($method === 'greet') {
            $name = isset($arguments[0]) ? $arguments[0] : 'Guest';
            echo "Hello, $name! Nice to meet you!";
        }
    }
}$user = new User('John Doe', 'john@example.com');
echo $user->name; // 输出:John Doe
echo $user->email; // 输出:john@example.com$user->age = 25;
echo $user->age; // 输出:25echo $user; // 输出:User: John Doe (john@example.com)$user->greet('Alice'); // 输出:Hello, Alice! Nice to meet you!

抽象类与抽象方法

抽象类和抽象方法是面向对象编程中的概念,用于实现抽象和多态性的特性。具有抽象方法的类为抽象类,抽象方法即为没有内容的空方法,要求子类进行完善内容,抽象类不能实例化,只能继承,通过 extends 来实现,抽象类中也可以定义普通方法。

  • 当父类为抽象类时,子类必须重写父类的抽象方法
  • 抽象类里不一定非要写抽象方法,但有抽象方法的类必须定义为抽象类
  • 抽象类必须继承使用
  • 抽象方法不能有主体即{}

注意:

抽象类(Abstract Class)是不能被实例化的类,它只能被用作其他类的基类。抽象类可以包含具体的方法实现,也可以包含抽象方法的声明。抽象类通过 abstract 关键字进行声明。

抽象方法(Abstract Method)是在抽象类中声明的方法,没有具体的实现代码。它只是定义了方法的名称、参数列表和返回类型,而具体的方法实现需要在继承的子类中完成。抽象方法通过在方法声明中使用 abstract 关键字进行声明。

abstract class AbstractClass
{
   // 强制要求子类定义这些方法
	abstract protected function getValue();	abstract protected function prefixValue($prefix);   // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue();
    }
}

接口(interface )

接口(Interface)是一种定义了一组方法的抽象类型,它只定义了方法的签名(名称、参数和返回类型),而没有具体的实现。接口可以被类实现(implement),一个类可以实现一个或多个接口。

接口与抽象类的区别:

​ 1 接口只能用 implements 实现 抽象类用 extends 继承实现。

​ 2 接口没有数据成员,可以定义常量,抽象类可以有。

​ 3 接口没有构造函数,抽象类可以定义构造函数。

​ 4 接口方法都是 public 抽象类方法可以用 protected private public 来修饰。

​ 5 一个类可以实现多个接口,但只能继承一个抽象类。

​ 6 接口中不可以有成员方法,抽象类可以有成员方法。

例子:

interface Logger {
    public function log($message);
}class DbOperate implements Logger {
    public function log($message) {
        echo "Logging message to a file: $message\n"; //实现log接口方法
    }
}class CreateGoods implements Logger {
    public function log($message) {
        echo "Logging message to a createGoods: $message\n"; //实现log接口方法
    }
}$fileLogger = new DbOperate();
$fileLogger->log("Error Info"); // 输出:Logging message to a file: Error Info$databaseLogger = new CreateGoods();
$databaseLogger->log("Warning"); // 输出:Logging message to a createGoods: Warning

欢迎点赞,评论,加关注!谢谢

点赞(34) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部