How to yield value with the key?

2.6k views Asked by At

How to set the key for yielded value? Can the generator have the key as well as array does?

I can easily name keys when returning arrays. It's very useful for PhpUnit dataProviders:

$array = [
    'key' => ['value',1,2,3],
    'here' => ['a',4,5,6],
    'there' => ['b',7,8,9],
];

foreach( $array as $key => $value ){
    echo $key."\t=>\t".var_export($value, true)."\n\n\n";
}

but can I do the same using generators?

e.g., how to change the following code?:

function hi()
{
    yield ['value',1,2,3];
    yield ['a',4,5,6];
    yield ['b',7,8,9];
}
$array = hi();
foreach( $array as $key => $value ){
    echo $key."\t=>\t".var_export($value, true)."\n\n\n";
}

Currently, the output is:

0   =>  array (
  0 => 'value',
  1 => 1,
  2 => 2,
  3 => 3,
)


1   =>  array (
  0 => 'a',
  1 => 4,
  2 => 5,
  3 => 6,
)


2   =>  array (
  0 => 'b',
  1 => 7,
  2 => 8,
  3 => 9,
)

How can I set the mindful keys for yielded values?

2

There are 2 answers

0
Eugene Kaurov On BEST ANSWER

It is easy, yield has documented ability to use keys: https://www.php.net/manual/en/language.generators.syntax.php

function hi()
{
    yield 'key' => ['value',1,2,3];
    yield 'here' => ['a',4,5,6];
    yield 'there' => ['b',7,8,9];
}
$array = hi();
foreach( $array as $key => $value ){
    echo $key."\t=>\t".var_export($value, true)."\n\n\n";
}

The output will have keys, as well as an array does:

key =>  [
  0 => 'value',
  1 => 1,
  2 => 2,
  3 => 3,
]


here    =>  [
  0 => 'a',
  1 => 4,
  2 => 5,
  3 => 6,
]


there   =>  [
  0 => 'b',
  1 => 7,
  2 => 8,
  3 => 9,
]
0
Eugene Kaurov On

Here is a sample how to use yeald keys as title explaining phpUnit test cases in data provider

<?php

use PHPUnit\Framework\TestCase;

class SomeDataProviderTest extends TestCase
{
    private SomeClass $someClass;

    protected function setUp(): void
    {
        parent::setUp();
        $this->someClass = new SomeClass();
    }

    /**
     * @dataProvider SomeDataProvider
     */
    public function testSomeMethod(string $expected, int $param1, int $param2, int $param3): void
    {
        $result = $this->someClass->someMethod($param1, $param2, $param3);
        $this->assertEquals($expected, $result);
    }

    public function SomeDataProvider(): \Generator
    {
        yield 'test case 1 explanation'     => ['value', 1, 2, 3];
        yield 'test case 2 title'           => ['a', 4, 5, 6];
        yield 'test case 3 for extra cases' => ['b', 7, 8, 9];
    }
}