函数
函数的特性:
- 控制程序设计的复杂性
- 提高软件的可靠性
- 提高软件的开发效率
- 提高软件的可维护性
- 提高程序的重用性
函数语法
函数名:不区分大小写
函数不能重名
function 函数名称(参数1,参数2 …){
# TODO
return 返回值; // 如需函数有返回值时使用,否则函数返回值为null
}如果函数中没有使用return返回值时则函数返回值为 null
可变函数(变量函数)
PHP 支持变量函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且将尝试执行它。除了别的事情以外,这个可以被用于实现回调函数,函数表等等。
变量函数不能用于语言结构,例如 echo(),print(),unset(),isset(),empty(),include(),require() 以及类似的语句。需要使用自己的外壳函数来将这些结构用作变量函数。
$func = 'md5';
echo $func('hello');
echo '<br>';
echo md5('hello');$file = 'logo.gif';
$action = strtolower(trim(strrchr($file, '.'), '.')); // gif
function jpg()
{
return 'jpeg 类型';
}
function png()
{
return 'png 类型';
}
if (!function_exists($action)) {
echo '文件类型错误';
} else {
echo $action();
}回调函数
回调函数就是调用函数的时候将另外一个函数的名称当作参数传递进去,并且在函数体中进行调用
如何调用回调函数
- 可以通过可变函数的形式在函数体中进行调用:
$array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// 取奇数
function odd($i)
{
if ($i % 2 == 1) {
return $i;
}
}
$filterData = array_filter($array, 'odd');
var_dump($filterData);
// array(5) { [0]=> int(1) [2]=> int(3) [4]=> int(5) [6]=> int(7) [8]=> int(9) }
$array = [1, 3, 5];
function test1($item)
{
return $item * 3;
}
$mapData = array_map('test1', $array);
var_dump($mapData);
// array(3) { [0]=> int(3) [1]=> int(9) [2]=> int(15) }
function test2(&$item)
{
$item *= 2;
return $item;
}
array_walk($array, 'test2');
var_dump($array);
// array(3) { [0]=> int(2) [1]=> int(6) [2]=> int(10) }- 可以通过
call_user_func()和call_user_func_array()进行调用:
function test()
{
return 'test<br>';
}
echo call_user_func('test'); // test
function add($x, $y)
{
return $x + $y;
}
function reduce($x, $y)
{
return $x - $y;
}
echo call_user_func('add', 1, 3), '<br>'; // 4
echo call_user_func_array('reduce', [100, 10]), '<br>'; // 90匿名函数
匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数,最经常用作回调函数参数的值。
匿名函数也可以作为变量的值来使用。
$func = function ($username) {
return $username;
};
echo $func('foo');递归函数
所谓的函数递归调用,就是函数可以在其声明的执行叙述之中调用执行自己。
function recursive($n)
{
if ($n == 1) {
return $n;
}
return $n * recursive($n - 1);
}
echo "当 N 值为 5 时,阶乘为: " . recursive(5); // 120
Closure::call()(PHP7新特性)
class Test {
private $num = 1;
}
$f = function () {
return $this->num + 1;
}
echo $f->call(new Test); // 输出:2
# 低于 PHP7 版本会报错======【常见系统函数】======
字符串比较
strcmp:区分大小写
strcasecmp:不区分大小写
var_dump(strcmp('a', 'b')); // -1
var_dump(strcmp('m', 'b')); // 11
var_dump(strcmp('amc', 'anc')); // -1
var_dump(strcasecmp('A', 'a')); // 0返回ascii码及获取对应的字符
ord:获取ascii码
chr:根据ascii码获取对应字符
$char = 'c';
var_dump(ord($char)); // int(99)
var_dump(chr(99)); // string(1) "c"给一组变量赋值 list()
$arr = [1, 2, 3];
list($a, $b, $c) = $arr;- PHP7新特性
$arr = [1, 2, 3];
[$a, $b, $c] = $arr;获取当前路径 getcwd()
getcwd(): string|false
getcwd(); // 输出:D:\www列出指定路径中的文件和目录 scandir()
$dir = '/tmp';
$files1 = scandir($dir);
$files2 = scandir($dir, 1); // 默认:按字母升序排列;1:按字母降序排列
Array
(
[0] => .
[1] => ..
[2] => bar.php
[3] => foo.txt
[4] => somedir
)
Array
(
[0] => somedir
[1] => foo.txt
[2] => bar.php
[3] => ..
[4] => .
)返回一个 Directory 类实例 dir()
$d = dir(getcwd());
echo "Handle: " . $d->handle . "<br>";
echo "Path: " . $d->path . "<br>";
while (($file = $d->read()) !== false) {
echo "filename: " . $file . "<br>";
}
$d->close();
// 输出:
// Handle: Resource id #3
// Path: D:\www
// filename: .
// filename: ..
// filename: .htaccess
// filename: index.php改变目录 chdir()
echo getcwd() . "\n"; // 输出:/home/www
chdir('public_html');
echo getcwd() . "\n"; // 输出:/home/www/public_html在每个单/双引号(" ')前添加反斜杠 addslashes()
$str = "Is your name O'reilly?";
echo addslashes($str); // 输出: Is your name O\'reilly?加密 md5() sha1()
echo md5('password'); // 输出:5f4dcc3b5aa765d61d8327deb882cf99
echo sha1('password'); // 输出:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8单向字符串散列 crypt()
crypt(string $str, string $salt = ?): string
$str = '时间是一切财富中最宝贵的财富。'; // 声明字符串变量$str
echo '$str加密前的值为:' . $str; // 输出:时间是一切财富中最宝贵的财富。
$cry = crypt($str, 'foo'); // 对变量$str加密
echo '<p>$str加密后的值为:' . $cry; // 输出:focsK.5T3JXeg对除法结果取整 intdiv()(PHP7新特性)
版本要求:> PHP7.0
echo intdiv(9, 3), PHP_EOL; // 3
echo intdiv(10, 3), PHP_EOL; // 3
echo intdiv(5, 10), PHP_EOL; // 0设置变量的类型 settype()
$flo1 = 100.86; // 定义浮点型数据
echo settype($flo1, "int"); // 强制转换数据为整数并输出,返回值:布尔值,输出:1
echo "<br>";
echo $flo1; // 输出:100扩展是否开启 extension_loaded()
var_dump(extension_loaded('gd'));函数检测 function_exists()
用于检测函数是否定义
// 检测user这个函数是否定义:
var_dump(function_exists('user'));
// 判断系统扩展是否安装
if (function_exists('mysql_connect')) {
echo 'Mysql扩展已经安装';
}======【返回函数参数相关】======
func_get_args()
这个函数返回的是包含当前函数所有参数的一个数组
func_get_arg()
函数返回的是指定位置的参数的值
func_num_args()
这个函数返回的是当前函数的参数数量 返回的是数字
function foo($x, $y)
{
var_dump(func_get_arg(1)); // int(200)
var_dump(func_get_args()); // array(2) { [0]=> int(100) [1]=> int(200) }
var_dump(func_num_args()); // 2
}
foo(100, 200);转换指定字符 strtr()
strtr() 函数转换字符串中特定的字符。
/** * 用上下文信息替换记录信息中的占位符 */
function interpolate($message, array $context = array()){
// 构建一个花括号包含的键名的替换数组
$replace = array();
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}
// 替换记录信息中的占位符,最后返回修改后的记录信息。
return strtr($message, $replace);
}
// 含有带花括号占位符的记录信息。
$message = "User {username} created";
// 带有替换信息的上下文数组,键名为占位符名称,键值为替换值。
$context = array('username' => 'bolivar');
// 输出 "Username bolivar created"
echo interpolate($message, $context);返回字符串的长度 strlen()、mb_strlen()
echo strlen("山际见来烟,竹中窥落日。"); // 36
echo mb_strlen("山际见来烟,竹中窥落日。", "UTF8"); // 12替换字符串的子串 substr_replace()
$phone = "13677778888";
echo substr_replace($phone, "****", 3, 4); // 136****8888字母大小写处理 ucfirst()、ucwords()、strtolower()、strtoupper()
$str = "I have a dream";
echo strtolower($str) . "<br>"; // 转换为小写
echo strtoupper($str) . "<br>"; // 转换为大写
echo ucfirst($str) . "<br>"; // 整个字符串首字母大写
echo ucwords($str) . "<br>"; // 整个字符串中以空格为分隔符的单词首字母大写
echo $str;设置用户自定义的错误处理函数 set_error_handler()
// 定义错误函数
function customError($errno, $errstr)
{
echo "<b>错误:</b> [$errno] $errstr";
}
// 设置错误函数的处理
set_error_handler("customError");
// 触发自定义错误函数
echo $foo; // 错误: [8] Undefined variable: foo创建用户自定义的错误消息 trigger_error()
产生一个用户级别的 error/warning/notice 信息
trigger_error(string $error_msg, int $error_type = E_USER_NOTICE): bool
$foo = 5;
if ($foo > 4) {
trigger_error("Value must be 4 or below"); // 创建自定义错误信息
}
// 输出:Notice: Value must be 4 or below in D:\www\index.php on line 5// 定义错误函数
function customError($errno, $errstr)
{
echo "<b>错误:</b> [$errno] $errstr";
}
// 设置错误函数的处理
set_error_handler("customError", E_USER_WARNING);
// trigger_error函数
$test = 5;
if ($test > 4) {
trigger_error("Value must be 4 or below", E_USER_WARNING);
}
// 输出:错误: [512] Value must be 4 or below向服务器错误记录、文件或远程目标发送一个错误 error_log()
error_log(
string $message,
int $message_type = 0,
string $destination = ?,
string $extra_headers = ?
): bool
error_log("错误:error message");
// 此时会在Nginx指定日志文件 error.log 插入一条错误日志抛出异常 throw new Exception()
// 创建可抛出一个异常的函数
function checkNum($number)
{
if ($number > 1) {
throw new Exception("数值必须小于或等于1");
}
return true;
}
// 在try代码块中触发异常
try {
checkNum(2);
// 如果没有异常,则会显示以下信息
echo '没有任何异常';
} // 捕获异常
catch (Exception $e) {
echo '异常信息: ' . $e->getMessage();
}
// 输出:异常信息: 数值必须小于或等于1用户定义异常类
class customException extends Exception
{
public function errorMessage()
{
//错误消息
$errorMsg = '异常发生的行: ' . $this->getLine() . ' in ' . $this->getFile()
. ': <b>' . $this->getMessage() . '</b>不是一个有效的邮箱地址';
return $errorMsg;
}
}
$email = "someone@example.321com";
try {
//检查是否符合条件
if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
//如果邮件地址无效,则抛出异常
throw new customException($email);
}
} catch (customException $e) {
//显示自定义的消息
echo $e->errorMessage();
}
// 输出:异常发生的行: 19 in D:\www\index.php: someone@example.321com不是一个有效的邮箱地址用户自定义异常处理 set_exception_handler()
// 定义顶层的异常处理程序
function myException($exception)
{
echo "<b>异常是:</b> ", $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('正在处理未被捕获的异常');
// 输出:异常是: 正在处理未被捕获的异常获取最后发生的错误、清除最近一次错误 error_get_last()、error_clear_last()
var_dump(error_get_last()); // NULL
error_clear_last();
var_dump(error_get_last()); // NULL
@$a = $b;
var_dump(error_get_last()); // array(4) { ["type"]=> int(8) ["message"]=> string(21) "Undefined variable: b" ["file"]=> string(16) "D:\www\index.php" ["line"]=> int(7) }
error_clear_last();
var_dump(error_get_last()); // NULL======【命名空间】======
作用: 可以将函数声明在指定空间,防止函数重名引起冲突。
命名空间批量导入(PHP7新特性)
use Space\{ClassA, ClassA, ClassB, ClassC as C}下面是定义 User.php 与 Article.php 两个文件内容如下:
User.php 文件内容
namespace User;
function show()
{
echo __NAMESPACE__ . '\\' . __FUNCTION__ . '<hr/>';
}Article.php 文件内容
namespace Article;
function show()
{
echo __NAMESPACE__ . '\\' . __FUNCTION__ . '<hr/>';
}在 Index.php 使用
include 'User.php';
include 'Article.php';
User\show();
Article\show();使用命名空间后就可以定义相同名称的函数了。
======【参数传递】======
按值传递参数
父程序直接传递指定的值或是变量给函数使用。由于所传递的值或变量,与函数里的数值分别储存于不同的内存区块,所以当函数对所导入的数值作了任何变动时,并不会对父程序造成直接影响。
按址传递参数(用“&”符号实现)
相对于按值传递模式,并不会将父程序中的指定数值或目标变量传递给函数,而是把该数值或变量的内存储存区块相对地址导入函数之中。因此当该数值在函数中有任何变动时,会连带对父程序造成影响。
function make(&$num)
{
return ++$num;
}
$a = 1;
make($a);
echo $a; // 2点语法
当传递的参数数量确定时,可以使用…与变量名。函数的所有参数会成为变量的数组元素。
function sum(...$args)
{
// $args = array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
return array_sum($args);
}
echo sum(1, 2, 3); // 6参数默认值
php支持函数的默认方式调用。如果在调用函数时没有指定参数的值,在函数中会使用参数的默认值。 默认参数必须列在所有没有默认值参数的后面。
function mobile($tel, $num = 4, $fix = '*')
{
return substr($tel, 0, -1 * $num) . str_repeat($fix, $num);
}
echo mobile('123123123', 3); // 123123***严格模式(类型声明)
在文件头部定义 declare(strict_types=1) 为严格模式,这样会对函数参数类型进行严格约束。
<?php
// 必须定义在文件头
declare(strict_types=1);
// 参数必须为int类型
function handle(int ...$num)
{
return array_sum($num);
}
try {
//参数类型错误抛出异常
echo handle(1, '2', 3);
} catch (\Throwable $th) {
echo $th->getMessage();
}返回值类型
PHP7中我们可以设置函数允许的返回值类型。
function make(): int
{
return 'Hello world';
}
try {
make();
} catch (\Throwable $th) {
echo $th->getMessage();
// Return value of make() must be of the type int, string returned
}如果设置 ?int 表示返回类型为 int 或 null
function make(): ?int
{
return null;
}
try {
var_dump(make()); // NULL
} catch (\Throwable $th) {
echo $th->getMessage();
}系统会对返回值自动处理
function make(): string
{
return 100;
}
try {
var_dump(make()); // string(3) "100"
} catch (\Throwable $th) {
echo $th->getMessage();
}如果不希望函数返回任何值时,设置返回值为 void
function make(): void
{
return 'Hello world';
}
try {
var_dump(make());
} catch (\Throwable $th) {
echo $th->getMessage();
// Fatal error: A void function must not return a value in xxx/xxx.php on line 4
}======【变量范围】======
变量能见度
所谓变量的能见度,意指变量在程序中的可作用范围。当一个变量执行赋值动作后,会随着声明局部的差异,而有不同的作用范围。大致上来说变量会依据声明的局部分为下列两种:局部变量和全局变量。
局部变量
在函数之中声明的变量就是局部变量,并且该变量只有在函数范围之中才能加以使用。如果其它程序局部需要调用使用该变量值时,必须透过 return 指令,来将其传回至主程序区块以作后续处理。
$k = 0;
function func()
{
$k = 3; //定义局部变量
echo "在函数中显示局部变量\$k值: $k </br>"; // 3
}
func();
echo "在函数外显示变量\$k值: $k <br>"; // 0全局变量
在函数范围之外声明的变量为全局变量,在函数无法直接使用全局变量,函数要使用全局变量,必须要利用global引入或 $GLOBALS超全局数组引入。
$i = 1;
$j = 2;
function test1()
{
global $i, $j;
var_dump($i, $j); // 1 2
$i = 3;
$j = 5;
global $m, $n;
$m = 6;
$n = 7;
}
test1();
var_dump($i, $j); // 3 5
var_dump($m, $n); // 6 7$name = "Hello world";
function func()
{
// 方法1
global $name; //利用 global 引入全局变量
echo $name;
// 方法2
echo $GLOBALS['name'];
// 方法3
// 通过传参func(&$name),以传址&的形式,获取到函数以外的$name的值
}
func();静态变量
PHP支持声明函数变量为静态的static。一个静态变量在所有对该函数的调用之间共享,并且仅在脚本的执行期间函数第一次被调用时被初始化。要声明函数变量为静态关键字static 。通常,静态变量的第一次使用时赋予一个初始值。
function sum(int ...$num): int
{
static $count = 0;
return $count += array_sum($num);
}
echo sum(1, 2, 3); // 6
echo '<br/>';
echo sum(1, 2, 3); // 12function test1()
{
static $i = 1;
echo $i . '<br>';
++$i;
}
test1(); // 1
test1(); // 2
test1(); // 3
test1(); // 4
var_dump($i);
// Warning: Undefined variable $i in XXX on line 16
// NULL