PHP语法进阶
数组
数组能够在单个变量中存储多个值,并且可以根据 键 访问其中的 值
PHP有两种数组:数值数组、关联数组。
数值和关联两个词都是针对数组的键而言的。
先介绍下数值数组,数值数组是指数组的键是整数的数组,并且键的整数顺序是从0开始,依次类推。
数值数组
$maoshu = array("猫叔1","猫叔2","猫叔3","猫叔4","猫叔5");
$maoshu = ["猫叔1","猫叔2","猫叔3","猫叔4","猫叔5"];var_dump($maoshu[1]);
var_dump($maoshu[5]);
$maoshu2 = [];
$maoshu2[3] = '3';var_dump($maoshu2);
关联数组
关联数组是使用您分配给数组的指定的键的数组
$age=["maoshu"=>"35","dong"=>"37"];//或者$age['maoshu']="35";
$age['dong']="37";
获取数组的长度 - count() 函数
echo count($maoshu);
遍历数组
for($i=0;$i<count($maoshu);$i++) {echo $maoshu[$i];echo "<br>";
}foreach ($maoshu as $value)
{要执行代码;
}foreach ($maoshu as $key => $value)
{要执行代码;
}
多维数组
多维数组是包含一个或多个数组的数组
<?php$food = ["fruit" =>["apple"=>['果皮','果肉','果核'],"banana" =>['果皮','果肉','果核']],"vagatable"=>["potato"=>["皮","肉","子"],"tomato"=>["皮","肉","子"]]];
?>
多维数组
foreach($food as $key => $value)
{foreach($value as $kk => $vv){print_r($kk);echo'--';print_r($vv);}
}
函数
函数是一段可重复使用的代码块,可以将一系列操作封装起来,使代码更加模块化、可维护和可重用,来大大节省我们的开发时间和代码量,提高编程效率
内置函数
内置函数有很多,之前学的print_r() count() 就是一个内置函数,
获取当前时间 time(),date('Y-m-d H:i:s')这节我们主要讲自定义函数
创建(定义)函数 和 调用
PHP 函数准则:
- 函数的名称应该提示出它的功能
- 函数名称以字母或下划线开头(不能以数字开头)
function echoname()//函数名称{echo "我的名字是:鼠鼠实习两年半";}echoname();//调用
添加参数
为了给函数添加更多的功能,我们可以添加参数,参数类似变量
function MyName($name){echo "我的名字是:$name";
}
myName("鼠鼠实习两年半");
function nowTime($type){if($type == "time"){echo date('Y-m-d H:i:s');}else if ($type == "day"){echo "H:i:s";}
}nowTime("time");
多个参数
function more($a,$b){echo $a + $b;
}more(5,6);
严格模式 declare(strict_types=1)
在 PHP 中,declare(strict_types=1); 用于启用严格类型检查。这里的 1 是一个布尔值,表示开启严格模式。这样写是为了确保在函数参数和返回值的类型检查中,PHP 会严格遵循你声明的类型。
strict_types=1:启用严格类型检查,要求函数参数和返回值的类型必须严格匹配。例如,如果你定义了一个 int 类型的参数,传入的值必须是整数,不能是浮点数或其他类型。
strict_types=0(或不声明):关闭严格类型检查,PHP 会进行类型转换。例如,传入一个浮点数会被自动转换为整数
//严格模式
declare(strict_type=1)
function more(int $a,int $b){echo $a + $b;}more(5,6);
返回值
return
function plus($a,$b){return $a+$b;
}echo plus(2,3);
局部和全局(global)作用域
-
在所有函数外部定义的变量,拥有全局作用域
-
除了函数外,全局变量可以被脚本中的任何部分访问
-
要在一个函数中使用一个全局变量,需要使用 global 关键字
-
函数内部声明的变量是局部变量,仅能在函数内部访问
$name = "鼠鼠实习两年半"; function test(){global $name;$num = 35;echo $name;} test();
Static作用域
-
当一个函数完成时,它的所有变量通常都会被删除。然而,有时候希望某个局部变量不要被删除。
要做到这一点,请在第一次声明变量时使用 static 关键字 -
每次调用该函数时,该变量将会保留着函数前一次被调用时的值,但是该变量仍然是函数的局部变量
function FunctionName() {static $a =0;echo $a;$a++;echo PHP_EOL; } FunctionName(); FunctionName(); FunctionName(); ?>
-
函数参数作用域
参数是通过调用代码将值传递给函数的局部变量
function test($maoshu){echo $maoshu;
}test('猫叔');
var_dump($maoshu);
unset函数和isset函数
unset()可以删除变量
如果unset函数在函数里面没有办法将全局变量给删掉
如果unset函数在函数里面可以删除函数内的局部变量
$name= "叔叔实习两年半";
function test(){$page = 34;unset($page);var_dump($name);echo "<br>";
}
test();
var_dump($page);
echo "<br>";
var_dump($name);
isset() 可以判断变量是否存在
- 如果isset()函数在函数内部没有办法判断函数外部的全局变量是否存在
- 同样的如果isset()函数在函数外部也没有办法判断在函数内部的变量是否存在
- isset()函数在函数内部只能判断在函数内部的变量是否存在
$name = "叔叔实习两年半";
function test(){$page = "e33";var_dump(isset($page));var_dump(isset($name));
}
test();
var_dump(isset($page));
var_dump(isset($name));
超级全部变量
- $GLOBALS
- $_SERVER- $_REQUEST
- $_POST
- $_GET
- $_FILES
- $_ENV
- $_COOKIE
- $_SESSION
$GLOBALS
-
是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
-
和global的关键字一样可以在函数的外部使用,也可以在函数的内部使用
$name ="叔叔实习两年半";
$num = 20;
print_r($GLOBALS);
function test(){global $name,$num;$name ="叔叔实习两年半";$num="35";
}
test();
echo $name;
echo $num;
$_SERVER
$_SERVER
是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。- 这个数组中的项目由 Web 服务器创建。
- 不能保证每个服务器都提供全部项目;服务器可能会忽略一些,或者提供一些没有在这里列举出来的项目。
print_r($_SERVER)
命名空间
1. 概念与理解
- 一种把 类、函数、变量、常量 等放到逻辑子文件夹中去,以避免命名冲突的方法
- 学好命名空间对我们学习thinkphp/laravel/hyperf等框架有非常巨大的好处
默认情况下,所有常量、类和函数名都放在全局空间下,PHP中不允许两个函数、常量或者类出现相同的名字,否则会产生一个致命的错误
错误案例:
(函数名冲突)
1. 命名空间的基本语法
在PHP中,命名空间通过 namespace
关键字来声明,通常出现在文件的顶部。每个PHP文件可以有一个命名空间声明。命名空间必须是程序脚本的第一条语句 (注释除外)
<?php
namespace MyProject;class MyClass {public function greet() {echo "Hello from MyClass!";}
}
?>namespace app;
namespace app\Model\User;
namespace app\Model\User as UserModel;
2. 使用命名空间中的类
子命名空间
-
在命名空间内部再划分一个命名空间 ,让每个空间独立起来,类似于文件路径的写法。
-
虽然写法类似路径,但跟实际代码文件在文件系统中的路径没有任何关系(除非psr-4等硬性规定)
-
命名空间下可以放函数、类、常量、变量等
但一般不放变量 -
namespace MyProject\Sub\L
2.1 使用完全限定名(Fully Qualified Name)
完全限定名包括了命名空间的完整路径。如果要使用上面的 MyClass
,你需要提供完整的命名空间路径。
<?php
namespace MyProject;class MyClass {public function greet() {echo "Hello from MyClass!";}
}
?><?php
// 使用完全限定名调用 MyClass 类
$obj = new \MyProject\MyClass();
$obj->greet();
?>
2.2 使用 use
语句
- 引入 空间
- 引入 类 use xxx (最常用的)
- 引入 函数 use function xxx
- 引入 常量 use const xxx
- as 取别名
为了简化代码,PHP 允许你使用 use
语句来引入命名空间中的类,这样就可以在当前文件中直接使用类名,而不需要写完整的命名空间路径
<?php
namespace MyProject;class MyClass {public function greet() {echo "Hello from MyClass!";}
}
?><?php
// 使用 use 语句导入命名空间中的类
use MyProject\MyClass;$obj = new MyClass();
$obj->greet();
?>
为了方便管理,一般我们会把不同的类放在不同的文件内,然后使用require或者include引入文件。
同一文件内不建议上面那种写法,不好区分,无法全局调用,可以用下面的写法:
namespace MyProject1{const MS = 'maoshu.fun';function add(){return '这是add-1';} }namespace MyProject2{function add(){return '这是add-2';}}// 全局代码namespace {$c = MyProject1\add();echo $c;echo ' --- ';echo MyProject1\MS;echo ' --- ';$d = MyProject2\add();echo $d;}
限定 非限定 完全限定
限定:带命名空间前缀
echo MyProject1\MS;
非限定:无前缀
echo MS;
完全限定:以\开头的前缀
echo \MyProject1\MS;
2个魔术常量
echo __NAMESPACE__;
echo __METHOD__;
手动/自动加载
手动加载
手动加载方式,判断类是否存在,不存在则先引入文件
if(!class_exists('Animal')){ require 'Animal.php';
}
自动加载 :
1 . spl_autoload_register()
函数
<?php
spl_autoload_register(function($class){require str_replace('\\','/',$class).'.php';
});(new Myproject1\test\maoshu\User()) -> test();
?>
如果要使用函数的话必须先实例化类 才能调用函数
使用composer自动加载
- 初始化
在终端输入
composer init# 然后一直点回车即可
修改psr-4里的文件夹路径
前面是命名空间,后面是文件夹名称,注意大小写
\ \不能去除
"psr-4": {"ms1\\": "ms1"
}
更新composer
composer update
引入autoload文件
include './vendor/autoload.php';
同一命名空间里的类可以直接使用
注册类:
namespace ms1\user;class register {public function __construct() {echo '- 用户注册类';(new login)->main();}
}
登录类:
namespace ms1\user;class login {public function __construct() {echo '- 用户登录类';}public function main(){echo '-这是登录的核心方法-';}
}
调用
spl_autoload_register(function($class){require str_replace('\\','/',$class).'.php';
});use ms1\user\register;(new register);
数据类型转换
整数/浮点数/布尔值转字符串
函数strval ()
<?php
$int =123;
$str = strval($int);
var_dump($str);echo PHP_EOL;$float = 3.14;
$str = strval($float);
var_dump($str);
echo PHP_EOL;$bool = true;
$str= strval($bool);
var_dump($str);// 输出 "1"
//注意:布尔值true转换为字符串时会得到"1",而false则会得到""(空字符串)
类型强制转换 (string)
$bool = true;
$str = (string)$bool;
var_dump($str); // 输出 "1"
字符串连接,隐式转换
$bool = true;
$str = $bool . "";
var_dump($str);
字符串转整数
函数intval ()
$str = "123";
$int = intval($str);
var_dump($int) ; // 输出 123
类型强制转换 (int) 或 (integer)
$str = "123";//$int = (integer)$str;$int = (int)$str;var_dump($int) ;
字符串转浮点数
函数floatval ()
$str = "3.14";
$float = floatval($str);
var_dump($float); // 输出 3.14
强制类型转换 (float) 或 (double)
$str = "3.14";
$float = (float)$str;
var_dump($float); // 输出 3.14
PHPDoc 声明 (文档注释)
vscode需要安装PHP DocBlocker扩展
- @param 表示参数信息
- @return 表示返回值信息
- @throws 表示异常信息
- @see 表示相关信息
- @link 表示链接信息
- @since 表示版本信息
- @author 表示作者信息
- @copyright 表示版权信息
- @license 表示许可证信息
- @version 表示版本信息
- @todo 表示待办事项
- @deprecated 表示已弃用信息
/*** 获取用户信息** @param int $id 用户 ID* @return array 用户信息** @see get_user_by_id() 获取用户信息* @link https://www.example.com/user/get 获取用户信息* @since 1.0.0 版本* @author Maoshu 作者* @copyright Copyright (c) 2024 猫叔* @license MIT License 许可证* @version 1.0.0 版本* @todo 待办事项* @deprecated 已弃用信息*/
function getUserInfo($id)
{// 获取用户信息$user = get_user_by_id($id);// 返回用户信息return $user;
}
函数传参 (传值和传引用)
传值和传引用是两种传递参数的方式。
传值和传引用的主要区别在于传递参数的方式不同,这也会影响到函数或方法对参数的处理方式。
传值是指将参数的值复制一份,然后将这份复制的值传递给函数或方法。函数或方法对参数的修改不会影响到原始数据。
传引用则是指将参数的内存地址传递给函数或方法,这样函数或方法就可以直接访问原始数据,而不是复制一份。函数或方法对参数的修改会直接影响到原始数据。
在函数中的使用
function increment($number) {$number++;echo "函数内部的值:" . $number . "\n";
}$myNumber = 5;
increment($myNumber);
echo "函数外部的值:" . $myNumber . "\n";
在数组中使用
$arr = ["a","b","c","d"];
foreach($arr as &$value){$value = strtoupper($value);
}
print_r($arr);
序列化和反序列化
序列化:是将PHP变量转换为可以存储或传输的字符串格式的过程。这个字符串包含原始变量的所有必要信息以便于将来恢复原状。
反序列化:是将之前序列化的字符串还原回原来的PHP变量结构的过程。
//序列化
print_r(serialize(["1","2","3"]));//反序列化
$serialized = 'a:2:{i:0;s:1:"1";i:1;s:1:"2";}';
$unserialized = unserialize($serialized);print_r($unserialized);
和json_encode有些类似,但又有很大区别。
serialize()
能处理包括数组、对象、布尔值、整数、浮点数、NULL等所有类型,且不丢失其类型和结构,例如对象:
$o = new stdClass;
$o->name = "maoshu";$s = serialize($o);
var_dump($s);var_dump(unserialize($s));
list解构赋值
list()
-
list()
是一个用于同时将数组的值赋给一组变量的特殊构造。 -
它允许你快速地从数组中提取元素,并按照索引顺序将它们分配给对应的变量。
-
自 PHP 7.1 开始,
list()
函数已经被[]
赋值运算符(也称为解构赋值)替代,但为了兼容性,list()
仍然可用。
list($var1, $var2, ..., $varN) = array($value1, $value2, ..., $valueN);//例子:
list($a, $b) = ['maoshu','2024','222'];
//list($a, ,$b) = ['maoshu','2024','222'];
echo $a,PHP_EOL,$b,PHP_EOL;$path = 'users.getinfo.name';
list($a, $b) = explode('.', $path,2);
echo $a,PHP_EOL,$b,PHP_EOL;
list()
函数仅适用于索引数组,对于关联数组无效,因为它是基于索引而不是键来赋值的
//例如这段就会报错
list($a, $b) = ["name"=>'maoshu','2024'];
//list($a, $b) = ["1"=>'maoshu',"0"=>'2024'];
echo $a,PHP_EOL,$b,PHP_EOL;//改正:
list($a, $b) = array_values(["name"=>'maoshu','2024']);
支持嵌套使用
list($a, list($b, $c)) = array(1, array(2, 3));var_dump($a, $b, $c);
赋值给新的数组
$info = array('1', '2', '3');
list($arr[0], $arr[1], $arr[2]) = $info;
var_dump($arr);
在循环在直接解构
$array = [[1, 2], [3, 4], [5, 6]];foreach($array as list($odd, $even)){echo "$odd is odd; $even is even", PHP_EOL;
}
解构关联数组
$array = ['name' => 'Maoshu','cn' => '猫叔','age' => 35,
];// 使用解构赋值将关联数组的元素分别赋给已存在的或新声明的变量
['name'=>$name,'cn'=> $cn, 'age'=>$age] = $array;echo $name;
echo $cn;
echo $age;
文件和目录
文档地址: https://www.php.net/manual/zh/book.filesystem.php
文件操作
首先准备一个文件:
$filename = './maoshu.txt';
文件是否存在与信息获取
文档地址: https://www.php.net/manual/zh/function.file-exists.php
使用 file_exists()
判断文件或目录是否存在。
var_dump(file_exists('./maoshu3.txt'));
使用 is_file()
和 is_dir()
判断是否为普通文件或目录。
//如果文件不存在,也会返回false
var_dump(is_file('./maoshu.txt'));
- is_file() - 判断给定文件名是否为一个正常的文件
- is_readable() - 判断给定文件名是否可读
- is_writable() - 判断给定的文件名是否可写
- file() - 把整个文件读入一个数组中
basename()
获取文件名部分
//将返回maoshu.txt
basename('./ms/test/maoshu.txt')
dirname()
获取目录路径部分
//将返回./ms/test
dirname('./ms/test/maoshu.txt')
使用 filesize()
获取文件大小。
//返回int类型。
//如果文件不存在,则会报错(Warning),返回false
var_dump(filesize('./maoshu.txt'));
使用 filemtime()
获取文件最后修改时间。
//返回int类型的时间戳
//如果文件不存在,则会报错(Warning),返回false
var_dump(filemtime('./maoshu.txt'));
//fileatime 文件上次被访问的时间
filetype()获取文件类型
//返回file
var_dump(filetype('./maoshu.txt'));
//返回dir
var_dump(filetype('./error'));
下面是几种常见的类型:
文件类型 | 类型说明 |
---|---|
dir | 目录类型,目录也是文件的一种 |
file | 普通文件类型,如文本文件、可执行文件等 |
unknown | 未知类型 |
打开与关闭文件
打开
// r 只读模式,从文件头开始读,如果文件不存在则返回 FALSE
// r+读写模式,从文件头开始读写// w 写入模式,从文件头开始,会删除原有内容;如不存在则会创建文件
// w+读写模式// a 追加模式
// a+追加读写模式//
$file = fopen($filename, 'r');
r 与w 区别于是否会创建文件(若文件不存在) 或者清空文件内容
关闭
// 在结束文件操作后关闭文件
fclose($file);
读取文件
读取整个文件
$content = file_get_contents($filename);
echo $content;
按行或指定大小逐块读取文件
使用 fgets()
或 fread()
if ($file) {$i=1;while (!feof($file)) {$line = fgets($file);echo $i.' - '.$line;$i++;}fclose($file);
}//逐块读取
fread($file, 1024);
fgets(resource $stream
, ?int $length
= null
): string|false
可以指定最多获取多少字节的文字,默认为1024
feof()
函数是检测文件指针是否已经到达了文件的末尾(End Of File)。当你逐行或逐块读取一个文件时,可以使用 feof()
函数来判断是否还有更多的内容可读。
区别:
- 如果你需要按字节读取任意格式的数据(如图像、音频等非文本格式),选择
fread()
更合适。 - 当你需要按行读取文本数据时,应使用
fgets()
,因为它可以自动处理换行符并确保每次读取的是完整的一行文本。
写入文件
fputs或fwrite函数
fputs () 是 fwrite() 的别名
$file = fopen($filename, 'r+');
$data = "Hello, World111233322!";
fputs($file, $data);
fputs($file, $data);
在当前打开的文件里写入数据 (会覆盖)
fwrite ()
$file = fopen($filename, 'w');
fwrite($file, "测试22333");
fclose($file);
追加:通过 'a'
或 'a+'
模式
$file = fopen($filename, 'a');
fwrite($file, "\n这是新增的内容");
fclose($file);
使用 file_put_contents()
将数据写入文件(会覆盖原内容,如果文件不存在,则会自动创建)
$data = "Hello, World!";
file_put_contents('maoshu2.txt', $data);
删除文件
//删除成功,返回true
//如果不存在则报错并返回false
unlink($filename);
复制文件
copy('被复制的文件路径', '复制到的文件路径');
//如果复制到的文件不存在,则会先创建;
//不能创建目录,复制到的文件目录必须先已经存在
//复制成功则返回true,失败则报错,并返回false
copy($filename, './maoshu_copy.txt');
重命名文件
//成功则返回true,失败则报错,并返回false
//注意这里需要他们在同级目录下
rename($old_file_name, $new_file_name)
目录操作
创建和删除目录
创建目录
mkdir('路径名称',目录权限,是否递归)
目录权限,最常见的是755,777如图所示
// 创建单级目录(不递归)
$dirPath = './myDirectory';
if (!file_exists($dirPath)) {if (mkdir($dirPath, 0755)) { // 使用默认权限0755创建目录echo "目录 '$dirPath' 创建成功";} else {echo "无法创建目录 '$dirPath'";}
} else {echo "目录 '$dirPath' 已经存在";
}
创建多级目录
// 创建多级目录(递归)
$multiLevelDirPath = './level1/level2/level3';
if (!file_exists($multiLevelDirPath)) {// 设置第三个参数为true以实现递归创建if (mkdir($multiLevelDirPath, 0755, true)) {echo "多级目录 '$multiLevelDirPath' 创建成功";} else {echo "无法创建多级目录 '$multiLevelDirPath'";}
} else {echo "多级目录 '$multiLevelDirPath' 已经存在";
}
遍历目录
//将得到一个数组
scandir(目录路径);glob('./*.txt');
递归删除非空目录
$dirpath ='./ccc/liu/filename';
function removedir($dirpath){if(is_dir($dirpath)){var_dump(scandir($dirpath));foreach (scandir($dirpath) as $key => $value) {if($value != '.' && $value != '..'){if (is_dir($dirpath.'/'.$value)){removedir($dirpath.'/'.$value);}else{unlink($dirpath.'/'.$value);}}}var_dump(rmdir($dirpath));}else{echo '不是目录';}
}removedir($dirpath);
统计目录下的文件大小和数量
$dirpath ='./ccc/liu';function countFile($dirpath){$totalsize = 0;$filecount = 0;if(is_dir($dirpath)){foreach(scandir($dirpath) as $key => $value){if($value != '.' && $value != '..' ){$filepath = $dirpath.'/'.$value;if(is_dir($filepath)){list($subdirsize,$subfilecount) = countFile($filepath);$totalsize += $subdirsize;$filecount += $subfilecount;// $size = filesize($filepath);// $totalsize+=$size;// $filecount+=1;}else{$totalsize += filesize($filepath);$filecount++;}}}return [$totalsize, $filecount];}else{echo $dirpath."不是目录";return [0, 0]; }
}
list($totalsize, $filecount) = countFile($dirpath);
echo "总文件大小: " . $totalsize . " 字节\n";
echo "文件总数: " . $filecount . "\n";
数组过滤array_filter
array_filter
是 PHP 中的一个函数,用于过滤数组中的元素。它会遍历数组,应用一个回调函数(如果提供了回调函数),并且根据回调函数的返回值来决定是否保留数组中的每个元素。它的常见用法是在数组中去除某些元素,或者仅保留符合特定条件的元素。
array_filter(array $array, callable $callback = null, int $mode = 0): array
参数说明
-
$array:要过滤的原始数组。
-
$callback:可选参数。如果提供了回调函数,
array_filter
会调用它来检查每个数组元素是否应保留。回调函数接收一个数组元素作为参数,返回true
或false
。如果返回true
,该元素将被保留;如果返回false
,该元素会被移除。 -
$mode
:可选参数。可以是以下两个值之一:
ARRAY_FILTER_USE_KEY
:如果传入这个值,则回调函数将接收到数组的键而不是值作为参数。ARRAY_FILTER_USE_BOTH
:如果传入这个值,则回调函数将接收到数组的键和值作为参数。
$array = array('key1' => 'apple','key2' => 'banana','key3' => 'cherry' );$new_array = array_filter($array,function($key){return strpos($key, 'key1') !== false; },ARRAY_FILTER_USE_KEY);print_r($new_array); //输出Array ([key1] => apple)