ãããŠããã¡ãããé¢æ¥ã§ã®è³ªåãã©ããªã«å¥åŠã§äžæ£ç¢ºã§ãã£ãŠããããªãã¯ããã°ã©ãã³ã°ã®ããã«æ¯æãããèšèªãç¥ã£ãŠãçµå±æºåããå¿ èŠããããŸãã
äžé£ã®èšäºã®ç¬¬3éšã¯ãçŸä»£ã®PHPã§æãèšå€§ãªæŠå¿µã®1ã€ã§ããå埩ãå埩åãå埩å¯èœãšã³ãã£ãã£ã«åœãŠãããŠããŸãã PHPã®éçºè ã®å°äœã«å¯Ÿããã€ã³ã¿ãã¥ãŒã®ããã®èªå·±æºåã«é©ããããã®åé¡ã«é¢ããç¹å®ã®æäœéã®ç¥èã1ã€ã®ããã¹ãã§åæžããããšããŸããã
åã®2ã€ã®éšåïŒ
- PHPã€ã³ã¿ãã¥ãŒã®æºåïŒéçããŒã¯ãŒã
- PHPã€ã³ã¿ãã¥ãŒã®æºåïŒCallable Pseudotype
PHPã®é å
æåããå§ããŸãããã
PHPã«ã¯é åããããŸãã PHPã®é åã¯é£æ³çã§ããã€ãŸãããã¢ïŒããŒãå€ïŒãæ ŒçŽããŸããããŒã¯intãŸãã¯stringã§ããå¿ èŠããããå€ã¯ã©ã®ã¿ã€ãã§ãããŸããŸããã
äŸïŒ
$arr = ['foo' => 'bar', 'baz' => 42, 'arr' => [1, 2, 3]];
ããŒãšå€ã¯ãèšå·ã=>ãã§åºåãããŠããŸãã ããŒã¯ãã€ã³ããã¯ã¹ããšåŒã°ããããšããããŸãããPHPã§ã¯ãããã¯åçã®çšèªã§ãã
PHPã®é åã§ã¯ãããªãå®å šãªäžé£ã®æäœãå®çŸ©ãããŠããŸãã
// $arr['new'] = 'some value'; // $arr[] = 'another value'; // echo $arr['foo']; echo $arr[$bar]; // unset($arr['foo']); // "" [$foo, $bar, $baz] = $arr;
é åãæäœããããã®å€ãã®é¢æ°ããããŸã- æ°åãæ°çŸïŒ
ãã ããããããPHPã®é åã®æãéèŠãªããããã£ã¯ãé åã®ãã¹ãŠã®èŠçŽ ãé çªã«åŠçãããã¹ãŠã®ããŒãšå€ã®ãã¢ãé çªã«ååŸããæ©èœã§ãã
é åã®å埩
é åããã©ããŒã¹ããããã»ã¹ã¯ãå埩ãïŒãŸãã¯ãç¡å¹åãïŒãšåŒã°ãïŒãšããã§ãåã¹ããããåã ã®ããŒãšå€ã®ãã¢ãååŸããããšããå埩ãã§ãïŒããããã£ãŠé åèªäœã¯å埩å¯èœã§ãïŒãå埩ãïŒæ¬è³ªã
å埩ããã»ã¹ã®æãåçŽãªäŸã¯ããã¡ãããforeachã¹ããŒãã¡ã³ãã«ãã£ãŠå®è£ ããããžã§ã€ã³ãã«ãŒãã§ãã
foreach ($arr as $key=>$val) { echo $key . '=>' . $val; echo "\n"; }
ã«ãŒãããããŒã®ããŒãšå€ãåºåãåãã=>ãèšå·ã«æ³šæããŠãã ããã
ããããPHPã¯ã©ã®ããã«ç解ããŸãã-ã«ãŒãã®ç¹å®ã®ã¹ãããã§é åã®ã©ã®èŠçŽ ãåããïŒ æ¬¡ã«åãã®ã¯ã©ãã§ããïŒ ãããŠãã€åæ¢ããã®ãïŒ
ãã®è³ªåã«çããã«ã¯ãåé åã«ååšãããããããå éšãã€ã³ã¿ãŒãã®ååšã«æ³šæããå¿ èŠããããŸãã ãã®äžå¯èŠã®ãã€ã³ã¿ã¯ãçŸåšã®ãèŠçŽ ãæããããã«1ã¹ããã移åã§ããŸã-次ã®èŠçŽ ã«ç§»åããããæåã®èŠçŽ ã«å床ãªã»ããããŸãã
PHPã®å éšãã€ã³ã¿ãŒãçŽæ¥æäœããã«ã¯ãäŸã䜿çšããŠæãç°¡åã«åŠç¿ã§ããé¢æ°ããããŸãã
$arr = [1, 2, 3]; // , reset($arr); // key() , , null while ( null !== ($key = key($arr)) ) { // current() , echo $key . '=>' . current($arr); echo "\n"; // next() next($arr); }
äžããããã³ãŒãäŸãå®éã«ä»¥åã«äœ¿çšãããforeachã«ãŒããšåçã§ãããforeachãresetïŒïŒãkeyïŒïŒãcurrentïŒïŒãnextïŒïŒé¢æ°ã®æ§æã·ã¥ã¬ãŒã®ãããªãã®ã§ããããšã¯ç°¡åã«ããããŸãïŒãããŠendïŒïŒããã³prevïŒ ïŒ-éé ã§æ€çŽ¢ãæŽçããŸãïŒã
ãã®ã¹ããŒãã¡ã³ãã¯ãPHP 7ããåã¯çå®ã§ããããçŸåšã¯ããã§ã¯ãããŸãã-foreachã«ãŒãã¯ãresetïŒïŒãnextïŒïŒãããã³ãã®ä»ã®å埩é¢æ°ãšåãå éšãã€ã³ã¿ãŒã䜿çšããŠåæ¢ãããããäœçœ®ã®å€æŽãåæ¢ããŸããã
å°èš
ãããã£ãŠãPHPã®é åã®ç¹°ãè¿ããã©ã®ããã«æ©èœããããèŠçŽããã«ã¯ïŒ
- åé åã«ã¯ãå éšãã€ã³ã¿ãŒãé¢é£ä»ããããŠããŸãã
- é åã®å é ïŒãŸãã¯æ«å°ŸïŒã«ãªã»ããã§ããŸã
- 次ã®ïŒåã®ïŒèŠçŽ ã«ç§»åã§ããŸãã
- æåŸã«å°éãããã©ããã確èªã§ããŸã-ãã€ã³ã¿ãŒãé åããåºãŠããŸããïŒ
- ãããŠãçŸåšã®èŠçŽ ã®ããŒãšå€ãååŸã§ããŸãïŒãã€ã³ã¿ãæãïŒ
ãã®ãããªããã€ã¹ã䜿çšãããšãã«ãŒãå ã§é åïŒèŠçŽ ãåæïŒã®ç¹°ãè¿ããæŽçã§ããŸãã ãã ããforeachã«ãŒãã¯äŒŒãŠããŸãããresetïŒïŒãkeyïŒïŒãcurrentïŒïŒãªã©ã®é¢æ°ãšåãå éšãã€ã³ã¿ãŒã§ã¯æ©èœãããç¬èªã®ããŒã«ã«ã«ãŒãã§æ©èœããããšãç解ããããšãéèŠã§ãããµã€ã¯ã«ã®ããã«ã
ãªããžã§ã¯ããå埩åŠçãã
é åã®ãããªãªããžã§ã¯ãã¯ãå埩å¯èœãªãšã³ãã£ãã£ã§ãã ãªããžã§ã¯ãã¯ããã®ã³ã³ããã¹ãã§è¡šç€ºãããããããã£ã«ãã£ãŠã¯ããŒã«ãããããããã£åã¯ããŒãšããŠæ©èœããŸãã
class Foo { public $first = 1; public $second = 2; protected $third = 3; public function iterate() { foreach ($this as $key => $value) { echo $key . '=>' . $value; echo "\n"; } } } $foo = new Foo; foreach ($foo as $key => $value) { echo $key . '=>' . $value; echo "\n"; } /* first=>1 second=>2 */ $foo->iterate(); /* first=>1 second=>2 third=>3 */
ãã ãããã®ãããªå埩ã¯ããã®ç®ã«èŠããç¹æ§ã«åŸã£ãŠãå€ãã®å Žåå®å šã«åœ¹ã«ç«ããªãã æãäžè¬çãªäŸã¯ãå éšã®å®å šãªã¹ãã¢ã«å€ã®ã»ãããæ ŒçŽãããªããžã§ã¯ãã§ãã ããšãã°ã次ã®ããã«ïŒ
class Storage { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } }
ãããªãã¯ããããã£ãæããªããã®ãããªãªããžã§ã¯ãã®å埩ãæŽçããæ¹æ³ã¯ïŒ ãããŠãããçš®ã®ã«ã¹ã¿ã éæšæºã¢ã«ãŽãªãºã ã䜿çšããŠäžè¬çã«å埩ãæŽçããæ¹æ³ã¯ïŒ
ã€ãã¬ãŒã¿ã€ã³ã¿ãŒãã§ã€ã¹
ç¬èªã®å埩ã¢ã«ãŽãªãºã ãå®è£ ããããã«ãPHPïŒãŸãã¯SPLïŒã¯ã5ã€ã®ã¡ãœããã§æ§æãããç¹å¥ãªIteratorã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸãã
// public function current(); // public function key(); // "" public function next(): void; // "" public function rewind(): void; // - ? public function valid(): bool
ã¯ã©ã¹ã¯ãããã®ã¡ãœãããå®è£ ããå¿ èŠããããå®è£ ãããã¢ã«ãŽãªãºã ã«åŸã£ãŠforeachã«ãŒãã䜿çšããŠãã®ã¯ã©ã¹ã®ãªããžã§ã¯ããå埩ããæ©äŒãåŸãããŸãã
ããã§ã€ãã¬ãŒã¿ã€ã³ã¿ãŒãã§ã€ã¹ã¡ãœããã®èª¬æã§èšåãããŠããNB "ãã€ã³ã¿"ã¯ãå®éã«ååšããé åã®å éšãã€ã³ã¿ãšã¯å¯Ÿç §çã«ãçŽç²ãªæœè±¡åã§ãã ãã®æœè±¡åã®å®è£ æ¹æ³ã¯ãŠãŒã¶ãŒã«ãã£ãŠç°ãªããŸããçµæã®ã¿ãéèŠã§ããããšãã°ãrewindïŒïŒããã³currentïŒïŒã¡ãœããã®é£ç¶åŒã³åºãã¯ãæåã®èŠçŽ ã®å€ãè¿ãå¿ èŠããããŸãã
Iteratorã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããæãç°¡åãªäŸ
class Example implements Iterator { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } public function current() { return current($this->storage); } public function key() { return key($this->storage); } public function next(): void { next($this->storage); } public function rewind(): void { reset($this->storage); } public function valid(): bool { return null !== key($this->storage); } } $test = new Example; $test->set('foo', 'bar'); $test->set('baz', 42); foreach ($test as $key => $val) { echo $key . '=>' . $val; echo "\n"; }
Traversableããã³IteratorAggregate
å³å¯ã«èšãã°ãTraversableã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããšãforeachã䜿çšããŠå埩åŠçãè¡ãããšãã§ããIteratorããã®åŸç¶ã§ãã Traversableã®æ©èœã¯ãçŽæ¥å®è£ ã§ããªãïŒäžçš®ã®ãæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ãïŒãããã¢ããªã±ãŒã·ã§ã³ã§Iteratorã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯ãã®ãåŒãIteratorAggregateã䜿çšããå¿ èŠããããŸãã 圌ã«ã€ããŠè©±ããŸãããã
SPLã«ã¯ãã€ãã¬ãŒã¿ãŒãªããžã§ã¯ãã§ä»ã®ãšã³ãã£ãã£ïŒé åãªã©ïŒãã©ããã§ããããã€ãã®çµã¿èŸŒã¿ã€ãã¬ãŒã¿ãŒã¯ã©ã¹ãå«ãŸããŠããŸãã
$iterator = new ArrayIterator([1, 2, 3]); foreach ($iterator as $key => $val) { // ... }
ãã®ãããªæ¢è£œã®ã€ãã¬ãŒã¿ã©ãããŒã®ãªã¹ãã¯éåžžã«å€§ãããDirectoryIteratorïŒæå®ããããã£ã¬ã¯ããªå ã®ãã¡ã€ã«ã®ãªã¹ããå埩åŠçïŒãRecursiveArrayIteratorïŒãã¹ããããé åã®ååž°çãã©ããŒã¹ïŒãFilterIteratorïŒäžèŠãªå€ã®æåŠã«ãããã©ããŒã¹ïŒãããã³ãã®ä»ã®å€æ°ã®æçšãªã¯ã©ã¹ãå«ãŸããŸã ã
æ¢è£œã®ã€ãã¬ãŒã¿ãŒãšIteratorAggregateã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšãããšãç¬èªã®ã€ãã¬ãŒã¿ãŒã¯ã©ã¹ã®äœæãå€§å¹ ã«ç°¡çŽ åã§ããŸãã ãããã£ãŠãäžèšã®ãã¿ãã¬ã®äžã«ããéåžžã«é·ãã¯ã©ã¹ã¯ã次ã®ãããªãã®ã«æžããããšãã§ããŸãã
class Example implements IteratorAggregate { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } public function getIterator(): Traversable { return new ArrayIterator($this->storage); } }
-çµæã¯ãIteratorã€ã³ã¿ãŒãã§ãŒã¹ã®å®è£ ãšåãã«ãªããŸãã
ãžã§ãã¬ãŒã¿ãŒã¯ã©ãã§ããïŒ
ãã¡ããã§ãã foreachã§ãããã䜿çšããŸãïŒ
class Generator implements Iterator
ãã ãããžã§ãã¬ãŒã¿ãŒã¯å¥ã®èšäºã®ãããã¯ã§ãã ãããŸã§ã®éããžã§ãã¬ãŒã¿ãŒã®ã¡ã«ããºã ã«éæ³ã¯äœããªããšèšãã ãã§ååã§ããåãIteratorã€ã³ã¿ãŒãã§ãŒã¹ãå埩ã«äœ¿çšãããŸãã 1ã€ã®ãbutããé€ããŠãå埩ãæ¢ã«éå§ãããŠããå Žåããžã§ãã¬ãŒã¿ãŒããæåã«å·»ãæ»ããããšã¯ã§ããŸãããrewindïŒïŒã¡ãœãããåŒã³åºããšäŸå€ãã¹ããŒãããŸãã
å埩å¯èœã¿ã€ã
PHP 7.1ããåã«ã¯ãå¥åŠãªç¶æ³ããããŸããã äžæ¹ã«ã¯ãIteratorãŸãã¯IteratorAggregateãä»ããŠTraversableãå®è£ ããå埩å¯èœãªãªããžã§ã¯ãããããŸããã åãã¡ã«ããºã ã䜿çšããã®ãšåãåŽã«ãžã§ãã¬ãŒã¿ãŒããããŸããã ãŸããå察åŽã«ã¯é åãããããªããžã§ã¯ãã®å¯èŠããããã£ã«å¯Ÿããããã€ãã£ããå埩ããããŸãã å®éãåãåäœããããå ±éç¹ã®ãªã2çš®é¡ã®å埩å¯èœãªãšã³ãã£ãã£ããããŸããã
7.1ã§ã¯ãæçµçã«ãã®äžæŽåã解æ¶ãããå¥ã®ãç䌌åãïŒãŸãã¯ãããã«ã¹ã¿ã åïŒããå埩å¯èœãã«ãªããŸããã
PHPã§typeæŒç®åã衚瀺ãããã®ããã€ãåŸ ã€ãšãiterableã®å®çŸ©ã¯æ¬¡ã®ããã«èšè¿°ã§ããŸãã
type iterable = array | Traversable;
ãã®åã¯ãé åãšãã¹ãŠã®Traversableåå«ãçµã¿åãããforeachã䜿çšããŠå埩ã§ããå€ã®åã瀺ããŸãã
function doSomething(iterable $it) { foreach ($it as $key=>$val) { // do something } }
ãããŠãããã¯äœã§ããïŒ
ãã®ã¿ã€ããã£ãŒãã¯æ¬¡ã®ãšããã§ãã
iterable ---> array --> Traversable ---> Iterator --> IteratorAggregate --> Generator
衚瀺å¯èœãªããããã£ã«å¿ããŠãã€ãã£ããªå埩ãèš±å¯ãããªããžã§ã¯ãïŒããªããžã§ã¯ãã ããã¿ã€ãïŒã¯ãå埩å¯èœãªã¿ã€ãã«ãŸã å«ãŸããŠããªãããšã«æ³šæããŠãã ããã ãããããã®ãããªãªããžã§ã¯ããå埩åŠçããããšã®å®çšçãªäŸ¡å€ã¯ããã»ã©å€§ãããªããããåæºããçç±ã¯ãããŸãã...
ä»ã«èªããã®ã¯äœã§ããïŒ
- en.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D1%82%D0%B8%D0%B2%D0 ïŒ BDïŒ D1ïŒ 8BïŒ D0ïŒ B9_ïŒ D0ïŒ BCïŒ D0ïŒ B0ïŒ D1ïŒ 81ïŒ D1ïŒ 81ïŒ D0ïŒ B8ïŒ D0ïŒ B2
- https://en.wikipedia.org/wiki/%D0%A6%D0%B8%D0%BA%D0%BB_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80% D0ïŒ B0ïŒ D0ïŒ BCïŒ D0ïŒ BCïŒ D0ïŒ B8ïŒ D1ïŒ 80ïŒ D0ïŒ BEïŒ D0ïŒ B2ïŒ D0ïŒ B0ïŒ D0ïŒ BDïŒ D0ïŒ B8ïŒ D0ïŒ B5ïŒïŒãD0.A1ã D0.BE.D0.B2.D0.BC.D0.B5.D1.81.D1.82.D0.BD.D1.8B.D0.B9_.D1.86.D0.B8.D0.BA.D0ã BB
- php.net/manual/ru/language.types.array.php
- php.net/manual/ru/control-structures.foreach.php
- php.net/manual/ru/language.oop5.iterations.php
- php.net/manual/ru/spl.iterators.php
- php.net/manual/ru/class.traversable.php
ã€ã³ã¿ãã¥ãŒãšè·å Žã§ã®æåïŒ