PHPでの3つのドット(…)の意味


125

PHPの3つのドット(...)の意味は何ですか?

サーバーにMagento 2をインストールしているときにエラーが発生しました。コードを調査すると、エラーを引き起こしている3つのドット(...)があることがわかりました。以下のコードについて言及しました

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

PHP 5.6で導入された配列のパッキング/アンパッキング
Mark Ba​​ker

あなたは、インストールする前に要件を確認しました:devdocs.magento.com/guides/v2.0/install-gde/...
マチュー・デ・Lorimier

4
これはランダムなコメントですが、これはJSのスプレッドオペレーターです。:)
クリスハッピー

この場合の@ChrisHappyは、実際には残りの演算子です。
ケニーHorna

参照: PHP
splat

回答:


191

...$str呼び出されたPHPでのスプラット演算子

この機能を使用すると、必要に応じて渡される「通常の」引数と組み合わせて、関数への可変数の引数をキャプチャできます。例で見るのが最も簡単です:

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つ以上の引数を渡すと、2番目以降の引数が$ strings配列に追加され、使用できるようになります。

お役に立てれば!


1
おかげで:)、なぜSPLAT演算子を使用する必要がありますか?これの代わりに、配列内のすべての文字列を2番目の引数として渡すことができますか?
bikash.bilz

3
@ bikash.bilz回答者に代わって話をします。これは単なる構文上の糖分だと思います。splat演算子を使用する[と、引数をとで囲む必要がなくなります]。あまりメリットはありませんが、見た目は良いと思います。
コドスジョンソン2018

20
可変個引数の型ヒントも入力できます。したがって、PHP 7.2では、を定義できますfunction myFunc($foo, string ...$bar)。次に$bar、実行時に保証された文字列の配列のみを関数に提供します。単一の配列パラメーターを使用してそれを行うことはできません。
Jason

4
これは、他の方法では固定数の文字列を必要とするコンテキストで配列を許可するため、単なる構文シュガー以上のものです。固定数の文字列を使用するには、文字列の数が変わる可能性があるたびに、ソースコードをリファクタリングする必要があります。
dreftymac

2
簡単な例は、データベースのクエリに使用される関数シグネチャです。function get_data($fname,$lname,$age)これら3つ以外のフィールドfunction get_data(...$fields)を変更する必要がない場合は、変更する必要があります。必要なフィールドをで指定するだけです$fields。@heykatieben
dreftymac

21

すべての回答は、それらに加えて同じブログ投稿を参照しています可変長の引数リストに関する公式ドキュメント次のとおりです。

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

PHP 5.6以降では、引数リストに...トークンを含めて、関数が可変数の引数を受け入れることを示すことができます。引数は配列として与えられた変数に渡されます

"splat"オペレーターは正式名称ではないようですが、それでもかわいいです。


13

省略記号(...)のPHPトークンには2つの用途があります。それらは、配列のパッキングと配列のアンパックと考えることができます。どちらの目的も関数の引数に適用されます。


パック

関数を定義するときに、動的に提供される変数の数が必要な場合(つまり、コードで呼び出されたときにその関数に提供される引数の数がわからない場合)は、省略記号(...)トークンを使用します。をてその関数に提供される残りのすべての引数を、関数ブロック内でアクセス可能な配列にキャプチャします。省略記号(...)によって取り込まれる動的引数の数は、ゼロ以上にすることができます。

たとえば、次のとおりです。

// 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
これが最良の答えです。非常に明確な説明と例。ありがとうございました!!!
Jee

UnpackはDoctrineのOrX関数にとても便利です
G.

5

この機能を使用するには、を使用して配列を変数にアンパックする必要があることをPHPに警告するだけ... operatorです。詳細はこちらをご覧ください。簡単な例は次のようになります。

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

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

4

つまり、連想配列をリストに分解します。したがって、メソッドを呼び出すためにN個のパラメーターを入力する必要はなく、1つだけです。ifメソッドは分解されたパラメーターを許可し、パラメーターが同じタイプである場合。

私にとって、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を使用するよりも優れています
Erdal G.

3

これは、いわゆる「スプラット」演算子です。基本的に、それは「任意の数の引数」に変換されます。PHP 5.6で導入

詳細はこちらをご覧ください。


3

誰も言及していないようですので、ここに留まります[これは、PHPRestパラメータを要求する開発者を支援するGoogle(および他のSE)にも役立ちます]:

ここに示されているように、JSのRest Parametersと呼ばれます。この意味のある命名は、スプラットよりも優先されます。

PHPでは、... argsによって提供される機能Variadic関数と呼ばれ、PHP5.6で導入されました。同じ機能がを使用して実装されていましたfunc_get_args()

それを適切に使用するには、ボイラープレートコードの削減に役立つ場所であれば、残りのパラメーター構文を使用する必要があります


1
さらに、PHPでRestパラメータを見つける際にGoogleを支援するための1つ
kapreski

1

Magentoフレームワークでのこのオペレーターの使用法を共有したいと思います。このオペレーターは、動的構成可能パラメーター(XML構成ファイルと考えられる)でオブジェクトをインスタンス化します。

createObject次のコードスニペットから関数を見ることができるように、オブジェクト作成のために準備された引数の配列を受け取ります。次に、...(3つのドット)演算子を使用して、配列の値を実引数としてクラスのコンストラクターに渡します。

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

    ...

}


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.