Exercises - PHP
0. Environment Setup
Before starting the exercises, make sure you have set up Docker, as explained in the guide.
1. HTTP Parameters
-
- Inside an empty folder, create a script called sum2.php that receives two numbers (num1 and num2) as arguments and prints the sum of those two numbers:
Hint: To access the arguments, you should use the special $_GET array. - On the terminal, run the Docker command from the guide. Make sure to change
C:\html
to the path of the new folder you created. - You can now test your page by going to http://localhost:9000/sum2.php?num1=2&num2=5.
- Make sure the output of your script is valid HTML.
- Create a new HTML file, form2.html, containing a form asking for two numbers.
Note: Make that form send the numbers to the script you created previously. - Modify the PHP file to contain a link back to the form.
Hint: here’s what it should look like:
- Inside an empty folder, create a script called sum2.php that receives two numbers (num1 and num2) as arguments and prints the sum of those two numbers:
2. SQLite Database Creation
-
- Remove the container from the previous exercise.
- Create a new folder.
- Copy the news.sql file into the new folder.
- This file contains an SQL script that creates a new database.
Open the file and see if you can understand what it does. - Create a new database inside the folder using the command:
sqlite3 -init news.sql news.db
- After this last command, the SQLite interface will become active. To verify if the database has been created correctly, try some SQL commands:
SELECT * FROM News WHERE id = 4; SELECT * FROM Comments WHERE news_id = 4;
- To exit from the SQLite interface type:
.exit
- Verify if a new file called news.db has been created.
- To go back to the SQLite interface and interact with the new database type:
sqlite3 news.db
3. Listing Data from SQLite
-
- In the same folder where you created the database, create a new PHP file called index.php.
- On the terminal, create a new Docker container. Make sure to change
C:\html
to the path of the folder you are working on. - Open http://localhost:9000 in your browser.
As expected, you should see an empty page. - In index.php, open a connection to the database using the following PHP code:
<?php $db = new PDO('sqlite:news.db'); ?>
- The $db variable now represents your connection to the database.
- Execute a query returning all news in the database using the following code:
$stmt = $db->prepare('SELECT * FROM News'); $stmt->execute(); $articles = $stmt->fetchAll();
- The $articles variable is now an associative array containing all the news in the database.
- You can iterate over this array using:
<?php foreach ($articles as $article) { ?> <h1><?php echo $article['title'] ?></h1> <p><?php echo $article['introduction'] ?></p> <?php } ?>
- Verify the result at http://localhost:9000.
4. Complete Page
-
- Using your recently acquired PHP superpowers, let’s change the index.php file to create a page like the one we used in the first CSS exercise. In fact, you can start fresh by download the files from that exercise HERE.
- This time, we will get the news from the database instead of them being hard-coded.
- You can use the following SQL to get all the information (article data, user information, and number of comments) about each article:
SELECT News.*, Users.*, COUNT(Comments.id) AS comments FROM News JOIN Users USING (username) LEFT JOIN Comments ON Comments.news_id = News.id GROUP BY News.id, Users.username ORDER BY published DESC
- You can use the date function to format a date in epoch/unix time format. For example:
$date = date('F j', $article['published']);
- You can use the explode function to split a string by a separator. For example:
$tags = explode(',', $article['tags']);
- Do not forget to verify if the page returns valid HTML code.
- Also, create a new page, article.php, that receives a parameter id containing the id of an article in the database.
- This page should be able to present that article and its comments.
- Use the following code to get the article information:
$stmt = $db->prepare('SELECT * FROM News JOIN Users USING (username) WHERE id = ?'); $stmt->execute(array($_GET['id'])); $article = $stmt->fetch();
- And then do this to get the comments:
$stmt = $db->prepare('SELECT * FROM Comments JOIN Users USING (username) WHERE news_id = ?'); $stmt->execute(array($_GET['id'])); $comments = $stmt->fetchAll();
- Create links from the index.php page to the article.php page in the appropriate places.
Change the remaining HTML files to.php
and update all the links accordingly. - Validate all pages.
5. Data Layer Separation
In this exercise, we will separate the code accessing the database from the business logic code:
-
- Create a new folder called database and a new file called connection.php inside that folder.
- Copy the code initializing the database connection into the new file inside a
getDatabaseConnection()
function. - Replace the initialization code in all pages with a
require_once()
instruction (including the newly created file) and a call to the new function. - Inside the same folder, create a file called news.php. This file will be responsible for all the accesses to the News table.
- Inside this file, create a function called
getAllNews()
that receives the database connection, queries the database, and returns an array with all the news. - Replace any code where all articles are retrieved with calls to this new function.
- The initial PHP code in your index.php should now look like this:
<?php require_once('database/connection.php'); require_once('database/news.php'); $db = getDatabaseConnection(); $articles = getAllNews($db); ?>
Do the same changes to your article.php page by calling functions
getNewsItem()
(defined in database/news.php) andgetNewsComments()
(defined in database/comments.php). - In the end, move the news.sql and news.db files to the new database folder.
6. Presentation Layer Separation
-
- All pages in this example start and end with the same HTML code (DOCTYPE, head, header, nav, aside, …).
- Inside a file called templates/common_tpl.php (create the new folder first), create two functions (
output_header()
andoutput_footer()
) that output that code. - Replace that code in both pages (index.php and article.php) by calling these two functions.
Notice that you can output HTML code inside a PHP function very easily. Example:<?php function print_header($title) { ?> <h1><?php echo $title ?></h1> <?php } ?>
- For more specific HTML code, create new files in the templates folder called, for example, news_tpl.php and comments_tpl.php.
- Create functions that output a list of articles and a single article (with and without the full text and comment section).
- Replace that code on both pages by calling these new functions.
- The index.php page should now look like this:
<?php require_once('database/connection.php'); // database connection require_once('database/news.php'); // news table queries require_once('templates/common_tpl.php'); // common templates require_once('templates/news_tpl.php'); // news templates $db = getDatabaseConnection(); // connect to database $articles = getAllNews($db); // get articles from database output_header(); // output page header output_article_list($articles); // output list of articles output_footer(); // output page footer ?>
Notice that you can call other template functions inside a template function to simplify your code. For example:
<?php function output_article_list($articles) { ?> <section id="news"> <?php foreach($articles as $article) output_article($article); ?> </section> <?php } ?>
- Also, move all the CSS files into a css folder.
From this point forward, all pages should be written using this format.
7. Editing Data
-
- Create a new page called edit_article.php that contains a form with three fields: title, introduction, and fulltext.
- Use an input with type “text” for the first one and textareas for the other two. Also, add a submit button.
- This page should receive a parameter called id containing the id of the article to be edited.
- Add a hidden input field containing this id.
- Retrieve the article to be edited from the database and fill the fields with its values.
- Add a link in the article_tpl.php file that points to this new page.
- The “action” of this new form should point to a new file called action_edit_news.php.
- This new file should receive the four values (id, title, introduction, and fulltext) and update the News table with them.
Don’t forget to separate this code into the database/news.php file. - This new action file should not print any HTML. Instead, it should redirect the user back to the article page, sending the correct id as a parameter.
8. Authentication
-
- Modify the login.php file to have the same format as index.php or article.php.
- The form in this file should send the data (username and password) to a new action_login.php file.
- On this new file, start by initiating the session, verifying if the username and password are correct and, if they are, storing the username in the session. In the end, redirect back to the page you came from. Something like this:
<?php session_start(); // starts the session require_once('database/connection.php'); // database connection require_once('database/users.php'); // user table queries if (userExists($_POST['username'], $_POST['password'])) // test if user exists $_SESSION['username'] = $_POST['username']; // store the username header('Location: ' . $_SERVER['HTTP_REFERER']); // redirect to the page we came from ?>
- Add
session_start()
in all pages so you can access the current user easily with$_SESSION['username']
. - Change the header template so that if the $_SESSION array contains a valid user, it will have a logout link pointing to action_logout.php (instead of the login and register links).
- Create this file to destroy the session and redirect back to the previous page.
- Change the article_tpl.php page so that the link to edit news only appears if a user is logged in.
- Change the edit_article.php and action_edit_article.php pages so that if a user is not logged in, they will redirect back to the main page.
9. Insert and Delete
-
- Change register.php file to comply with the new format and create a new action_register.php file that inserts the new user into the database.
- Create pages and actions to insert and delete articles.
- Create actions to insert comments.
Solutions for These Exercises
Acknowledgement
Exercises by André Restivo.