Значение трех точек (…) в PHP


125

Что означает три точки (...) в PHP?

При установке Magento 2 на свой сервер возникла ошибка. Изучите код и обнаружите, что есть три точки (...), которые вызывают ошибку. Я упомянул код ниже

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

упаковка / распаковка массивов представлена ​​в PHP 5.6
Марк Бейкер


4
Просто случайный комментарий, это оператор распространения в JS. :)
Chris Happy

@ChrisHappy в данном случае - это оператор отдыха .
Kenny Horna

См. Также: PHP splat operator
dreftymac

Ответы:


191

В PHP...$str это называется оператором splat .

Эта функция позволяет вам захватывать переменное количество аргументов функции в сочетании с переданными "обычными" аргументами, если хотите. Это проще всего увидеть на примере:

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

В списке параметров в объявлении функции есть ...оператор, и это в основном означает «... а все остальное должно быть помещено в $ strings». Вы можете передать в эту функцию 2 или более аргумента, и второй и последующие аргументы будут добавлены в массив $ strings и готовы к использованию.

Надеюсь это поможет!


1
Спасибо :), почему я должен использовать оператор SPLAT, вместо этого я могу передать все эти строки в массиве в качестве второго аргумента ???
bikash.bilz 04

3
@ bikash.bilz Я отвечу за ответ: я думаю, это просто синтаксический сахар . Оператор splat избавляет вас от необходимости заключать аргументы в символы [и ]. Это не так уж и важно, но я думаю, что выглядит неплохо.
Kodos Johnson

20
Вы также можете указать переменные параметры. Итак, в PHP 7.2 вы можете определить function myFunc($foo, string ...$bar). Затем $barдает вашей функции массив строк и ничего больше, гарантированное во время выполнения. Вы не можете сделать это с одним параметром массива.
Джейсон

4
Это больше, чем просто синтаксический сахар, потому что он позволяет использовать массив в контекстах, которые в противном случае потребовали бы фиксированного количества строк. Использование фиксированного количества строк требует, чтобы вы повторно использовали исходный код каждый раз, когда количество строк может измениться.
dreftymac

2
Простым примером является сигнатура функции, используемая для запроса базы данных. function get_data($fname,$lname,$age)придется изменить, если вы хотите, чтобы поля, отличные от этих трех function get_data(...$fields), не менялись, вам нужно только указать поля, которые вы хотите ввести $fields. @heykatieben
dreftymac

21

Каждый ответ относится к одному и тому же сообщению в блоге, кроме них, вот официальная документация о списках аргументов переменной длины :

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

В PHP 5.6 и более поздних версиях списки аргументов могут включать токен ... для обозначения того, что функция принимает переменное количество аргументов. Аргументы будут переданы в данную переменную в виде массива

Вроде оператор "сплат" - не официальное название, но все же мило!


13

Существует ДВА использования токена PHP с многоточием (...) - представьте их как упаковку массива и распаковку массива. Обе цели применимы к аргументам функции.


пак

При определении функции, если вам нужно динамическое количество переменных, предоставляемых функции (т. Е. Вы не знаете, сколько аргументов будет предоставлено этой функции при вызове в коде), используйте токен с многоточием (...) для захватить все оставшиеся аргументы, предоставленные этой функции, в массив, доступный внутри функционального блока. Число динамических аргументов, захваченных многоточием (...), может быть равно нулю или больше.

Например :

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

Когда упаковка используется при создании экземпляра функции, многоточие (...) захватывает все оставшиеся аргументы , т. Е. Вы все еще можете иметь любое количество начальных фиксированных (позиционных) аргументов:

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

распаковывать

В качестве альтернативы, при вызове функции, если аргументы, которые вы предоставляете этой функции, предварительно объединены в массив, используйте токен с многоточием (...) для преобразования этого массива в отдельные аргументы, предоставляемые функции - каждый элемент массива назначается соответствующему переменная аргумента функции, указанная в определении функции.

Например:

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

Распаковка особенно полезна при использовании функций массива для управления массивами или переменными.

Например, распаковка результата 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
Это лучший ответ. Очень понятное объяснение и примеры. Спасибо!!!
Джи

Распаковка очень полезна для функции OrX Doctrine
Эрдал Г.

5

Чтобы использовать эту функцию, просто предупредите PHP, что ему необходимо распаковать массив в переменные, используя расширение ... operator. Подробнее см. Здесь , простой пример может выглядеть так:

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

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

4

Это означает, что ассоциативный массив разбивается на список. Таким образом, вам не нужно вводить N параметров для вызова метода, только один. Если метод допускает разложенный параметр, и если параметры одного типа.

Для меня самое важное в операторе splat - это то, что он может помочь напечатать параметры массива:

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

он экономит некоторые усилия по управлению типами, особенно при работе с огромными коллекциями или очень объектно-ориентированными.

Важно отметить, что ...$arrayмассив действительно разбивается независимо от типа его элементов , поэтому вы также можете пойти по уродливому пути:

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!

Но, пожалуйста, не надо.


Это не так уж и плохо. Как и в случае с функциями Doctrine OrX, которым нужен список, но вам нужно передать массив (потому что вы не знаете, сколько элементов вы передадите). Я считаю этот способ лучше, чем использование call_user_func_array
Эрдал Г.

3

Это так называемый оператор "splat". По сути, это означает «любое количество аргументов»; введено в PHP 5.6

Подробнее см. Здесь .


3

Кажется, никто об этом не упомянул, так что здесь, чтобы остаться [это также поможет Google (и другим SE) направлять разработчиков, которые запрашивают параметры отдыха в PHP ]:

Как указано здесь, это называется Rest Parameters на JS, и я предпочитаю это значимое именование этой штуке со знаками!

В PHP функциональные возможности, предоставляемые ... args , называются функциями Variadic, которые представлены в PHP5.6. Та же функциональность была реализована с использованием func_get_args().

Чтобы использовать его правильно, вы должны использовать синтаксис остальных параметров везде, где это помогает уменьшить шаблонный код .


1
плюс один за помощь Google в поиске параметра Rest в PHP
kapreski

1

Я хотел бы поделиться использованием этого оператора в среде Magento, где он создает экземпляры объектов с динамически настраиваемыми параметрами (мысленные файлы конфигурации XML).

Как мы видим в createObjectследующем фрагменте кода, функция принимает массив аргументов, подготовленных для создания объекта. Затем он использует ...оператор (три точки) для передачи значений массива в качестве реальных аргументов конструктору класса.

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

    ...

}


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.