Welcome to our free PHP tutorial. This tutorial is based on Webucator's Introduction to PHP Training course.
In this lesson, you will get a thorough introduction to how PHP works and you will write your first PHP scripts. We will also introduce you to the website you will be building throughout this course.
Lesson Goals
As this may be your first experience programming on the server, we'll start with an introduction to how the server-side works. Client-side pages (HTML, CSS, and JavaScript) are executed by the browser, but the browser needs to get those pages somehow. Generally, they are delivered by a server. For static websites, the server will simply fetch and deliver those pages. For dynamic websites, some magic gets done on the server, which could affect the content of the pages returned.
If you have already taken our Creating, Styling, and Validating Web Forms course, the rest of the content in this reading will be familiar to you. You are welcome to review it or skip ahead to the next activity.
The first step to understanding server-side programming is to understand how a web server works. The diagram below shows how a web server delivers static pages, such as HTML, JavaScript, CSS, image files, audio and video files, PDFs, all of which browsers have a built-in way of handling; and other files that can be downloaded but not handled by the browser, such as Microsoft Word documents, zip files, and executables. All these files, both the ones the browser handles and the ones it just downloads, are static, meaning they are simply fetched by the web server and returned to the client without any processing on the server.
Dynamic websites are websites that do more than just fetch and return files. They have software on the server that reviews the client request before deciding what to do. Depending on the client request, the server may just return a static file or it may perform any number of processes on the server before returning a dynamically created file to the client. Here are some examples of what a dynamic site might do when it receives a request:
Web servers can have access to all sorts of software on the computer on which they sit and can even reach across networks to make requests of other servers, so the variety of tasks they can perform is infinite. Follow the numbers in the diagram below to see how a dynamic website works:
At the time of this writing, the most widely used web servers are:
And the most widely used server-side programming languages are:
While JavaScript is more well known as a client-side technology, it is now often used in server-side programming as well, most often with Node.js.
The Google Chrome DevTools' Network tab shows which files are delivered when the browser makes a request. Let's first take a look at what it shows when we request a file from our local file system without going through a server:
The most common status codes returned by a web server are listed below along with their meanings:
As the server-side developer, you have the ability to return these status codes and to decide what pages get returned with them. For example, it is common to return a special "404 Page Not Found" page when the user navigates to a URL on your website that doesn't exist. The screenshot below shows how Google handles this:Notice the 404 status on the Network tab.
When a user browses to a page that ends with a .php extension, the request is sent to a web server, which directs the request to the PHP interpreter. The PHP interpreter processes the page, communicating with file systems, databases, and email servers as necessary, and then delivers a web page to the web server to return to the browser.
Before we look at PHP syntax, we should briefly mention the php.ini file. This is a plain text file that is used to configure PHP. When the PHP interpreter is started, it reads the php.ini file to determine what settings to use. We will mention this file from time to time throughout the course, but for now, it is enough that you are aware of its existence.
PHP code must be contained in special tags so that the PHP interpreter can identify it. The open tag is:
<?php
And the close tag is:
?>
It is an unwritten rule that every programming course must contain a "Hello, World!" script. Here it is:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Hello, World!</title> </head> <body> <main> <?php // Write out Hello World! echo '<p>Hello, World!</p>'; ?> </main> </body> </html>
Notice the following about the above code:
<?php
and ?>
is processed by the PHP interpreter.echo
command is used to print text back to the browser.This code isn't very exciting. In fact, PHP doesn't buy us anything here as we could have just as easily output the result using straight HTML. There is nothing dynamic about this script. After learning about variables, we'll take a look at some more interesting examples.
Open this page in your browser by navigating to http://localhost:8888/Webucator/php/PHPBasics/Demos/hello-world.php. You should see the following page:
In this course, we assume that you are using port 8888 to serve your PHP pages. We also assume that your class files are located in htdocs/Webucator/php/.
If you're using a different port or your file structure is different from this, you will need to modify the localhost URLs accordingly.
Many of our class files will reference static image, JavaScript, and CSS files that are stored in a folder called static in the php folder:
These files are used throughout the demo site, which we will introduce soon, and the class files, but don't have any bearing on the PHP you are learning.
PHP has two forms of comments:
//
)./*
" and end with "*/
".// This is a single-line comment /* This is a multi-line comment. */
PHP has two forms of comments:
//
)./*
" and end with "*/
".// This is a single-line comment /* This is a multi-line comment. */
There are literally hundreds of built-in PHP functions that do everything from returning the current date and time on the server to pulling data out of a database. A function might take zero arguments (e.g, pi()
, which simply returns the value of Π
) or it might take multiple arguments (e.g, trim()
, which takes one required and one optional argument). The syntax for calling a function is straightforward:
function_name(arguments);
The example below shows how to call a simple function: phpinfo()
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>PHPINFO</title> </head> <body> <?php //Output information on the PHP environment phpinfo(); ?> </body> </html>
Open this page in your browser by navigating to http://localhost:8888/Webucator/php/PHPBasics/Demos/phpinfo.php. This will return a page similar to the following that shows how PHP is configured on the server:
PHP functions are well documented at https://www.php.net. You can quickly look up documentation on a function by going to https://www.php.net/function_name. For example, to see documentation on phpinfo()
, go to https://www.php.net/phpinfo. You should see something like this:
The function signature shows what a function will return and what parameters it must or can take. Here is how it is broken out:
returnType
: The type of object returned by the function. Some possible values are:
int
bool
string
array
mixed
- the function can return different types of dataphp_info()
function doesn't have any required parameters.$what
parameter of phpinfo()
is optional and has the default value of INFO_ALL
, which is a constant (to be covered soon).Take a look at the function signature for date (from https://www.php.net/date):
string date (string $format [, int $timestamp = time() ])
$format
parameter is required and must be a string.$timestamp
parameter is optional and defaults to the value returned by the build-in time()
function, which you will explore in the following exercise.The epoch is the moment that a computer or computer language considers time to have started. PHP considers the epoch to be January 1, 1970 at midnight (1970-01-01 00:00:00
). Times before the epoch are expressed internally as negative numbers.
Find and read through the php.net documentation on the following functions:
date()
time()
mktime()
min()
max()
Pay attention to the function signature and the parameter descriptions. You may also find it interesting to read some of the user-contributed comments. Those can sometimes be very useful.
Create a new PHP file and experiment with the functions.
There is no real solution to this exercise. The documentation for the functions is located at:
date()
- https://www.php.net/datetime()
- https://www.php.net/timemktime()
- https://www.php.net/mktimemin()
- https://www.php.net/minmax()
- https://www.php.net/maxVariables are used to hold data in memory.
The main variable types in PHP are listed in the table below:
Variable Type | Explanation |
---|---|
Integer | whole number |
Float | floating-point number |
String | string of characters |
Boolean | true or false |
Array | list of items |
Object | instance of a class |
Variable names and all other identifiers in PHP (e.g., function names) are case sensitive and must begin with a dollar sign followed by letters, digits, and underscores. As a convention, variable names in PHP are written in lowerCamelCase
. Here are some example variable assignments:
$firstName = 'Thomas'; $birthWeight = 9.6; $yearOfBirth = 1743; $favoriteFruit = 'banana'; $isAdmin = false;
Variable, function and class names are all identifiers and all follow these rules, with the exception that function names are not case sensitive, though the best practice is to treat function names as if they were.
PHP variables are not assigned a type (e.g, integer) at the time they are declared. Rather, the type of a PHP variable is determined at runtime by the value the variable holds and the way in which it is used. Most of the time, this is useful, but it can cause problems as we will see later in the course. Because of these potential problems, it can be useful to explicitly change the type of a variable by casting it to a different type. This is done by putting the new type in parentheses before the variable to be cast, like this:
$a = '1'; // $a is a string $a = (int) $a; // $a is now an integer $a = (bool) $a; // $a is now a boolean
See PhpBasics/Demos/gettype.php, which uses the gettype()
function to show the current type of $a
after each cast. Then run the file by visiting http://localhost:8888/Webucator/php/PHPBasics/Demos/gettype.php.
Here is the "Hello, World!" script again, but this time we use a variable:
<?php $greeting = 'Hello, World!'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title><?php echo $greeting; ?></title> </head> <body> <main> <p> <?php echo $greeting; ?> </p> </main> </body> </html>
This time the string "Hello, World!" is stored in the $greeting
variable, which is output in the title
and body
of the page with an echo
command.
In this exercise, you will write a simple PHP script from scratch. The script will declare a variable called $today
that stores the day of the week and outputs it to the page in the title
and the body
.
$today
that holds the current day of the week as literal text.$today
in the title
and body
of the page. Instead of assigning a literal string (e.g, "Monday") to $today
, use the built-in date()
function so that the script won't have to be manually updated every day to stay current. For documentation, visit https://www.php.net/date.
<?php $today = 'Monday'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title><?php echo $today; ?></title> </head> <body> <?php echo $today; ?> </body> </html>
<?php $today = date('l'); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title><?php echo $today; ?></title> </head> <body> <?php echo $today; ?> </body> </html>
A variable's scope determines the locations from which the variable can be accessed. PHP variables are either superglobal, global, or local.
Variable Scope | Explanation |
---|---|
superglobal | Superglobal variables, also called automatic globals, are predefined arrays, including $_POST and $_GET . They are accessible everywhere. |
global | Global variables are accessible throughout the script in which they are declared and any files that are included by that script. However, they are not visible within functions in the script unless they are re-declared within the function as global variables. |
local | Variables in the function scope are called local variables. Local variables are local to the function in which they are declared. |
Again, superglobal variables are predefined arrays, including $_POST
and $_GET
, and are accessible from anywhere on the page. The list of superglobals is shown below:
$_GET
- variables passed into a page on the query string.$_POST
- variables passed into a page through a form using the post method.$_SERVER
- server environment variables (e.g, $_SERVER['HTTP_REFERER']
returns the URL of the referring page).$_COOKIE
- cookie variables.$_FILES
- variables containing information about uploaded files.$_ENV
- PHP environment variables (e.g, $_ENV['HTTP_HOST']
returns the name of the host server.$_REQUEST
- variables passed into a page through forms, the query string and cookies.$_SESSION
- session variables.The elements within superglobal variables are accessed using the following syntax:
$_GET['var-name']
We will revisit superglobals throughout the course.
In PHP, for simple strings you can use single quotes and double quotes interchangeably. However, there is one important difference of which you need to be aware. Text within single quotes will not be parsed for variables and escape sequences (e.g., \n
for a newline and \t
for a tab). Compare the examples below:
---- C O D E O M I T T E D ---- <?php $person = 'George'; echo '<p>Hello, $person!!</p>'; ?> ---- C O D E O M I T T E D ----
Because of the use of single quotes above, the string <p>Hello, $person!!</p>
will be output literally, as shown below:
---- C O D E O M I T T E D ---- <?php $person = 'George'; echo "<p>Hello, $person!!</p>"; ?> ---- C O D E O M I T T E D ----
This time, because of the double quotes, the string will be parsed for variables and special characters and will be output as shown below:
To include an apostrophe in a string denoted with single quotes, use a backslash to escape the apostrophe. For example:
$author = 'Madeleine L\'Engle';
Do the same thing to include a quotation mark in a string denoted with double quotes:
echo "Madeleine L'Engle said \"The great thing about getting older is that you don't lose all the other ages you've been.\"";
Concatenation is a fancy word for stringing strings of text together. In PHP, concatenation is done with the .
operator. It is often used to combine variables with literals as in the following example:
$firstName = 'Nat'; echo 'Hello, ' . $firstName;
Using the .=
operator, it is possible to do one-step concatenation, in which you append a string on to the end of another string as shown below:
$name = 'Nat'; $name .= ' Dunn'; echo $name; // will echo 'Nat Dunn'
A common way to pass values from the browser to the server is by appending them to the URL as follows:
https://www.example.com/hello.php?greet=Hello&who=World
The part of the URL that follows the question mark is called the query string. One or more name-value pairs can be passed to the server in this way. Each name-value pair is separated by an ampersand (&
). The processing page can read these name-value pairs and use them to determine its response.
The HTML page below shows an example of how these name-value pairs might be passed.
---- C O D E O M I T T E D ---- <p>Do you prefer a formal or informal greeting?</p> <ul> <li><a href="hello-hi.php?greeting=Hello">Formal</a></li> <li><a href="hello-hi.php?greeting=Hi">Informal</a></li> <li><a href="hello-hi.php?greeting=Howdy">Friendly</a></li> </ul> ---- C O D E O M I T T E D ----
<?php // Assign the passed variable to a variable with // a more convenient name. $greeting = $_GET['greeting']; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title><?= $greeting ?>, World!</title> </head> <body> <main> <?php echo "<p>$greeting, World!</p>"; ?> </main> </body> </html>
Notice the following about the code above.
$
).$_GET
array and can be accessed using the following syntax: $_GET['var-name']
.<?php echo 'text to print'; ?>
is: <?= 'text to print' ?>
In this exercise, you will write a script that says "hello" to different people based on what is passed through the query string.
Change the links so that each Beatle gets a custom greeting (e.g, 'Howdy, Paul!', 'Hi, John!', 'Bye, George!', 'Hey, Ringo!').
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Greeting the Beatles</title> </head> <body> <main> <p>Choose a Beatle to greet.</p> <ul> <li><a href="hello-who.php?beatle=Paul">Paul</a></li> <li><a href="hello-who.php?beatle=John">John</a></li> <li><a href="hello-who.php?beatle=George">George</a></li> <li><a href="hello-who.php?beatle=Ringo">Ringo</a></li> </ul> </main> </body> </html>
<?php $beatle = $_GET['beatle']; ?> <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Hello, <?= $beatle ?>!</title> </head> <body> <main> <?php echo "<p>Hello, $beatle!</p>"; ?> </main> </body> </html>
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Greeting the Beatles</title> </head> <body> <main> <p>Choose a Beatle to greet.</p> <ul> <li> <a href="hello-who-challenge.php?beatle=Paul&greeting=Hi"> Paul</a> </li> <li> <a href="hello-who-challenge.php?beatle=John&greeting=Hello"> John</a> </li> <li> <a href="hello-who-challenge.php?beatle=George&greeting=Bye"> George</a> </li> <li> <a href="hello-who-challenge.php?beatle=Ringo&greeting=Hey"> Ringo</a> </li> </ul> </main> </body> </html>
<?php $beatle = $_GET['beatle']; $greeting = $_GET['greeting']; ?> <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title><?= $greeting . ', ' . $beatle ?>!</title> </head> <body> <main> <?php echo "<p>$greeting, $beatle!</p>"; ?> </main> </body> </html>
User-defined functions (UDFs) are used to make common tasks easier and to make code more modular and easier to read.
A simple function is defined as follows:
function myFunction() { doThis(); doThat(); doThisOtherThing(); }
Like built-in functions, UDFs can receive parameters. To define a function with parameters, place receiving variables in the parentheses:
function addNums($param1, $param2, $param3) { $sum = $param1 + $param2 + $param3; echo 'The sum is ' . $sum; }
UDFs can also return values:
function addNums($param1, $param2, $param3) { $sum = $param1 + $param2 + $param3; return $sum; }
UDFs are called in the same way that built-in functions are. For example, the following code calls the addNums()
function to get the sum of three numbers:
$total = addNums(1,3,5);
The following file shows the above code in action:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Simple User-defined Function</title> </head> <body> <main> <?php function addNums($param1, $param2, $param3) { $sum = $param1 + $param2 + $param3; return $sum; } $total = addNums(1,3,5); echo $total; ?> </main> </body> </html>
Note that calling addNums()
without passing in the correct number of values will result in a fatal error. You can fix this by providing default values.
You can make function parameters optional by assigning default values to them as shown in the example below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>User-defined Function with Default Values</title> </head> <body> <main> <?php function addNums($param1=0, $param2=0, $param3=0) { $sum = $param1 + $param2 + $param3; return $sum; } $total = addNums(1,3); echo $total; ?> </main> </body> </html>
In this case, if you don't pass a value into the function for one or more of the parameters, the default value of 0
will be used. When defining a function, all required parameters must precede optional parameters.
In PHP, variables declared outside of functions are not available by default inside of functions. The following code illustrates this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Local Variables</title> </head> <body> <main> <?php $a = 10; function incrNumBy($incr) { return $a + $incr; } $c = incrNumBy(5); echo '<hr>'; echo $c; // outputs 5 to the browser ?> </main> </body> </html>
As $a
is not available within incrNumBy()
, a warning is generated, which depending on your settings (more on this soon) may or may not be output to the browser:
Notice that the function doesn't take into account the value of
$a
and returns only the value passed in as $incr
: 5
.
To make global variables available within a function, they must be declared within the function as global variables using the global
keyword as shown below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>Global Variables</title> </head> <body> <main> <?php $a = 10; function incrNumBy($incr) { global $a; return $a + $incr; } $c = incrNumBy(5); echo $c; // outputs 15 to the browser ?> </main> </body> </html>
This time the call to incrNumBy()
will output 15
as expected.
By default, variables are passed to functions by value, meaning that the function's receiving variables get copies of the values received rather than pointers to them. If the receiving variables are modified, the passed variables remain unaffected. The following code illustrates this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>By Value</title> </head> <body> <main> <?php $a = 10; $b = 5; function incrNumBy($num, $incr) { $num += $incr; } incrNumBy($a,$b); echo $a; //outputs 10 to the browser ?> </main> </body> </html>
The code above outputs "10" to the browser. Although $num
was incremented by 5, $a
was unaffected by the function call. To pass a variable by reference, put an ampersand (&
) before the parameter in the function definition as shown below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="../../static/styles/normalize.css"> <link rel="stylesheet" href="../../static/styles/styles.css"> <title>By Reference</title> </head> <body> <main> <?php $a = 10; $b = 5; function incrNumBy(&$num, $incr) { $num += $incr; } incrNumBy($a,$b); echo $a; //outputs 15 to the browser ?> </main> </body> </html>
This time the function outputs "15" because $num
references the variable $a
itself. So, any change in $num
will affect $a
.
Throughout this course, we will be building a complete website for reading and writing poems. Some of the features the website includes are:
Let's take a look at the complete site, a live version of which is available at http://www.phppoetry.com:
Throughout this course, you will learn to build this "PHP Poetry" site. The site you buld will also have an "admin" section, accessible via an Admin link in the footer:
Admins can edit, delete, and approve and unapprove poems. They can also update users and make other users administrators.
Most websites, including PHP Poetry, have a header and footer that are common to many pages. Rather than rewrite the header and footer with every new page, wouldn't it be nice if you could just write them once and include them on multiple pages on the site? Enter PHP.
PHP provides two common constructs for including files in web pages: require
and include
. They are basically the same with one minor difference: require
throws a fatal error when it fails; whereas, include
only gives a warning. If the included file is necessary (i.e., required) to continue to process the page, you should use require
.
It is important to keep in mind that a PHP tag cannot start in a calling file and continue in an included file. All PHP code in the included file must be nested in PHP tags.
require
is not actually a function, but a language construct, so require statements do not need parentheses:
require path_to_file;
path_to_file
can be an absolute or a relative path.
require_once
can be used just like require
. The difference is that if the included file has already been included by earlier code, it will not be re-included.
The following code samples demonstrate how to include files using require
:
<?php $headerText = 'Hello!'; $footerText = 'Goodbye!'; echo $headerText; ?> <hr>
<hr> <?php echo $footerText; ?>
<?php require 'includes/header.php'; ?> <h1>Body of Page</h1> <p>This the body.</p> <?php require 'includes/footer.php'; ?>
The above code is relatively straightforward. include-demo.php contains two included (required) files: header.php and footer.php, both of which are in the includes folder.
Visit http://localhost:8888/Webucator/php/PHPBasics/Demos/include-demo.php to see the page in the browser. When the browser requests include-demo.php, PHP combines the two included files into the main file and the web server returns the result to the browser:View the page source to see the resulting markup of the page, showing you exactly what PHP created:
Note that this demo is intentionally kept very simple. Normally, you would create a complete HTML page starting with the open <html>
tag and ending with the close </html>
tag.
In this exercise, you will start with a full HTML page and break out the reusable parts into include files.
Navigate to http://localhost:8888/Webucator/php/PHPBasics/Exercises/phppoetry.com in your browser:Clicking the More Poems link will bring you to the poem listing:
Then clicking on the Dancing Dogs in Dungarees link will take you to that poem:
Notice that the top and bottom of these three pages are identical.
</header>
tag.<footer>
tag to the end of the file.$pageTitle
to 'Poems'.$pageTitle
to 'Dancing Dogs in Dungarees'.<title>
tag starts with the $pageTitle
value followed by "| The Poet Tree Club". For example, the title for poem.php, once interpreted by PHP, should end up being: <title>Dancing Dogs in Dungarees | The Poet Tree Club</title>
<!DOCTYPE HTML> <html lang="en"> <head> ---- C O D E O M I T T E D ---- <title><?= $pageTitle ?> | The Poet Tree Club</title> </head> <body> <header> <nav id="main-nav"> <!-- Bar icon for mobile menu --> <div id="mobile-menu-icon"> <i class="fa fa-bars"></i> </div> <ul> <li><a href="index.php">Home</a></li> <li><a href="poems.php">Poems</a></li> <li><a href="poem-submit.php">Submit Poem</a></li> <li><a href="my-account.php">My Account</a></li> <li><a href="contact.php">Contact us</a></li> </ul> </nav> <h1> <a href="index.php">The Poet Tree Club</a> </h1> <h2>Set your poems free...</h2> </header>
<footer> <span>Copyright © 2019 The Poet Tree Club.</span> <nav> <a href="logout.php">Log out</a> <a href="admin/index.php">Admin</a> <a href="about-us.php">About us</a> </nav> </footer> </body> </html>
<?php $pageTitle = 'Poems'; require 'includes/header.php'; ?> <main id="poems"> ---- C O D E O M I T T E D ---- </main> <?php require 'includes/footer.php'; ?>
This page should look just as it did before. Notice the title:
<?php $pageTitle = 'Dancing Dogs in Dungarees'; require 'includes/header.php'; ?> <main id="poem"> ---- C O D E O M I T T E D ---- </main> <?php require 'includes/footer.php'; ?>
This page should look just as it did before. Notice the title (you may need to hover over it to see the whole thing):
<?php require 'includes/header.php'; ?> <main> ---- C O D E O M I T T E D ---- </main> <?php require 'includes/footer.php'; ?>
This page should look just as it did before with one tiny exception. Notice the pipe at the beginning of the title: The code in header.php that outputs the title looks like this:
<title><?= $pageTitle ?> | The Poet Tree Club</title>
But we don't declare a $pageTitle
variable in index.php, so nothing gets output. In fact, this generates a low-level error in PHP called a warning. Normally, warnings are simply ignored, but you can change this as we will soon see.
Constants are like variables except that, once assigned a value, they cannot be changed. Constants are created using the define()
function and by convention (but not by rule) are in all uppercase letters. Constants can be accessed from anywhere on the page.
define('CONST_NAME',VALUE);
If you try to reassign a value to a constant, it will fail and trigger an E_NOTICE
, which is a low-level error that will likely go unnoticed. For example:
<?php define('BASE_YEAR', 1970); define('BASE_YEAR', 1971); // Fails echo BASE_YEAR; // 1970 ?>
PHP includes a large number of predefined constants. You won't have to worry about most of these, but there are a couple of interesting ones:
PHP_VERSION
- The version of PHP that you are running.DEFAULT_INCLUDE_PATH
- The path to the directory in which PHP will look for included files after it looks in the current directory. More on this soon.Visit http://localhost:8888/Webucator/php/PHPBasics/Demos/predefined-constants.php to see the value of both of these constants. The code for this page is shown below:
---- C O D E O M I T T E D ---- <main> <table> <thead> <tr> <th>Constant</th> <th>Value</th> </tr> </thead> <tbody> <tr> <td><code>PHP_VERSION</code></td> <td><?= PHP_VERSION ?></td> </tr> <tr> <td><code>DEFAULT_INCLUDE_PATH</code></td> <td><?= DEFAULT_INCLUDE_PATH ?></td> </tr> </tbody> </table> </main> ---- C O D E O M I T T E D ----
When you run this file in your browser, you should see something like this:
Many of the predefined constants in PHP are error reporting constants. They are used to set the types of errors that you would like to have reported. All of the error reporting constants are prefixed with E_
. For example:
E_ERROR
: Report fatal run-time errors - errors that will stop execution of the script.E_WARNING
: Report run-time warnings - errors that will not stop the execution of the script.E_DEPRECATED
: Report notices about deprecated code- code that may not work in future versions of PHP.E_ALL
: Report all errors.The level of error reporting is set with the error_reporting
directive in the php.ini file and defaults to E_ALL
. You should most likely leave that default in place.
Two other error-reporting directives in the php.ini file are display_errors
and log_errors
. On a production server, you should set display_errors
to Off
and log_errors
to On
. They are almost certainly already set that way, but you can confirm this in the following two ways:
phpinfo()
function.php_ini_loaded_file()
function to let you know where the php.ini file is located. You should see something like this:Within the php.ini file, you can turn boolean directives on using 1
, On
, True
or Yes
.
You can turn them off using 0
, Off
, False
or No
.
As already mentioned, on a production server, you will likely leave these settings unchanged, but you can change them on your development server if you like. Alternatively, you can change them using the ini_set()
function. The most likely setting you will want to change during development is display_errors
, which controls whether errors are output to the browser. During production, you definitely don't want that to happen, but during development, you probably do. To do so, at the beginning of every script or in the included header.php file, add the following code:
ini_set('display_errors', '1');
In this exercise, you will turn on the display_errors
setting whenever the site is not running on the production server.
function isProduction() { // Provide way of knowing if the code is on production server return false; } function isDebugMode() { // Set to true if not on production // You may want to provide other ways for setting debug mode return !isProduction(); }
isProduction()
function will provide a mechanism for the code to know if it is running on a development or production server.isDebugMode()
function now. Note that eventually you might have a more nuanced way of setting debug mode. For example, you might give superadmin users a way of turning on debug mode in their settings in an admin section of the website.if (isDebugMode()) { ini_set('display_errors', '1'); }This code uses
ini_set()
to turn on the display_errors
setting, but only when in debug mode.<title>
tag, the error message shows up on the browser tab. Hover over it to see the full error message: Notice: Undefined variable: pageTitle
<?php function isProduction() { // Provide way of knowing if the code is on production server return false; } function isDebugMode() { // Set to true if not on production // You may want to provide other ways for setting debug mode return !isProduction(); } ?>
<?php require_once 'utilities.php'; if (isDebugMode()) { ini_set('display_errors', '1'); } ?> <!DOCTYPE HTML> <html lang="en"> <head> ---- C O D E O M I T T E D ---- <title><?= $pageTitle ?> | The Poet Tree Club</title> </head> ---- C O D E O M I T T E D ----
Setting display_errors
to 1
during development allows us to catch these errors, so that we can improve our code. In the next lesson, we will learn how to fix this error, so that on our home page, we do not try to prepend anything to the site name (i.e., "The Poet Tree Club").
Any file under the web root can potentially be accessed over the web. Navigate to http://localhost:8888/Webucator/php/PHPBasics/Demos/find-document-root.php to find the path to your web root. That will output the path to the root and the paths to the current files and directory:
If included files are under the web root, they can be accessed just as any other file can. If they have an extension such as inc
then the browser may display them as plain text. With other extensions, the browser may attempt to download the file. If the included file is a PHP file and a user navigates to it, the server will try to process the file and may return errors. It is also possible that your web server becomes misconfigured and returns a PHP file as plain text showing your sensitive data in the browser. As a precaution, you should place any included files with sensitive data in a directory outside of the web root. This will prevent users from accessing the files directly.
In order to be able to include files that are outside of the web root, you will need to modify the include_path
directive in the php.ini file. The include_path
directive takes a list of paths to directories in which PHP should look for included files. In the following exercise, you will change your setup to be able to include a configuration file outside of your web root.
In this exercise, you will:
include_path
directive in the php.ini file.Follow these instructions:
include_path
directive and append a colon (Mac) or semi-colon (Windows) followed by the path to the new includes folder to the end. Also, be sure to uncomment the line by removing the leading semi-colon.
; UNIX: "/path1:/path2" include_path = ".:/Applications/MAMP/bin/php/php7.2.10/lib/php:/Applications/MAMP/includes"
; Windows: "\path1;\path2" include_path = ".;c:\php\includes;c:\MAMP\includes"
include_path
line, you should remove it.