Significado de tres puntos (…) en PHP

125

¿Cuál es el significado de Tres puntos (...) en PHP?

Mientras instalo Magento 2 en mi servidor, recibí un error. Investigue el código y descubrió que hay un punto Tres (...), que está produciendo el error. Mencioné el código a continuación

return new $type(...array_values($args));
abu abu
fuente
empaquetado / desempaquetado de matrices introducido en PHP 5.6
Mark Baker
¿ Verificó
Mathieu de Lorimier
4
Solo un comentario aleatorio, este es el operador de propagación en JS. :)
Chris Happy
@ChrisHappy en este caso es en realidad el operador rest .
Kenny Horna
Ver también: operador PHP splat
dreftymac

Respuestas:

191

El ...$strse llama operador splat en PHP .

Esta característica le permite capturar un número variable de argumentos para una función, combinados con argumentos "normales" pasados ​​si lo desea. Es más fácil de ver con un ejemplo:

function concatenate($transform, ...$strings) {
    $string = '';
    foreach($strings as $piece) {
        $string .= $piece;
    }
    return($transform($string));
}

echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");
// This would print:
// I'D LIKE 6 APPLES

La lista de parámetros en la declaración de la función tiene el ...operador, y básicamente significa "... y todo lo demás debe ir en $ strings". Puede pasar 2 o más argumentos a esta función y el segundo y los siguientes se agregarán a la matriz $ strings, listos para usarse.

¡Espero que esto ayude!

Saumya Rastogi
fuente
1
Gracias :), ¿por qué debería usar el operador SPLAT, en lugar de esto puedo pasar todas esas cadenas en una matriz como segundo argumento?
bikash.bilz
3
@ bikash.bilz Hablaré en nombre del que responda: Creo que es simplemente azúcar sintáctico . El operador splat le evita rodear los argumentos con [y ]. No es un gran beneficio, pero creo que se ve bien.
Kodos Johnson
20
También puede escribir sugerencias sobre los parámetros variadic. Entonces, en PHP 7.2, puede definir function myFunc($foo, string ...$bar). Luego $barle da a su función una matriz de cadenas y nada más, garantizada en tiempo de ejecución. No puede hacer eso con un solo parámetro de matriz.
Jason
4
Esto es más que un simple azúcar sintáctico porque permite una matriz en contextos que de otro modo requerirían un número fijo de cadenas. El uso de una cantidad fija de cadenas requiere que vuelva a factorizar su código fuente cada vez que la cantidad de cadenas pueda cambiar.
dreftymac
2
Un ejemplo sencillo es la firma de una función que se utiliza para consultar una base de datos. function get_data($fname,$lname,$age)tendrá que cambiar si desea que los campos que no sean esos tres function get_data(...$fields)no tengan que cambiar, solo necesita especificar los campos que desea $fields. @heykatieben
dreftymac
21

Cada respuesta se refiere a la misma publicación de blog, además de ellos, aquí está la documentación oficial sobre listas de argumentos de longitud variable :

http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list

En PHP 5.6 y posterior, las listas de argumentos pueden incluir el símbolo ... para indicar que la función acepta un número variable de argumentos. Los argumentos se pasarán a la variable dada como una matriz

Parece que el operador "splat" no es un nombre oficial, ¡pero es lindo!

rap-2-h
fuente
13

Hay DOS usos para el token PHP de puntos suspensivos (...); piense en ellos como empaquetar una matriz y desempaquetar una matriz. Ambos propósitos se aplican a los argumentos de funciones.


Paquete

Al definir una función, si necesita un número dinámico de variables proporcionadas a la función (es decir, no sabe cuántos argumentos se proporcionarán a esa función cuando se llame en el código) use el token de puntos suspensivos (...) para capturar todos los argumentos restantes proporcionados a esa función en una matriz que sea accesible dentro del bloque de funciones. El número de argumentos dinámicos capturados por puntos suspensivos (...) puede ser cero o más.

Por ejemplo :

// function definition
function sum(...$numbers) { // use ellipsis token when defining function
    $acc = 0;
    foreach ($numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2, 3, 4); // provide any number of arguments

> 10

// and again...
echo sum(1, 2, 3, 4, 5);

> 15

// and again...
echo sum();

> 0

Cuando se usa el empaquetado en la creación de instancias de funciones, la elipsis (...) captura todos los argumentos restantes , es decir, aún puede tener cualquier número de argumentos iniciales fijos (posicionales):

function sum($first, $second, ...$remaining_numbers) {
    $acc = $first + $second;
    foreach ($remaining_numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2); // provide at least two arguments

> 3

// and again...
echo sum(1, 2, 3, 4); // first two are assigned to fixed arguments, the rest get "packed"

> 10

Deshacer

Alternativamente, al llamar a una función, si los argumentos que le proporcionas a esa función se han combinado previamente en una matriz, usa el token de puntos suspensivos (...) para convertir esa matriz en argumentos individuales proporcionados a la función; cada elemento de la matriz se asigna a la respectiva variable de argumento de función nombrada en la definición de función.

Por ejemplo:

function add($aa, $bb, $cc) {
    return $aa + $bb + $cc;
}

$arr = [1, 2, 3];
echo add(...$arr); // use ellipsis token when calling function

> 6

$first = 1;
$arr = [2, 3];
echo add($first, ...$arr); // used with positional arguments

> 6

$first = 1;
$arr = [2, 3, 4, 5]; // array can be "oversized"
echo add($first, ...$arr); // remaining elements are ignored

> 6

El desempaquetado es particularmente útil cuando se utilizan funciones de matriz para manipular matrices o variables.

Por ejemplo, desempaquetando el resultado de array_slice :

function echoTwo ($one, $two) {
    echo "$one\n$two";
}

$steaks = array('ribeye', 'kc strip', 't-bone', 'sirloin', 'chuck');

// array_slice returns an array, but ellipsis unpacks it into function arguments
echoTwo(...array_slice($steaks, -2)); // return last two elements in array

> sirloin
> chuck
nudillos sangrientos
fuente
4
Esta es la mejor respuesta. Explicación y ejemplos muy claros. ¡¡¡Gracias!!!
Jee
Desempaquetar es súper útil para la función OrX de Doctrine
Erdal G.
5

Para usar esta función, simplemente advierta a PHP que necesita descomprimir la matriz en variables usando ... operator. Consulte aquí para obtener más detalles, un ejemplo simple podría verse así:

$email[] = "Hi there";
$email[] = "Thanks for registering, hope you like it";

mail("[email protected]", ...$email);
Desarrollador principal
fuente
4

El significado es que descompone una matriz asociativa en una lista. Por lo tanto, no necesita escribir N parámetros para llamar a un método, solo uno. Si el método permite un parámetro descompuesto y si los parámetros son del mismo tipo.

Para mí, lo más importante sobre el operador splat es que puede ayudar a escribir parámetros de matriz de sugerencias:

$items = [
    new Item(), 
    new Item()
];

$collection = new ItemCollection();
$collection->add(...$items); // !

// what works as well:
// $collection->add(new Item());
// $collection->add(new Item(), new Item(), new Item()); // :(

class Item  {};

class ItemCollection {

    /**
     * @var Item[]
     */
    protected $items = [];

    public function add(Item ...$items)
    {
        foreach ($items as &$item) {
            $this->items[] = $item;
        }
    }
} 

ahorra algo de esfuerzo en el control de tipos, especialmente cuando se trabaja con colecciones enormes o muy orientadas a objetos.

Es importante tener en cuenta que ...$arraydescompone una matriz a pesar del tipo de sus elementos , por lo que también puede seguir el camino más feo:

function test(string $a, int $i) {
    echo sprintf('%s way as well', $a);

    if ($i === 1) {
        echo('!');
    }
}

$params = [
    (string) 'Ugly',
    (int) 1
];

test(...$params);

// Output:
// Ugly way as well!

Pero por favor no lo hagas.

yergo
fuente
No es tan feo. Al igual que con las funciones OrX de Doctrine, que necesita una lista, pero necesita pasar una matriz (porque no sabe cuántos elementos pasará). Encuentro esta manera mejor que usar call_user_func_array
Erdal G.
3

Este es el llamado operador "splat". Básicamente, eso se traduce en "cualquier número de argumentos"; introducido con PHP 5.6

Consulte aquí para obtener más detalles.

GhostCat
fuente
3

Parece que nadie lo ha mencionado, así que aquí para quedarse [También ayudará a Google (y otros SE) a guiar a los desarrolladores que soliciten parámetros de descanso en PHP ]:

Como se indica aquí, se llama Parámetros de descanso en JS y prefiero este nombre significativo sobre esa cosa de splat.

En PHP, la funcionalidad proporcionada por ... args se llama funciones Variadic que se introdujo en PHP5.6. Se utilizó la misma funcionalidad para implementar utilizando func_get_args().

Para usarlo correctamente, debe usar la sintaxis de los parámetros de descanso, en cualquier lugar donde ayude a reducir el código repetitivo .

behradkhodayar
fuente
1
más uno para ayudar a Google a encontrar el parámetro Rest en PHP
kapreski
1

Me gustaría compartir un uso de este operador en el marco de Magento, donde instancia objetos con parámetros configurables dinámicos (archivos de configuración XML pensados).

Como podemos ver la createObjectfunción del siguiente fragmento de código, toma una matriz de los argumentos preparados para la creación del objeto. Luego usa el ...operador (tres puntos) para pasar los valores de la matriz como argumentos reales al constructor de la clase.

<?php

namespace Magento\Framework\ObjectManager\Factory;

abstract class AbstractFactory implements \Magento\Framework\ObjectManager\FactoryInterface
{
    ...

    /**
     * Create object
     *
     * @param string $type
     * @param array $args
     *
     * @return object
     * @throws RuntimeException
     */
    protected function createObject($type, $args)
    {
        try {
            return new $type(...array_values($args));
        } catch (\TypeError $exception) {
            ...
        }
    }

    ...

}
granizo
fuente