Control structures

So far, our files have been executed line by line. Due to that, we have been getting notices on some scenarios, such as when the array does not contain what we are looking for. Would it not be nice if we could choose which lines to execute? Control structures to the rescue!

A control structure is like a traffic diversion sign. It directs the execution flow depending on some predefined conditions. There are different control structures, but we can categorize them in conditionals and loops. A conditional allows us to choose whether to execute a statement or not. A loop executes a statement as many times as you need. Let's take a look at each one of them.

Conditionals

A conditional evaluates a Boolean expression, that is, something that returns a value. If the expression is true, it will execute everything inside its block of code. A block of code is a group of statements enclosed by {}. Let's see how it works:

<?php
echo "Before the conditional.";
if (4 > 3) {
    echo "Inside the conditional.";
}
if (3 > 4) {
    echo "This will not be printed.";
}
echo "After the conditional.";

In the preceding piece of code, we use two conditionals. A conditional is defined by the keyword if followed by a Boolean expression in parentheses and by a block of code. If the expression is true, it will execute the block, otherwise it will skip it.

You can increase the power of conditionals by adding the keyword else. This tells PHP to execute some block of code if the previous conditions were not satisfied. Let's see an example:

if (2 > 3) {
    echo "Inside the conditional.";
} else {
    echo "Inside the else.";
}

The preceding example will execute the code inside the else as the condition of the if was not satisfied.

Finally, you can also add an elseif keyword followed by another condition and a block of code to continue asking PHP for more conditions. You can add as many elseif as you need after an if. If you add an else, it has to be the last one of the chain of conditions. Also keep in mind that as soon as PHP finds a condition that resolves to true, it will stop evaluating the rest of conditions.

<?php
if (4 > 5) {
    echo "Not printed";
} elseif (4 > 4) {
    echo "Not printed";
} elseif (4 == 4) {
    echo "Printed.";
} elseif (4 > 2) {
    echo "Not evaluated.";
} else {
    echo "Not evaluated.";
}
if (4 == 4) {
    echo "Printed";
}

In the last example, the first condition that evaluates to true is the highlighted one. After that, PHP does not evaluate any more conditions until a new if starts.

With this knowledge, let's try to clean up our application a bit, executing statements only when needed. Copy this code to your index.php file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bookstore</title>
</head>
<body>
    <p>
<?php
if (isset($_COOKIE[username'])) {
    echo "You are " . $_COOKIE['username'];
} else {
    echo "You are not authenticated.";
}
?>
    </p>
<?php
if (isset($_GET['title']) && isset($_GET['author'])) {
?>
    <p>The book you are looking for is</p>
    <ul>
        <li><b>Title</b>: <?php echo $_GET['title']; ?></li>
        <li><b>Author</b>: <?php echo $_GET['author']; ?></li>
    </ul>
<?php
} else {
?>
    <p>You are not looking for a book?</p>
<?php
}
?>
</body>
</html>

In this new code, we have mixed conditionals and HTML code in two different ways. The first one opens a PHP tag, and adds an if…else clause that will print whether we are authenticated or not with an echo. No HTML is merged within the conditionals, which makes it clear.

The second option—the second highlighted block—shows an uglier solution, but sometimes necessary. When you have to print a lot of HTML code, echo is not that handy, and it is better to close the PHP tag, print all HTML you need, and then open the tag again. You can do that even inside the code block of an if clause as you can see in the code.

Note

Mixing PHP and HTML

If you feel that the last file we edited looks rather ugly, you are right. Mixing PHP and HTML is confusing, and you should avoid it. In Chapter 6, Adapting to MVC, we will see how to do things properly.

Let's edit our authenticate.php file too, as it is trying to access the $_POST entries that might not be there. The new content of the file would be as follows:

<?php
$submitted = isset($_POST['username']) && isset($_POST['password']);
if ($submitted) {
    setcookie('username', $_POST['username']);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bookstore</title>
</head>
<body>
<?php if ($submitted): ?>
    <p>Your login info is</p>
    <ul>
        <li><b>username</b>: <?php echo $_POST['username']; ?></li>
        <li><b>password</b>: <?php echo $_POST['password']; ?></li>
    </ul>
<?php else: ?>
    <p>You did not submit anything.</p>
<?php endif; ?>
</body>
</html>

This code also contains conditionals, which we already know. We are setting a variable to know if we submitted a login or not, and set the cookies if so. But the highlighted lines show you a new way of including conditionals with HTML. This makes the code more readable when working with HTML code, avoiding the use of {}, and instead using : and endif. Both syntaxes are correct, and you should use the one that you consider more readable in each case.

Switch…case

Another control structure similar to if…else is switch…case. This structure evaluates only one expression, and executes the block depending on its value. Let's see an example:

<?php
switch ($title) {
    case 'Harry Potter':
        echo "Nice story, a bit too long.";
        break;
    case 'Lord of the Rings':
        echo "A classic!";
        break;
    default:
        echo "Dunno that one.";
        break;
}

The switch clause takes an expression, in this case a variable, and then defines a series of cases. When the case matches the current value of the expression, PHP executes the code inside it. As soon as PHP finds a break statement, it exits the switch…case. In case none of the cases are suitable for the expression, PHP executes the default, if there is one, but that is optional.

You also need to know that breaks are mandatory if you want to exit the switch…case. If you do not specify any, PHP will keep on executing statements, even if it encounters a new case. Let's see a similar example, but without the breaks:

<?php
$title = 'Twilight';
switch ($title) {
    case 'Harry Potter':
        echo "Nice story, a bit too long.";
    case 'Twilight':
        echo 'Uh...';
    case 'Lord of the Rings':
        echo "A classic!";
    default:
        echo "Dunno that one.";
}

If you test this code in your browser, you will see that it prints Uh...A classic! Dunno that one. PHP found that the second case is valid, so it executes its content. But as there are no breaks, it keeps on executing until the end. This might be the desired behavior sometimes but not usually, so be careful when using it!

Loops

Loops are control structures that allow you to execute certain statements several times, as many times as you need. You might use them in several different scenarios, but the most common one is when interacting with arrays. For example, imagine you have an array with elements, but you do not know what is in it. You want to print all its elements, so you loop through all of them.

There are four types of loops. Each of them has its own use cases, but in general, you can transform one type of loop into another. Let's look at them closely.

While

The while loop is the simplest of the loops. It executes a block of code until the expression to evaluate returns false. Let's see one example:

<?php
$i = 1;
while ($i < 4) {
    echo $i . " ";
    $i++;
}

In the preceding example, we define a variable with value 1. Then we have a while clause in which the expression to evaluate is $i < 4. This loop executes the content of the block of code until that expression is false. As you can see, inside the loop we are incrementing the value of $i by 1 each time, so the loop ends after 4 iterations. Check the output of that script and you will see "0 1 2 3". The last value printed is 3, so at that time the value of $i was 3. After that, we increased its value to 4, so when the while clause evaluates if $i < 4, the result is false.

Note

Whiles and infinite loops

One of the most common problems with the while loops is creating an infinite loop. If you do not add any code inside the while loop that updates any of the variables considered in the while expression such that it can be false at some point, PHP will never exit the loop!

Do…while

The do…while loop is very similar to while in the sense that it evaluates an expression each time, and will execute the block of code until that expression is false. The only difference is that when this expression is evaluated, the while clause evaluates the expression before executing the code, so sometimes, we might not even enter the loop if the expression evaluates to false the very first time. On the other hand, do…while evaluates the expression after it executes its block of code, so even if the expression is false from the very beginning, the loop will be executed at least once.

<?php
echo "with while: ";
$i = 1;
while ($i < 0) {
    echo $i . " ";
    $i++;
}
echo "with do-while: ";
$i = 1;
do {
    echo $i . " ";
    $i++;
} while ($i < 0);

The preceding piece of code defines two loops with the same expression and block of code, but if you execute them, you will see that only the code inside the do…while is executed. In both cases, the expression is false since the beginning, so while does not even enter the loop, whereas the do…while enters the loop once.

For

The for loop is the most complex of the four loops. It defines an initialization expression, an exit condition, and the end of an iteration expression. When PHP first encounters the loop, it executes what is defined as the initialization expression. Then, it evaluates the exit condition and if it resolves to true, it enters the loop. After executing everything inside the loop, it executes the end of the iteration expression. Once done, it evaluates the end condition again, going through the loop code and the end of the iteration expression, until it evaluates to false. As always, an example will clarify it:

<?php
for ($i = 1; $i < 10; $i++) {
    echo $i . " ";
}

The initialization expression is $i = 1, and is executed only the first time. The exit condition is $i < 10, and it is evaluated at the beginning of each iteration. The end of the iteration expression is $i++, which is executed at the end of each iteration. This example prints the numbers from 1 to 9. Another more common usage of the for loop is with arrays:

<?php
$names = ['Harry', 'Ron', 'Hermione'];
for ($i = 0; $i < count($names); $i++) {
    echo $names[$i] . " ";
}

In this example, we have an array of names. Since it is defined as a list, its keys will be 0, 1, and 2. The loop initializes the variable $i to 0, and it iterates until the value of $i is not less than the number of elements in the array, that is, 3. In the first iteration, $i is 0, in the second, it is 1, and in the third one it is equal to 2. When $i is 3, it will not enter the loop, as the exit condition evaluates to false.

On each iteration, we print the content of the position $i of the array, hence the result of this code will be all three names in the array.

Tip

Be careful with exit conditions

It is very common to set an exit condition that is not exactly what we need, especially with arrays. Remember that arrays start with 0 if they are a list, so an array of three elements will have entries of 0, 1, and 2. Defining the exit condition as $i <= count($array) will cause an error in your code, as when $i is 3, it also satisfies the exit condition and will try to access the key 3, which does not exist.

Foreach

The last, but not least, type of loop is foreach. This loop is exclusive for arrays, and it allows you to iterate an array entirely, even if you do not know its keys. There are two options for the syntax, as you can see in the following examples:

<?php
$names = ['Harry', 'Ron', 'Hermione'];
foreach ($names as $name) {
    echo $name . " ";
}
foreach ($names as $key => $name) {
    echo $key . " -> " . $name . " ";
}

The foreach loop accepts an array—in this case $names—and it specifies a variable which will contain the value of the entry of the array. You can see that we do not need to specify any end condition, as PHP will know when the array has been iterated. Optionally, you can specify a variable that contains the key of each iteration, as in the second loop.

The foreach loops are also useful with maps, where the keys are not necessarily numeric. The order in which PHP iterates the array will be the same order that you used to insert the contents in the array.

Let's use some loops in our application. We want to show the available books in our home page. We have the list of books in an array, so we will have to iterate all of them with a foreach loop, printing some information from each one. Append the following code to the body tag in index.php:

<?php endif;
    $books = [
        [
            'title' => 'To Kill A Mockingbird',
            'author' => 'Harper Lee',
            'available' => true,
            'pages' => 336,
            'isbn' => 9780061120084
        ],
        [
            'title' => '1984',
            'author' => 'George Orwell',
            'available' => true,
            'pages' => 267,
            'isbn' => 9780547249643
        ],
        [
            'title' => 'One Hundred Years Of Solitude',
            'author' => 'Gabriel Garcia Marquez',
            'available' => false,
            'pages' => 457,
            'isbn' => 9785267006323
        ],
    ];
?>
<ul>
<?php foreach ($books as $book): ?>
        <li>
            <i><?php echo $book['title']; ?></i>
            - <?php echo $book['author']; ?>
<?php if (!$book['available']): ?>
          <b>Not available</b>
<?php endif; ?>
        </li>
<?php endforeach; ?>
    </ul>

The highlighted code shows a foreach loop using the : notation as well, which is better when mixing it with HTML. It iterates all of the $books array, and for each book, it prints some information as an HTML list. Notice also that we have a conditional inside a loop, which is perfectly fine. Of course, this conditional will be executed for each entry in the array, so you should keep the block of code of your loops as simple as possible.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.67.70