likes
comments
collection
share

盘点总结一下Php8开发中常用的一些特性

作者站长头像
站长
· 阅读数 22

作为一名phper,我们知道,php8是直接用从php7.4跳过来的,php8.0给php带来了很多新功能和新特性。本文盘点总结一下这些新特性具体使用。盘点总结一下Php8开发中常用的一些特性

联合类型(Union types)

PHP 中的联合类型允许您指定变量或函数参数可以接受多种类型。此功能是在 PHP 8.0 中引入的,目的是在类型声明中提供更大的灵活性。联合类型使用|来联合数据类型下面是一个演示 PHP 中联合类型用法的示例:

function processValue(int|float|string $value): void {
  if (is_int($value)) {
    echo "Processing an integer: $value\n";
  } elseif (is_float($value)) {
    echo "Processing a float: $value\n";
  } elseif (is_string($value)) {
    echo "Processing a string: $value\n";
  } else {
    echo "Invalid value!\n";
  }
}

$value1 = 42;
$value2 = 3.14;
$value3 = "Hello";

processValue($value1);
processValue($value2);
processValue($value3);

在此示例中, processValue 函数接受类型 int 、 float 或 string 的参数 $value 。这是使用联合类型声明 int|float|string 指定的。在函数内部,我们可以使用条件语句(6, elseif )和类型检查函数( is_int() , is_float() , is_string() )来适当地处理不同的类型。调用 processValue 函数时,我们可以传递任何指定类型( int 、 float 或 string )的变量。该函数将根据参数的实际类型处理每种情况。联合类型允许您在类型声明中更具表现力,并在使用可接受多种类型的变量或函数参数时提供更大的灵活性。它有助于提高类型安全性并防止运行时与类型相关的错误。

可空类型(Nullable types)

可为 null 的类型允许您指示变量或函数参数可以接受特定类型或为 null 。PHP 7.1 中引入了可为空的类型,作为增强类型安全性和表示变量或参数为 null 的可能性的一种方式。若要声明可为 null 的类型,可以在类型名称前使用问号 ( ? )。下面是一个示例:

function processValue(?string $value): void {
    if ($value !== null) {
        echo "Processing string: $value\n";
    } else {
        echo "Value is null\n";
    }
}

$value1 = "Hello";
$value2 = null;

processValue($value1);  // Output: Processing string: Hello
processValue($value2);  // Output: Value is null

在本示例中, processValue 函数接受可以是 string 或 null 的参数 $value 。 ?string 类型声明指示参数可以接受字符串值或为 null 。在函数内部,我们在处理之前使用 !== 运算符检查该值是否不为 null。这样,我们可以处理值为 null 的情况,而不是处理有效字符串的情况。使用 nullable 类型有助于使代码更明确地说明 null 值的可能性,这可以防止与 null 相关的错误并提高代码清晰度。值得注意的是,从 PHP 7.1 开始,可为空的类型只能用于基本类型和自定义类

数组解构

在之前php7版本中,我们都用list来解构索引数组。解构允许您以方便的方式将数组中的值分配给各个变量。下面是使用 list() 进行数组解构的示例:

$array = ['Apple', 'Banana', 'Cherry'];

list($fruit1, $fruit2, $fruit3) = $array;

echo $fruit1;  // Output: Apple
echo $fruit2;  // Output: Banana
echo $fruit3;  // Output: Cherry

在此示例中,list() 函数用于解构索引数组 array。变量array 。变量 array。变量fruit1 、 fruit2和fruit2 和 fruit2fruit3 被分配了数组中的相应值。但在php8之后,我们直接使用方括号语法进行数组解构

$array = ['Apple', 'Banana', 'Cherry'];

[$fruit1, $fruit2, $fruit3] = $array;

echo $fruit1;  // Output: Apple
echo $fruit2;  // Output: Banana
echo $fruit3;  // Output: Cherry

在这种情况下,方括号用于将数组 array分解为单独的变量array 分解为单独的变量 array分解为单独的变量fruit1 、 fruit2和fruit2 和 fruit2fruit3 。需要注意的是,左侧的变量数(在 list() 或方括号语法中)必须与数组中的元素数匹配。否则,您可能会遇到“未定义的偏移量”或“未定义的变量”错误。您也可以通过在左侧保留空插槽来仅解构数组的一部分:

$array = ['Apple', 'Banana', 'Cherry', 'Durian'];

[, $fruit2, $fruit3] = $array;

echo $fruit2;  // Output: Banana
echo $fruit3;  // Output: Cherry

使用赋值左侧的空插槽 ( , ) 跳过数组的第一个元素。数组解构提供了一种从索引数组中提取值并将其分配给各个变量以供进一步处理的便捷方法。我们还可以使用方括号语法来解构关联数组(key非数字索引)。

$array = ['name' => 'John', 'age' => 30, 'city' => 'New York'];

['name' => $name, 'age' => $age, 'city' => $city] = $array;

echo $name;  // Output: John
echo $age;   // Output: 30
echo $city;  // Output: New York

在此示例中,方括号用于解构关联数组 array。变量array 。变量 array。变量name 、 age和age 和 agecity 根据其键从数组中分配相应的值。请务必注意,左侧指定的键必须与关联数组中的键匹配。否则,将不会为变量分配正确的值。您也可以仅解构关联数组的一部分,类似于索引数组:

$array = ['name' => 'John', 'age' => 30, 'city' => 'New York'];

['name' => $name, 'city' => $city] = $array;

echo $name;  // Output: John
echo $city;  // Output: New York

空合并运算符

空合并运算符 (??) 是 PHP 7 中引入的一项功能,它提供了一种简洁的方式来处理空值。它允许您为变量分配默认值(如果它为 null)。空合并运算符的语法如下:

$variable = $value ?? $default;

它的工作原理如下:

  • 如果 value不为null,则将值value 不为 null,则将值 value不为null,则将值value 赋值为 $variable 。
  • 如果 value为null,则将值value 为 null,则将值 valuenull,则将值default 赋给 $variable 。

下面是一个示例来说明其用法:

$name = $_POST['name'] ?? 'Anonymous';

在此示例中,如果设置了 POST[′name′]变量而不是null,则其值将赋值为_POST['name'] 变量而不是 null,则其值将赋值为 POST[name]变量而不是null,则其值将赋值为name 。但是,如果未设置 POST[′name′]或为null,则字符串′Anonymous′将分配给_POST['name'] 或为 null,则字符串 'Anonymous' 将分配给 POST[name]或为null,则字符Anonymous将分配给name 。还可以链接空合并运算符以处理多个级别的空值。下面是一个示例:

$result = $value1 ?? $value2 ?? $value3 ?? 'Default';

在这种情况下,如果 value1不为null,则其值将赋值为value1 不为 null,则其值将赋值为 value1不为null,则其值将赋值为result 。如果 value1为null,则进程继续到value1 为 null,则进程继续到 value1null,则进程继续到value2 。如果 value2也为null,则进程继续到value2 也为 null,则进程继续到 value2也为null,则进程继续到value3 。如果所有值都为 null,则字符串 'Default' 将分配给 $result 。null 合并运算符在处理可选或可为 null 的变量时很有用,它提供了一种在不使用条件语句或三元运算符的情况下分配默认值的便捷方法。这里需要和?:做一个区别对比,看下面示例:

<?php
$value1 = 0;
$value2 = null;
$value3 = false;
$result1 = $value1 ?? $value2 ?? $value3 ?? 'Default';
$result2 = $value1 ?: $value2 ?: $value3 ?: 'Default';


echo $result1; //echo 0
echo $result2; // echo 'default'

?:除了接收null,0,‘’,false等标量也加入判断

生成器函数

生成器函数提供了一种定义迭代器的替代方法。您可以使用 Generator 函数创建动态生成值的迭代器,而不是创建实现迭代器接口的迭代器类。生成器函数是使用 function 关键字定义的,但它包含 yield 关键字以指定要生成的值。当函数中遇到 yield 语句时,它会暂时暂停函数的执行并返回生成的值。然后,当迭代器请求下一个值时,可以从中断的位置恢复该函数。下面是生成数字序列的简单生成器函数的示例:

function numberGenerator($start, $end, $step = 1) {
    for ($i = $start; $i <= $end; $i += $step) {
        yield $i;
    }
}

// Create a generator object
$generator = numberGenerator(1, 10, 2);

// Iterate over the generator values
foreach ($generator as $number) {
    echo $number . ' ';
}

在上面的示例中, numberGenerator() 函数被定义为生成器函数。它需要三个参数: start、start 、 startend 和一个可选的 step参数。该函数使用for循环生成从step 参数。该函数使用 for 循环生成从 step参数。该函数使用for循环生成从start 到 end的数字,并指定end 的数字,并指定 end的数字,并指定step 。 yield 语句用于生成每个生成的数字。要使用 Generator 函数,我们通过像常规函数一样调用函数来创建生成器对象。然后,我们可以使用 foreach 循环遍历生成器对象。循环的每次迭代都将检索函数生成的下一个值,并将其分配给 $number 变量。当在生成器函数中遇到 yield 语句时,函数的执行将暂停,并返回生成的值。将保存函数状态,允许在请求下一个值时从中断的位置恢复函数状态。生成器函数提供了一种节省内存的方式来迭代大型数据集或动态生成值,而无需一次将所有值存储在内存中。在需要处理不需要完全加载到内存中的大量数据的情况下,它们特别有用。

Traits

Traits是一种机制,它允许在类中重用代码,而无需使用传统的类继承。特征提供了一种在不同类之间水平共享方法和属性的方法。Traits不需要多做介绍了,其在现代php开发中随处可见特征是使用 trait 关键字后跟特征名称定义的。在特征中,可以定义可由包含特征的类使用的方法和属性。下面是一个特征的示例:

trait Loggable {
    public function log($message) {
        echo "Logging: " . $message . "\n";
    }
}

在上面的示例中, Loggable 特征定义了一个名为 log() 的单个方法。此特征可以包含在其他类中,以使 log() 方法可用于这些类。要在类中使用特征,请使用 use 关键字,后跟特征名称。下面是包含 Loggable 特征的类的示例:

class MyClass {
    use Loggable;
    
    public function doSomething() {
        $this->log("Doing something...");
    }
}

在此示例中, MyClass 包括使用 use 关键字的 Loggable 特征。结果,特征中定义的 log() 方法在 MyClass .然后, MyClass 中的 doSomething() 方法可以调用 log() 方法,就好像它是直接在 MyClass 中定义的一样。特征允许您使用可重用的功能组合类,从而提供了一种跨不同类混合和匹配行为的方法,而不受单一继承的限制。您可以通过在 use 语句中用逗号分隔多个特征来在一个类中包含多个特征。请务必注意,特征不能直接实例化,也没有自己的状态。它们旨在用作在类之间共享代码的一种方式。特征可以成为代码重用和组织的强大工具,但应明智地使用它们以保持代码清晰度并避免过于复杂。

匿名类

匿名类提供了一种动态创建类的方法,而无需显式定义命名类。匿名类是使用 new class 语法后跟类定义的。下面是创建匿名类的示例:

$object = new class {
    public function doSomething() {
        echo "Doing something...\n";
    }
};

$object->doSomething(); // Output: Doing something...

在上面的示例中,使用 new class 语法创建了一个匿名类。类定义括在大括号 {} 中。在类定义中,可以定义方法、属性并执行其他与类相关的操作。匿名类在需要为特定目的创建小型自包含类而无需命名类的情况下非常有用。它们通常用于实现接口、扩展抽象类或创建一次性使用对象。下面是使用匿名类实现接口的示例:

interface Logger {
    public function log($message);
}

$logger = new class implements Logger {
    public function log($message) {
        echo "Logging: " . $message . "\n";
    }
};

$logger->log("Hello, world!"); // Output: Logging: Hello, world!

在此示例中,将创建一个实现 Logger 接口的匿名类。类定义包括在接口中定义的 log() 方法。匿名类还可以扩展其他类或用作闭包,从而在创建动态对象时具有更大的灵活性。请务必注意,匿名类的实例化和使用方式与任何其他对象相同。但是,由于它们没有名称,因此无法在代码中的其他位置引用它们。匿名类的每个实例都是唯一的,并且与其他实例没有共享状态。匿名类是 PHP 中的一项强大功能,它支持动态类创建和代码组织。在需要动态创建小型专用类或对象的情况下,它们特别有用。

空安全运算符

空安全运算符(PHP Nullsafe) 是 PHP 8.0 中引入的一项新功能。它提供了一种访问对象上的属性和方法的便捷方法,而无需显式检查 null 值。在 PHP 8.0 之前,如果要访问对象上的属性或调用方法,通常必须在执行此操作之前检查对象是否为 null,以避免“null 指针”错误。例如:

if ($object !== null) {
    $object->doSomething();
}

使用 Nullsafe 运算符,可以更简洁的方式执行相同的操作。null safe 运算符由问号后跟箭头 (->) 运算符表示,如下所示:

$object?->doSomething();

如果 $object 为 null,则表达式将正常返回 null,而不是引发错误。此运算符实质上是使表达式短路,如果任何中间属性或方法为 null,则停止计算表达式。还可以使用 null-safe 运算符将多个属性和方法链接在一起:

$value = $object?->getProperty()?->doSomething();

在此示例中,如果 object或getProperty()方法返回null,则将为object 或 getProperty() 方法返回 null,则将为 objectgetProperty()方法返回null,则将为value 变量分配 null,并且不会调用后续的 doSomething() 方法。Nullsafe 运算符是 PHP 的一个方便的补充,因为它简化了空值处理并减少了对显式空检查的需求。但是,重要的是要明智地使用它,并确保它不会导致代码更难理解或调试。

可变参数

在 PHP 中,可变参数(也称为可变长度参数列表)允许函数接受任意数量的参数。此功能从 PHP 5.6 开始可用。若要定义可变参数,请在函数声明中的参数名称前使用三个点 ( ... )。例如:

function sum(...$numbers) {
    $total = 0;
    foreach ($numbers as $number) {
        $total += $number;
    }
    return $total;
}

在此示例中, sum() 函数接受任意数量的参数。可变参数 numbers充当包含所有传递参数的数组。然后,您可以迭代numbers 充当包含所有传递参数的数组。然后,您可以迭代 numbers充当包含所有传递参数的数组。然后,您可以迭代numbers 并执行所需的操作下面介绍如何将 sum() 函数与不同数量的参数一起使用:

echo sum(1, 2, 3);           // Output: 6
echo sum(4, 5, 6, 7, 8);     // Output: 30
echo sum(10);                // Output: 10
echo sum();                  // Output: 0

您还可以在函数声明中将可变参数与常规参数组合在一起。但是,可变参数必须是函数签名中的最后一个参数。

function concatenate($separator, ...$strings) {
    return implode($separator, $strings);
}

在此示例中, concatenate() 函数将分隔符作为第一个参数,然后是任意数量的字符串。可变参数 $strings 捕获所有其他参数。

echo concatenate("-", "Hello", "world");               // Output: Hello-world
echo concatenate(",", "apple", "banana", "orange");   // Output: apple,banana,orange

当您想要处理函数中不同数量的参数时,可变参数提供了灵活性。当您事先不知道将向函数传递多少参数时,它们特别有用。

参数解包

参数解包,也称为 splat 运算符或可变参数函数,是 PHP 中的一项功能,允许您将数组或可迭代作为单个参数传递给函数或方法。它是在 PHP 5.6 中引入的。若要使用参数解包,请在数组或可迭代变量前面加上三个点 (...)。当函数或方法被调用时,PHP 将自动解压缩数组或可迭代对象的元素,并将它们作为单独的参数传递。下面是一个示例来说明参数解包的工作原理:

function addNumbers($a, $b, $c) {
    return $a + $b + $c;
}

$numbers = [2, 4, 6];

$result = addNumbers(...$numbers);
echo $result;  // Output: 12

在上面的示例中, addNumbers 函数需要三个单独的参数。但是,我们不是单独传递参数,而是使用参数解包传递 $numbers 数组。PHP 将解压缩数组的元素( 2 , 4 , 6 ),并将它们作为单独的参数传递给函数。结果为 2 + 4 + 6 = 12 。您还可以将参数解包与可变参数函数一起使用,可变参数函数是接受可变数量参数的函数。在这种情况下,您可以将解压缩与其他参数结合使用。下面是一个示例:

function concatenateStrings($separator, ...$strings) {
    return implode($separator, $strings);
}

$result = concatenateStrings(', ', 'apple', 'banana', 'orange');
echo $result;  // Output: apple, banana, orange

在此示例中, concatenateStrings 函数接受分隔符作为第一个参数,接受任意数量的字符串作为后续参数。 ...$strings 语法允许您传递多个参数,这些参数将被打包到一个数组中。在这种情况下,该函数使用 implode 将字符串与指定的分隔符连接起来。当您在数组或可迭代对象中有数据并希望将其作为单独的参数传递给函数或方法时,参数解包是一项有用的功能。

命名参数

命名参数是 PHP 8.0 中引入的一项功能,参考了python,它允许您通过指定参数名称及其相应的值来传递函数或方法参数。此功能在调用具有大量参数的函数或想要跳过可选参数时提供了更大的灵活性和清晰度。下面是在 PHP 中使用命名参数的示例:

function greet($name, $age, $city) {
    echo "Hello, $name! You are $age years old and live in $city.";
}

// Calling the function with named arguments
greet(name: "John", age: 30, city: "New York");

在上面的例子中,我们使用命名参数调用 greet() 函数。我们不是依赖于参数的位置顺序,而是显式提及参数名称,后跟相应的值。这使得代码更具可读性和不言自明。命名参数还允许您跳过可选参数或按任意顺序指定它们。下面是一个示例:

function generateGreeting($name, $age = 25, $city = "Unknown") {
    echo "Hello, $name! You are $age years old and live in $city.";
}

// Calling the function with skipped and unordered named arguments
generateGreeting(city: "London", name: "Alice");

在这种情况下,我们调用 generateGreeting() 函数并仅提供 name 和 city 参数,跳过 age 参数。将自动使用 age 的默认值,并且可以按任意顺序指定参数。PHP 中的命名参数有助于提高代码的可读性和可维护性,并使使用具有许多参数或可选参数的函数变得更加容易。

命名变量

命名可变参数,也称为带有命名参数的可变参数函数,是 PHP 8 中引入的一项功能。命名可变参数允许您将可变数量的参数传递给函数,其中每个参数都与特定的参数名称相关联。此功能通过提供一种基于参数名称指定参数的便捷方法,增强了可变参数函数的灵活性和可读性。下面是在 PHP 中使用命名可变参数的示例:

function processItems(...$items)
{
    foreach ($items as $item) {
        // Process each item
        echo "Processing item: $item" . PHP_EOL;
    }
}

function processItemsWithNames(...$items)
{
    foreach ($items as $name => $item) {
        // Process each item with its associated name
        echo "Processing item '$name': $item" . PHP_EOL;
    }
}

// Example usage
processItems('Apple', 'Banana', 'Orange');
/*
Output:
Processing item: Apple
Processing item: Banana
Processing item: Orange
*/

processItemsWithNames('fruit' => 'Apple', 'snack' => 'Banana', 'citrus' => 'Orange');
/*
Output:
Processing item 'fruit': Apple
Processing item 'snack': Banana
Processing item 'citrus': Orange
*/

在第一个示例中, processItems() 函数使用 ...items语法接受可变数量的参数。它遍历items 语法接受可变数量的参数。它遍历 items语法接受可变数量的参数。它遍历items 数组并处理每个项目。在第二个示例中, processItemsWithNames() 函数还采用可变数量的参数,但每个参数都与特定的参数名称相关联。该函数使用 foreach 循环遍历 $items 数组,其中键表示参数名称,值表示相应的参数。命名可变参数提供了一种更具表现力的方式来传递和处理变量参数,尤其是当参数在函数中具有不同的含义或角色时。它通过将每个参数与参数名称显式关联来提高代码的可读性,使代码更具自我文档化且更易于理解。

箭头函数

箭头函数是 PHP 7.4 中引入的一项功能,它为定义匿名函数提供了更简洁的语法。箭头函数使代码更具可读性,并减少传统匿名函数语法的冗长程度。下面是一个示例来说明 PHP 中箭头函数的用法:

// Traditional anonymous function
$addition = function ($a, $b) {
    return $a + $b;
};

// Short closure (arrow function)
$addition = fn($a, $b) => $a + $b;

// Example usage
echo $addition(2, 3); // Output: 5

在上面的示例中,传统的匿名函数 addition采用两个参数addition 采用两个参数 addition采用两个参数a 和 b,并返回它们的总和。等效的短闭合版本是fn(b ,并返回它们的总和。等效的短闭合版本是 fn(b,并返回它们的总和。等效的短闭合版本是fn(a, b)=>b) => b)=>a + $b 。箭头 ( => ) 将参数与执行和返回的表达式或语句分开。箭头函数具有以下特点:

  • 简洁语法:与传统匿名函数中使用的 function 关键字相比,短闭包使用紧凑的语法 (0)。这会产生更清晰、更易读的代码。
  • 隐式返回:如果短闭包由单个表达式组成,PHP 会自动返回该表达式的结果。在该示例中,直接返回表达式 a+a + a+b ,而无需 return 关键字。
  • 继承的作用域:短闭包从周围的作用域继承变量,类似于传统的匿名函数。这意味着它们可以访问在闭包外部定义的变量,而无需将它们显式作为参数传递。
  • 仅限于表达式:短闭包仅限于单个表达式。它们不能包含多个语句或复杂的逻辑。如果需要更复杂的功能,则应使用传统的匿名函数。

箭头函数在需要将小而简单的表达式封装为回调或用于函数式编程结构(如数组函数( array_map 、 array_filter 等)或高阶函数)的情况下特别有用。

匹配表达式

match 表达式,也称为 match 语句或 match 表达式,是 PHP 8.0 中引入的一项功能。它提供了一种简洁而富有表现力的方式来针对值执行模式匹配,并根据匹配的模式执行不同的代码块。match 表达式类似于 switch 语句,但提供了更大的灵活性和可读性。下面是一个示例来演示 PHP 中匹配表达式的用法:

$value = 2;

$result = match ($value) {
    1 => 'One',
    2 => 'Two',
    3, 4 => 'Three or Four',
    default => 'Other'
};

echo $result; // Output: Two

在上面的示例中,match 表达式用于将变量 $value 的值与不同的模式进行匹配。右箭头 ( => ) 将模式与相应的代码块分开。如果模式匹配,则执行相应的代码块。如果没有模式匹配,则执行与 default 关键字关联的代码块。匹配表达式具有以下特征:

  • 基于值的匹配:匹配表达式将匹配的值与模式进行比较。它允许简单的值匹配,以及范围、列表和模式组合。
  • 单一匹配:匹配表达式在找到第一个匹配模式后立即停止执行。与 switch 语句不同,它不会落入后续模式。
  • 穷举性检查:匹配表达式要求涵盖所有可能的情况。如果值与提供的任何模式都不匹配,并且没有 default 大小写,则将抛出 UnhandledMatchError 。
  • 表达式结果:match 表达式返回匹配代码块的结果,允许您将其分配给变量或直接在代码中使用它。

在处理复杂的条件逻辑或需要根据变量的值执行不同的操作时,match 表达式特别有用。它为多个 if-else 语句或 switch 语句提供了一种更具可读性和简洁性的替代方案。需要注意的是,匹配表达式是在 PHP 8.0 中引入的。如果您使用的是早期版本的 PHP,则匹配表达式可能不可用。

Stringable接口

PHP 中的 0 接口是 PHP 8.0 中引入的一项新功能。它是一个内置接口,允许对象在字符串上下文中使用时自动转换为字符串,例如当它们与其他字符串连接或将它们传递给需要字符串参数的函数时。Stringable 接口定义如下:

interface Stringable {
    public function __toString(): string;
}

若要使对象实现 Stringable 接口,需要在返回对象的字符串表示形式的类中定义一个 __toString() 方法。此方法不应没有参数,并且必须返回字符串。下面是实现 Stringable 接口的类的示例:

class MyClass implements Stringable {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function __toString(): string {
        return "Hello, " . $this->name;
    }
}

$obj = new MyClass("John");
echo $obj; // Output: Hello, John

在上面的示例中, MyClass 通过定义 __toString() 方法实现 Stringable 接口。当 $obj 实例在字符串上下文中使用时(例如,当它被回显时),PHP 会自动调用 __toString() 方法来获取对象的字符串表示形式。使用 Stringable 接口可以简化代码,允许在必要时将对象视为字符串,而无需显式调用方法来转换它们。