0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

あまり知られていないLaravelのコレクションメソッド #2: concat

Posted at

目次

  1. あまり知られていないLaravelのコレクションメソッド #1: macro
  2. あまり知られていないLaravelのコレクションメソッド #2: concat (本記事)

背景

Laravelのコレクション、使いこなしていますか?

以下の記事を先程読んで面白いと思いました。

「あなたは使ったことがないLaravelのコレクションメソッド10選」

ただし、英語で書かれていますし、各メソッドの説明が不十分に感じました。
ということで、以上の記事を翻訳する上で、それぞれのメソッドの活用方法を説明していきたいです!
今回はCollectionのconcatメソッドを解説します!

concat: コレクションにarrayや他コレクションの中身を追加する

概要

インスタンスメソッドになり、以下のように呼び出すことができます。

$collection = collect([/* ... */]);
$collection->concat(/* ... */);

既存コレクションに、arrayの中身を追加できます。

$collection = collect([1, 2, 3]);
$collection->concat([4]);
// [1, 2, 3, 4]

他コレクションの中身も追加できます!

$collection = collect([1, 2, 3]);
$collection2 = collect([4]);
$collection->concat($collection2);
// [1, 2, 3, 4]

ソースコードを読みましょう

concatメソッドのソースコードは以下になります。(Laravel 11.xのソースコードになります)

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @implements \ArrayAccess<TKey, TValue>
 * @implements \Illuminate\Support\Enumerable<TKey, TValue>
 */
class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable
{
    // ...

    /**
     * Push all of the given items onto the collection.
     *
     * @template TConcatKey of array-key
     * @template TConcatValue
     *
     * @param  iterable<TConcatKey, TConcatValue>  $source
     * @return static<TKey|TConcatKey, TValue|TConcatValue>
     */
    public function concat($source)
    {
        $result = new static($this);

        foreach ($source as $item) {
            $result->push($item);
        }

        return $result;
    }

    // ...
}

ソースコードを読むことで、2つのことがわかります。

追加されるarrayやコレクションのキーが捨てられる

今までキーのないarrayやコレクションでconcatメソッドを使ってきましたが、キーを指定するとどうなるでしょう?

$collection = collect([1, 2, 3]);
$collection->concat(['key' => 4]);
// [1, 2, 3, 4]

キーが全く考慮されず、値を追加しています。
ソースコードをもう一度読むと原因がわかります。

        // ...

        foreach ($source as $item) {
            $result->push($item);
        }

        // ...

foreachを使って追加されるarrayを処理しているため、キーが捨てられます。

既存コレクションにキーがあれば、追加キーがいい感じに追加される

追加元のコレクションにキーがある場合、キーはどう変わるでしょう?

実は普通のarrayに値を追加する場合と一緒です。

上記のように、キーを省略して新規要素を追加する場合、 追加される数値添字は、使用されている添字の最大値 +1 (ただし、少なくとも 0 以上) になります。 まだ数値添字が存在しない場合は、添字は 0 (ゼロ) となります。

つまりこういう感じです。

$collection = collect([1 => 1, 2 => 2, 3 => 3]);
$collection->concat(['key' => 123]);
// [1 => 1, 2 => 2, 3 => 3, 4 => 123]
$collection = collect(['key1' => 1, 'key2' => 2, 'key3' => 3]);
$collection->concat(['key' => 123]);
// ['key1' => 1, 'key2' => 2, 'key3' => 3, 0 => 123]

型の定義がちゃんと変わる...?

下記はPHPStanで検証しています

上級PHPになりますが、コレクションにジェネリックスが入っています。

$collection = collect([1, 2, 3]); // \Illuminate\Support\Collection<int,int>

concatメソッドを使うとジェネリックスがちゃんと変わります。

$collection = collect([1, 2, 3]); // \Illuminate\Support\Collection<int,int>
$collection->concat(['a']); // \Illuminate\Support\Collection<int,int|string>
// [1, 2, 3, 'a']

ただし、stringのキーを持っているコレクションに値を追加すると...

$collection = collect(['ab' => 1]); // \Illuminate\Support\Collection<string,int>
$collection->concat([2]); // \Illuminate\Support\Collection<string,int> !!!
// ['ab' => 1, 0 => 2] !!!

どうやら型と実際のarrayは一致しないようです。
PHPStanのバグ?Laravelのバグ?私の脳みそのバグ?はっきりわからないので調査中です。
もしわかる人がいれば是非コメントお願いします!!

参考

まとめ

いかがでしたか?
今度はpadメソッドなど、あまり知られていないLaravelのコレクションメソッドをさらに解説していきたいです。
ではまた!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?