27 min read

In this article by Antonio Lopez Zapata, the author of the book Learning PHP 7, you need to understand not only the syntax of the language, but also its grammatical rules, that is, when and why to use each element of the language. Luckily, for you, some languages come from the same root. For example, Spanish and French are romance languages as they both evolved from spoken Latin; this means that these two languages share a lot of rules, and learning Spanish if you already know French is much easier.

(For more resources related to this topic, see here.)

Programming languages are quite the same. If you already know another programming language, it will be very easy for you to go through this chapter. If it is your first time though, you will need to understand from scratch all the grammatical rules, so it might take some more time. But fear not! We are here to help you in this endeavor.

In this chapter, you will learn about these topics:

  • PHP in web applications
  • Control structures
  • Functions

PHP in web applications

Even though the main purpose of this chapter is to show you the basics of PHP, doing so in a reference-manual way is not interesting enough. If we were to copy paste what the official documentation says, you might as well go there and read it by yourself. Instead, let’s not forget the main purpose of this book and your main goal—to write web applications with PHP. We will show you how can you apply everything you are learning as soon as possible, before you get too bored.

In order to do that, we will go through the journey of building an online bookstore. At the very beginning, you might not see the usefulness of it, but that is just because we still haven’t seen all that PHP can do.

Getting information from the user

Let’s start by building a home page. In this page, we are going to figure out whether the user is looking for a book or just browsing. How do we find this out? The easiest way right now is to inspect the URL that the user used to access our application and extract some information from there. Save this content as your index.php file:

<?php
$looking = isset($_GET['title']) || isset($_GET['author']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Bookstore</title>
</head>
<body>
   <p>You lookin'? <?php echo (int) $looking; ?></p>
   <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>
</body>
</html>

And now, access http://localhost:8000/?author=Harper Lee&title=To Kill a Mockingbird. You will see that the page is printing some of the information that you passed on to the URL.

For each request, PHP stores in an array—called $_GET– all the parameters that are coming from the query string. Each key of the array is the name of the parameter, and its associated value is the value of the parameter. So, $_GET contains two entries: $_GET[‘author’] contains Harper Lee and $_GET[‘title’] contains To Kill a Mockingbird.

On the first highlighted line, we are assigning a Boolean value to the $looking variable. If either $_GET[‘title’] or $_GET[‘author’] exists, this variable will be true; otherwise, false. Just after that, we close the PHP tag and then we start printing some HTML, but as you can see, we are actually mixing HTML with PHP code.

Another interesting line here is the second highlighted line. We are printing the content of $looking, but before that, we cast the value. Casting means forcing PHP to transform a type of value to another one. Casting a Boolean to an integer means that the resultant value will be 1 if the Boolean is true or 0 if the Boolean is false. As $looking is true since $_GET contains valid keys, the page shows 1.

If we try to access the same page without sending any information as in http://localhost:8000, the browser will say “Are you looking for a book? 0”. Depending on the settings of your PHP configuration, you will see two notice messages complaining that you are trying to access the keys of the array that do not exist.

Casting versus type juggling

We already knew that when PHP needs a specific type of variable, it will try to transform it, which is called type juggling. But PHP is quite flexible, so sometimes, you have to be the one specifying the type that you need. When printing something with echo, PHP tries to transform everything it gets into strings. Since the string version of the false Boolean is an empty string, this would not be useful for our application. Casting the Boolean to an integer first assures that we will see a value, even if it is just “0”.

HTML forms

HTML forms are one of the most popular ways to collect information from users. They consist a series of fields called inputs in the HTML world and a final submit button. In HTML, the form tag contains two attributes: the action points, where the form will be submitted and method that specifies which HTTP method the form will use—GET or POST. Let’s see how it works. Save the following content as login.html and go to http://localhost:8000/login.html:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Bookstore - Login</title>
</head>
<body>
   <p>Enter your details to login:</p>
   <form action="authenticate.php" method="post">
       <label>Username</label>
     <input type="text" name="username" />
       <label>Password</label>
       <input type="password" name="password" />
       <input type="submit" value="Login"/>
   </form>
</body>
</html>

This form contains two fields, one for the username and one for the password. You can see that they are identified by the name attribute. If you try to submit this form, the browser will show you a Page Not Found message, as it is trying to access http://localhost:8000/authenticate.phpand the web server cannot find it. Let’s create it then:

<?php
$submitted = !empty($_POST);
?>
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Bookstore</title>
</head>
<body>
   <p>Form submitted? <?php echo (int) $submitted; ?></p>
   <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>
</body>
</html>

As with $_GET, $_POST is an array that contains the parameters received by POST. In this piece of code, we are first asking whether that array is not empty—note the ! operator. Afterwards, we just display the information received, just as in index.php. Note that the keys of the $_POST array are the values for the name argument of each input field.

Control structures

So far, our files have been executed line by line. Due to that, we are getting some 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 will execute 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 this piece of code, we are using 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 a 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.";
}

This will execute the code inside else as the condition of if was not satisfied.

Finally, you can also add an elseif keyword followed by another condition and block of code to continue asking PHP for more conditions. You can add as many elseif as you need after if. If you add 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 the 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 this last example, the first condition that evaluates to true is the one that is highlighted. After that, PHP does not evaluate any more conditions until a new if starts.

With this knowledge, let’s try to clean up a bit of our application, 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 are mixing 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 echo. No HTML is merged within the conditionals, which makes it clear.

The second option—the second highlighted block—shows an uglier solution, but this is 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 the 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.

Mixing PHP and HTML

If you feel like the last file we edited looks rather ugly, you are right. Mixing PHP and HTML is confusing, and you have to avoid it by all means.

Let’s edit our authenticate.php file too, as it is trying to access $_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 submitted anything.</p>
<?php endif; ?>
</body>
</html>

This code also contains conditionals, which we already know. We are setting a variable to know whether we’ve submitted a login or not and to set the cookies if we have. However, the highlighted lines show you a new way of including conditionals with HTML. This way, tries to be 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 case takes an expression; in this case, a variable. It 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 break, it will exit switch-case. In case none of the cases are suitable for the expression, if there is a default case         , PHP will execute it, but this is optional.

You also need to know that breaks are mandatory if you want to exit 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 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 is printing “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 we need to 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 on 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 their own use cases, but in general, you can transform one type of loop into another. Let’s see them closely

While

While 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++;
}

Here, we are defining a variable with the value 1. Then, we have a while clause in which the expression to evaluate is $i < 4. This loop will execute 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 after 4 iterations, the loop will end. Check out the output of that script, and you will see “0 1 2 3”. The last value printed is 3, so by that time, $i was 3. After that, we increased its value to 4, so when the while was evaluating whether $i < 4, the result was false.

Whiles and infinite loops

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

For

This is the most complex of the four loops. For defines an initialization expression, an exit condition, and the end of the 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 this is done, it will evaluate the end condition again, going through the loop code and the end of iteration expression until it evaluates to false. As always, an example will help clarify this:

<?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 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. As it is defined as a list, its keys will be 0, 1, and 2. The loop initializes the $i variable to 0, and it will iterate until the value of $i is not less than the amount of elements in the array 3 The first iteration $i is 0, the second will be 1, and the third one will be 2. When $i is 3, it will not enter the loop as the exit condition evaluates to false.

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

We careful with exit conditions

It is very common to set an exit condition. This is not exactly what we need, especially with arrays. Remember that arrays start with 0 if they are a list, so an array of 3 elements will have entries 0, 1, and 2. Defining the exit condition as $i <= count($array) will cause an error on your code, as when $i is 3, it also satisfies the exit condition and will try to access to 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 these 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. 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 will contain the key of each iteration, as in the second loop.

Foreach loops are also useful with maps, where the keys are not necessarily numeric. The order in which PHP will iterate the array will be the same order in which you used to insert the content 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, which is better when mixing it with HTML. It iterates all the $books arrays, and for each book, it will print some information as a HTML list. Also note 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.

Functions

A function is a reusable block of code that, given an input, performs some actions and optionally returns a result. You already know several predefined functions, such as empty, in_array, or var_dump. These functions come with PHP so you do not have to reinvent the wheel, but you can create your own very easily. You can define functions when you identify portions of your application that have to be executed several times or just to encapsulate some functionality.

Function declaration

Declaring a function means to write it down so that it can be used later. A function has a name, takes arguments, and has a block of code. Optionally, it can define what kind of value is returning. The name of the function has to follow the same rules as variable names; that is, it has to start by a letter or underscore and can contain any letter, number, or underscore. It cannot be a reserved word.

Let’s see a simple example:

function addNumbers($a, $b) {
   $sum = $a + $b;
   return $sum;
}
$result = addNumbers(2, 3);

Here, the function’s name is addNumbers, and it takes two arguments: $a and $b. The block of code defines a new variable $sum that is the sum of both the arguments and then returns its content with return. In order to use this function, you just need to call it by its name, sending all the required arguments, as shown in the highlighted line.

PHP does not support overloaded functions. Overloading refers to the ability of declaring two or more functions with the same name but different arguments. As you can see, you can declare the arguments without knowing what their types are, so PHP would not be able to decide which function to use.

Another important thing to note is the variable scope. We are declaring a $sum variable inside the block of code, so once the function ends, the variable will not be accessible any more. This means that the scope of variables declared inside the function is just the function itself. Furthermore, if you had a $sum variable declared outside the function, it would not be affected at all since the function cannot access that variable unless we send it as an argument.

Function arguments

A function gets information from outside via arguments. You can define any number of arguments—including 0. These arguments need at least a name so that they can be used inside the function, and there cannot be two arguments with the same name. When invoking the function, you need to send the arguments in the same order as we declared them.

A function may contain optional arguments; that is, you are not forced to provide a value for those arguments. When declaring the function, you need to provide a default value for those arguments, so in case the user does not provide a value, the function will use the default one:

function addNumbers($a, $b, $printResult = false) {
   $sum = $a + $b;
   if ($printResult) {
       echo 'The result is ' . $sum;
   }
   return $sum;
}
$sum1 = addNumbers(1, 2);
$sum1 = addNumbers(3, 4, false);
$sum1 = addNumbers(5, 6, true); // it will print the result

This new function takes two mandatory arguments and an optional one. The default value is false, and is used as a normal value inside the function. The function will print the result of the sum if the user provides true as the third argument, which happens only the third time that the function is invoked. For the first two times, $printResult is set to false.

The arguments that the function receives are just copies of the values that the user provided. This means that if you modify these arguments inside the function, it will not affect the original values. This feature is known as sending arguments by a value. Let’s see an example:

function modify($a) {
   $a = 3;
}

$a = 2;
modify($a);
var_dump($a); // prints 2

We are declaring the $a variable with the value 2, and then we are calling the modify method, sending $a. The modify method modifies the $a argument, setting its value to 3. However, this does not affect the original value of $a, which reminds to 2 as you can see in the var_dump function.

If what you want is to actually change the value of the original variable used in the invocation, you need to pass the argument by reference. To do that, you add & in front of the argument when declaring the function:

function modify(&$a) {
   $a = 3;
}

Now, after invoking the modify function, $a will be always 3.

Arguments by value versus by reference

PHP allows you to do it, and in fact, some native functions of PHP use arguments by reference—remember the array sorting functions; they did not return the sorted array; instead, they sorted the array provided. But using arguments by reference is a way of confusing developers. Usually, when someone uses a function, they expect a result, and they do not want their provided arguments to be modified. So, try to avoid it; people will be grateful!

The return statement

You can have as many return statements as you want inside your function, but PHP will exit the function as soon as it finds one. This means that if you have two consecutive return statements, the second one will never be executed. Still, having multiple return statements can be useful if they are inside conditionals. Add this function inside your functions.php file:

function loginMessage() {
   if (isset($_COOKIE['username'])) {
       return "You are " . $_COOKIE['username'];
   } else {
       return "You are not authenticated.";
   }
}

Let’s use it in your index.php file by replacing the highlighted content—note that to save some tees, I replaced most of the code that was not changed at all with //…:

//...
<body>
   <p><?php echo loginMessage(); ?></p>
<?php if (isset($_GET['title']) && isset($_GET['author'])): ?>
//...

Additionally, you can omit the return statement if you do not want the function to return anything. In this case, the function will end once it reaches the end of the block of code.

Type hinting and return types

With the release of PHP7, the language allows developers to be more specific about what functions get and return. You can—always optionally—specify the type of argument that the function needs, for example, type hinting, and the type of result the function will return—return type. Let’s first see an example:

<?php

declare(strict_types=1);

function addNumbers(int $a, int $b, bool $printSum): int {
   $sum = $a + $b;
   if ($printSum) {
       echo 'The sum is ' . $sum;
   }
   return $sum;
}

addNumbers(1, 2, true);
addNumbers(1, '2', true); // it fails when strict_types is 1
addNumbers(1, 'something', true); // it always fails

This function states that the arguments need to be an integer, and Boolean, and that the result will be an integer. Now, you know that PHP has type juggling, so it can usually transform a value of one type to its equivalent value of another type, for example, the string 2 can be used as integer 2. To stop PHP from using type juggling with the arguments and results of functions, you can declare the strict_types directive as shown in the first highlighted line. This directive has to be declared on the top of each file, where you want to enforce this behavior.

The three invocations work as follows:

  • The first invocation sends two integers and a Boolean, which is what the function expects. So, regardless of the value of strict_types, it will always work.
  • The second invocation sends an integer, a string, and a Boolean. The string has a valid integer value, so if PHP was allowed to use type juggling, the invocation would resolve to just normal. But in this example, it will fail because of the declaration on top of the file.
  • The third invocation will always fail as the something string cannot be transformed into a valid integer.

Let’s try to use a function within our project. In our index.php file, we have a foreach loop that iterates the books and prints them. The code inside the loop is kind of hard to understand as it is mixing HTML with PHP, and there is a conditional too. Let’s try to abstract the logic inside the loop into a function. First, create the new functions.php file with the following content:

<?php
function printableTitle(array $book): string {
   $result = '<i>' . $book['title'] . '</i> - ' . $book['author'];
   if (!$book['available']) {
       $result .= ' <b>Not available</b>';
   }
   return $result;
}

This file will contain our functions. The first one, printableTitle, takes an array representing a book and builds a string with a nice representation of the book in HTML. The code is the same as before, just encapsulated in a function.

Now, index.php will have to include the functions.php file and then use the function inside the loop. Let’s see how this is done:

<?php require_once 'functions.php' ?>
<!DOCTYPE html>
<html lang="en">

//...

?>
   <ul>
<?php foreach ($books as $book): ?>
   <li><?php echo printableTitle($book); ?> </li>
<?php endforeach; ?>
   </ul>

//...

Well, now our loop looks way cleaner, right? Also, if we need to print the title of the book somewhere else, we can reuse the function instead of duplicating code!

Summary

In this article, we went through all the basics of procedural PHP while writing simple examples in order to practice them. You now know how to use variables and arrays with control structures and functions and how to get information from HTTP requests among others.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here