Significato dei tre punti (…) in PHP


125

Qual è il significato di Tre punti (...) in PHP?

Durante l'installazione di Magento 2 nel mio Sever ho ricevuto un errore. Esamina il codice e hai scoperto che c'è un punto Tre (...), che sta producendo l'errore. Ho menzionato il codice di seguito

return new $type(...array_values($args));

inserimento / decompressione di array introdotto in PHP 5.6
Mark Baker

Hai controllato i requisiti prima dell'installazione: devdocs.magento.com/guides/v2.0/install-gde/…
Mathieu de Lorimier

4
Solo un commento casuale, questo è l'operatore spread in JS. :)
Chris Happy,

@ChrisHappy in questo caso è in realtà l' operatore resto .
Kenny Horna

Risposte:


191

La ...$strsi chiama un operatore di splat in PHP .

Questa caratteristica ti permette di catturare un numero variabile di argomenti per una funzione, combinati con argomenti "normali" passati se vuoi. È più facile vedere con un esempio:

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

L'elenco dei parametri nella dichiarazione della funzione contiene l' ...operatore, e in pratica significa "... e tutto il resto dovrebbe andare in $ stringhe". Puoi passare 2 o più argomenti in questa funzione e il secondo e quelli successivi verranno aggiunti all'array $ strings, pronti per essere utilizzati.

Spero che questo ti aiuti!


1
Grazie :), perché dovrei usare l'operatore SPLAT, invece di questo posso passare tutte quelle stringhe in un array come secondo argomento ???
bikash.bilz

3
@ bikash.bilz Parlerò per il rispondente: penso che sia solo zucchero sintattico . L'operatore splat ti evita di racchiudere gli argomenti con [e ]. Non è un gran vantaggio, ma penso che sia carino.
Kodos Johnson,

20
Puoi anche digitare i parametri variadici. Quindi su PHP 7.2, puoi definire function myFunc($foo, string ...$bar). Quindi $barassegna alla tua funzione un array di stringhe e nient'altro, garantito in fase di esecuzione. Non puoi farlo con un singolo parametro di array.
Jason

4
Questo è più di un semplice zucchero sintattico perché consente un array in contesti che altrimenti richiederebbero un numero fisso di stringhe. L'utilizzo di un numero fisso di stringhe richiede di riformattare il codice sorgente ogni volta che il numero di stringhe potrebbe cambiare.
dreftymac

2
Un semplice esempio è una firma di funzione utilizzata per interrogare un database. function get_data($fname,$lname,$age)dovrà cambiare se vuoi che i campi diversi da quei tre function get_data(...$fields)non debbano cambiare, devi solo specificare i campi che desideri $fields. @heykatieben
dreftymac

21

Ogni risposta fa riferimento allo stesso post del blog, oltre a loro, ecco la documentazione ufficiale sugli elenchi di argomenti a lunghezza variabile :

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

In PHP 5.6 e versioni successive, gli elenchi di argomenti possono includere il token ... per indicare che la funzione accetta un numero variabile di argomenti. Gli argomenti verranno passati nella variabile data come un array

Sembra che l'operatore "splat" non sia un nome ufficiale, tuttavia è carino!


13

Ci sono due usi per la puntini di sospensione (...) PHP pegno -Pensate di loro come imballaggio un array e disimballaggio un array. Entrambi gli scopi si applicano agli argomenti della funzione.


pacco

Quando si definisce una funzione, se è necessario un numero dinamico di variabili fornite alla funzione (cioè, non si sa quanti argomenti verranno forniti a quella funzione quando viene chiamata nel codice) utilizzare i puntini di sospensione (...) per cattura tutti gli argomenti rimanenti forniti a quella funzione in un array accessibile all'interno del blocco funzione. Il numero di argomenti dinamici catturati dai puntini di sospensione (...) può essere zero o più.

Ad esempio :

// 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

Quando si utilizza la compressione nella creazione di istanze di funzioni, i puntini di sospensione (...) acquisiscono tutti gli argomenti rimanenti , ovvero è ancora possibile avere un numero qualsiasi di argomenti iniziali fissi (posizionali):

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

disfare

In alternativa, quando si chiama una funzione, se gli argomenti forniti a quella funzione sono precedentemente combinati in un array, utilizzare il token con i puntini di sospensione (...) per convertire quell'array in singoli argomenti forniti alla funzione: ogni elemento dell'array è assegnato al rispettivo variabile dell'argomento della funzione denominata nella definizione della funzione.

Per esempio:

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

La decompressione è particolarmente utile quando si utilizzano funzioni di array per manipolare array o variabili.

Ad esempio, decomprimere il risultato di 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

4
Questa è la migliore risposta. Spiegazione ed esempi molto chiari. Grazie!!!
Jee

Unpack è super utile per la funzione OrX di Doctrine
Erdal G.

5

Per usare questa funzione, avvisa semplicemente PHP che deve decomprimere l'array in variabili usando il ... operator. Vedi qui per maggiori dettagli, un semplice esempio potrebbe assomigliare a questo:

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

mail("someone@example.com", ...$email);

4

Il significato è che scompone un array associativo in un elenco. Quindi non è necessario digitare N parametri per chiamare un metodo, solo uno. Se il metodo consente un parametro scomposto e se i parametri sono dello stesso tipo.

Per me, la cosa più importante dell'operatore splat è che può aiutare a digitare i parametri dell'array di suggerimento:

$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;
        }
    }
} 

risparmia un po 'di sforzo sul controllo del tipo, specialmente quando si lavora con raccolte enormi o molto orientate agli oggetti.

È importante notare che ...$arraydecomponi un array nonostante il tipo dei suoi elementi , quindi puoi anche andare nel modo brutto:

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!

Ma per favore non farlo.


Non è così brutto. Come con le funzioni OrX di Doctrine che necessitano di un elenco, ma devi passare un array (perché non sai quanti elementi passerai). Trovo questo modo migliore rispetto all'utilizzo di call_user_func_array
Erdal G.

3

Questo è il cosiddetto operatore "splat". Fondamentalmente quella cosa si traduce in "qualsiasi numero di argomenti"; introdotto con PHP 5.6

Vedi qui per ulteriori dettagli.


3

Sembra che nessuno l'abbia menzionato, quindi qui per restare [Aiuterà anche Google (e altri SE) a guidare gli sviluppatori che richiedono parametri di riposo in PHP ]:

Come indicato qui, si chiama Rest Parameters su JS e preferisco questa denominazione significativa a quella cosa splat!

In PHP, la funzionalità fornita da ... args è chiamata funzioni Variadic che è stata introdotta in PHP5.6. La stessa funzionalità è stata utilizzata per essere implementata utilizzando func_get_args().

Per usarlo correttamente, dovresti usare la sintassi dei parametri di riposo, ovunque aiuti a ridurre il codice boilerplate .


1
più uno per aiutare Google a trovare il parametro Rest in PHP
kapreski

1

Vorrei condividere un utilizzo di questo operatore nel framework Magento, dove istanzia oggetti con parametri dinamici configurabili (pensati file di configurazione XML).

Come possiamo vedere la createObjectfunzione dal seguente frammento di codice, accetta un array di argomenti preparati per la creazione dell'oggetto. Quindi utilizza l' ...operatore (tre punti) per passare i valori dell'array come argomenti reali al costruttore della classe.

<?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) {
            ...
        }
    }

    ...

}


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.