Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 41 additions & 77 deletions language/control-structures/for.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,97 +142,61 @@ endfor;
</informalexample>
</para>
<simpara>
It's common for many users to iterate through arrays like in the
example below.
Expressions <varname>expr2</varname> and <varname>expr3</varname> are
evaluated every iteration. It's advisable to use simple expressions in these
places to avoid performance issues. For example, if the number of iterations
is known in advance, it is better to use a variable instead of a function call
in <varname>expr2</varname>:
</simpara>
<para>
<informalexample>
<programlisting role="php">
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
/*
* This is an array with some data we want to modify
* when running through the for loop.
*/
$people = array(
array('name' => 'Kalle', 'salt' => 856412),
array('name' => 'Pierre', 'salt' => 215863)
);

for($i = 0; $i < count($people); ++$i) {
$people[$i]['salt'] = random_int(100000, 999999);
$people = ['Kalle', 'Pierre'];

// Bad practice: calling a function on every iteration
for($i = 0; $i < getIterationCount($people); ++$i) {
$people[$i] .= ' is cool';
}
var_dump($people);
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "Kalle"
["salt"]=>
int(454478)
}
[1]=>
array(2) {
["name"]=>
string(6) "Pierre"
["salt"]=>
int(776978)
}

// Good practice: storing the count in a variable
for($i = 0, $peopleCount = getIterationCount($people); $i < $peopleCount; ++$i) {
$people[$i] .= ' is cool';
}

]]>
</screen>
</programlisting>
</informalexample>
</para>
<simpara>
The above code can be slow, because the array size is fetched on
every iteration. Since the size never changes, the loop can be easily
optimized by using an intermediate variable to store the size instead
of repeatedly calling <function>count</function>:
In the example above, the function is called on every iteration of the
first loop, even though it always returns the same value. Storing that
value in a variable, as the second loop does, calls the function once.
Note that the number of iterations is then fixed: if the array is
modified inside the loop, the stored value no longer reflects its size.
</simpara>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$people = array(
array('name' => 'Kalle', 'salt' => 856412),
array('name' => 'Pierre', 'salt' => 215863)
);

for($i = 0, $size = count($people); $i < $size; ++$i) {
$people[$i]['salt'] = random_int(100000, 999999);
}
var_dump($people);
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "Kalle"
["salt"]=>
int(454478)
}
[1]=>
array(2) {
["name"]=>
string(6) "Pierre"
["salt"]=>
int(776978)
}
}
]]>
</screen>
</informalexample>
</para>
<note>
<simpara>
The size of an <type>array</type> is stored with the array, which means that
calling the built-in function <function>count</function> does not require
counting the elements and does not cause performance issues. This does not
apply to <constant>COUNT_RECURSIVE</constant>, which walks the whole array.
Care should also be taken when using <function>count</function> on objects
implementing <interfacename>Countable</interfacename>, as such calls can be
more expensive.
</simpara>
</note>

<note>
<simpara>
The <literal>for</literal> loop is not the recommended way to
iterate over arrays. The &foreach; loop is specifically
designed for this purpose and is usually more convenient.
</simpara>
</note>
</sect1>

<!-- Keep this comment at the end of the file
Expand Down
Loading