Source Code for /public/03-lists-and-loops/index.php

<?php
// Include the functions.php file, which provides functions we use all over the place:
require('../inc/functions.php');

// Render our HTML header, including this lesson's title
add_header('Lesson 3: Lists and Loops');
?>

<div class="objectives">
  <h2>Objectives</h2>
  <ul>
    <li>Create a variable and assign it a value</li>
    <li>Use a <code>for</code> loop to repeat a block of code a certain number of times</li>
    <li>Use a <code>foreach</code> loop to iterate through each item in an array</li>
    <li>Understand that arrays can be indexed by numbers (the default) or by strings</li>
    <li>Use a <code>glob()</code> function to turn a list of files into an array</li>
  </ul>
</div>

<h2 id="looping">Looping</h2>
<p>
  PHP has several ways of looping through the same code several times.
  A <code>for</code> loop lets you specify the number of times the loop should run. The
  syntax is a little gnarly if you've not come across <code>for</code> loops in any
  language before, but you'll get to grips with it with practice.
</p>
<p>
  Let's create a new file called <code>7-times-table.php</code> to show off how well we
  know our 7-times table:
</p>
<?php code_block_from_file( '03-lists-and-loops/7-times-table.php', 'php' ); ?>
<p>
  Here's what's happening:
</p>
<ol>
  <li>Our <code>for</code> loop creates a variable called <code>$i</code> and assign it the value 1</li>
  <li>While the value of <code>$i</code> is less than or equal to 10, the code inside the <code>for</code> loop is executed, and then the value of <code>$i</code> is increased by 1 (<code>++</code>)</li>
  <li>
    We print out the question <code>"7 × $i = "</code>
    <ul>
      <li>
        See how PHP lets us use the variable right in the middle of the string: this is called
        <a href="https://www.php.net/manual/en/language.types.string.php#language.types.string.parsing">string interpolation</a>,
        and it works for strings in double quotes (<code>"</code>) but not for strings in single quotes (<code>'</code>)
      </li>
    </ul>
  </li>
  <li>Then we calculate the answer <code>( 7 * $i )</code> and <code>echo</code> it out</li>
  <li>Finally, we <code>echo</code> a HTML line break (<code>&lt;br&gt;</code>)</li>
</ol>
<p class="tip">
  Doing your 7-times table up to ten sevens isn't so impressive, but what if you made it go to a hundred sevens. Or a thousand?
</p>
<p class="tip">
  It's possible to put loops inside other loops. Can you work out how to print out all the 1-times tables, 2-times tables, 
  3-times tables, etc., up to 12-times-12? You'll need a loop inside another loop, with the "outer" loop using a different
  variable name than the "inner" loop.
  <small>(<a href="https://php.danq.dev/demo-harness.php?file=public/appendix-samples/times-tables-square.php">🏁 view solution</a>)</small>
</p>

<h2 id="looping-through-a-list">A basic gallery</h2>
<p>
  Another kind of loop is the <code>foreach</code> loop. This iterates through each item in an array.
  (An array is a kind of list of values.) Arrays in PHP can be defined either using square brackets (<code>[]</code>)
  or the <code>array()</code> function: either way, the items in the array are separated by commas (<code>,</code>).
</p>
<p>
  Here I've made an array listing different fruits. For each fruit
  in the array, I exit my PHP code (<code>?&gt;</code>) to start writing HTML code. I write an <code>&lt;img&gt;</code>
  tag for each fruit, using the fruit's name as part of the filename and to help write the alt-text:
</p>
<?php code_block_from_file( '03-lists-and-loops/loop-through-images.php', 'php' ); ?>
<p>
  Loops are great when you want to do a very similar thing multiple times, like when you're outputting a list
  of links or the images in a gallery.
</p>
<p class="tip">
  Instead of showing each image, could you make an ordered list (<code>&lt;ol&gt;</code> and <code>&lt;li&gt;</code>) of
  hyperlinks (<code>&lt;a href="..."&gt;...&lt;/a&gt;</code>) to each fruit's image?
  <small>(<a href="https://php.danq.dev/demo-harness.php?file=public/appendix-samples/fruity-links.php">🏁 view solution</a>)</small>
</p>
<p>
  By default, an array in PHP is indexed by numbers (starting from 0). If you wanted to print the name of <em>third</em> fruit
  in the array, you could write <code>&lt;?php echo $images[2]; ?&gt;</code>. But it's also possible to index an array by
  some other identifier, such as a string. This means it's possible to make an array like this:
</p>
<?php code_block_from_file( '03-lists-and-loops/string-keyed-array.php', 'php' ); ?>

<h2 id="navigation-menu">Making a navigation menu</h2>
<p>
  Let's use what we know to write some PHP that prints out a navigation menu for our site. A navigation menu is a perfect
  example of something that may require the same repetitive structure several times over:
</p>
<?php code_block_from_file( '03-lists-and-loops/navigation-menu.php', 'php', true, true, true ); ?>

<p class="tip">
  <em>This site</em> uses a navigation menu like this, but with a few enhancements. If you're curious, you can
  <a href="/source-viewer.php?file=public/inc/functions.php">view the source code</a> to see how it's done (look
  in the <code>add_navbar()</code> function).
</p>

<p>
  Because we're working in PHP code, we can edit our array dynamically. For example, we could add a link to
  <a href="/02-hello-world/#conditional">the page we made that's closed on Mondays</a> to our navigation menu... but only
  if it's not a Monday.
</p>
<p>
  To do this, we use an <code>if</code> statement to check if today is Monday. If it isn't, we use PHP's
  <code>[]=</code> operator to add a new link to our array (another option would be the
  <a href="https://www.php.net/manual/en/function.array-push.php"><code>array_push()</code></a> function):
</p>
<?php code_block_from_file( '03-lists-and-loops/navigation-menu-2.php', 'php', true, true, true ); ?>
<p>
  The same approach could be used to add menu items that are only visible to logged-in users, for example.
  You'd still want to check if they're logged-in when they visit the page behind the link, of course, to prevent
  them from simply typing its URL into their browser's address bar!
</p>

<h2 id="looping-through-files">Looping through files</h2>
<p>
  Let's revisit our fruit gallery from before, but instead of manually specifying the list of fruits, we'll use
  PHP's <a href="https://www.php.net/manual/en/function.glob.php"><code>glob()</code></a> function. It'll
  produce an array of all the files in the <code>img/fruit/</code> directory, which we can then loop through
  (using <code>foreach</code>) to display each image:
</p>
<?php code_block_from_file( '03-lists-and-loops/loop-through-files.php', 'php' ); ?>
<p>
  Now if we add a new <code>.jpg</code> file into the <code>img/fruit/</code> directory, it will automatically be
  added to the gallery.
</p>
<p class="tip">
   What if there were both <code>.jpg</code> and <code>.webp</code> images in the directory? Can you work out how
   to loop through both types of image using a single loop?
   <a href="https://www.php.net/manual/en/function.array-merge.php"><code>array_merge()</code></a> might be useful.
   What about if you want to keep the fruit in alphabetical order, regardless of their file extension?
   Then you might want to use the <a href="https://www.php.net/manual/en/function.sort.php"><code>sort()</code></a> function.
  <small>(<a href="https://php.danq.dev/demo-harness.php?file=public/appendix-samples/fruity-gallery-2.php">🏁 view solution</a>)</small>
</p>

<h2 id="selecting-from-an-array">Showing a random quote</h2>
<p>
  PHP provides the <a href="https://www.php.net/manual/en/function.array-rand.php"><code>array_rand()</code></a> function
  which selects a random key from an array. Let's use that to show a random quote to our visitors:
</p>
<?php code_block_from_file( '03-lists-and-loops/random-quote.php', 'php' ); ?>
<p class="tip">
  Could you use this technique to show a random image, <em>and</em> apply a random CSS effect to it?
  <a href="/demo-harness.php?file=public/appendix-samples/random-image-with-effect.php">🏁 view solution</a>
</p>

<?php
// Render our HTML footer
add_footer();
?>