Lab 4: Application Architecture
In this lab, you are going to establish the underlying structure or framework of your application. This will give you a solid basis upon which to extend its functionality. Your tasks today will include:
- Establishing a logical directory structure which will encourage the separation of related scripts and other resources
- Using the include/require constructs to maximise code reuse and encourage a modular way of working
- Implementing a navigation system that will allow a single point of entry to your application
- Incorporating HTML into the scripts to render valid web pages
- Thinking about how the current views could be improved to give them a more obvious purpose, and about what features or functionality might be added to your application in the future.
An example of the end product is available in the lab-exercises
repo in the week-4
directory. Refer to this as necessary, but you don't have to recreate it exactly.
Task 1: Establish a logical directory structure
The current structure of your application will look something like this:
record-store root
|-- README.txt
|-- index.php
|-- artist.php
|-- sql/
| |-- record-store.sql
| |-- dummy-data.sql
-
Create a new directory for storing reuseable scripts in the root of your record-store app. From command line this would be:
mkdir includes
-
Create another one for storing all the scripts that will define the different 'views' of your application. Call this directory
views
. -
Create another directory which will contain purely HTML files. You could call this directory
templates
or something to that effect. -
Move any secondary 'view' scripts into the
views
directory. For example,artist.php
should now belong inviews
, since it offers a specific 'view' of our application.
You should now have a structure which looks something like this:
record-store root
|-- README.txt
|-- index.php
|-- views/
|-- |-- artist.php
|-- includes/
|-- templates/
|-- sql/
| |-- record-store.sql
| |-- dummy-data.sql
Task 2: Create an include to manage the database connection
-
Inside the
includes
directory, create a new .php script calleddb_connect.php
(or something similar). -
Cut and paste the connection code from
index.php
intodb_connect.php
. This should include the part which checks if the connection was successful. -
Where you removed the code from
index.php
, add the following code to include the connection script:require('includes/db_connect.php')
Notice we are using the require()
rather than the include()
here, as our application is essentially useless without a database connection!
Task 3: Implement a single point of entry navigation
You are now going to turn index.php
into the single, generic entry point for the application. You can think of it like the 'lobby' area of the app, from which the other 'rooms' (views) are accessed.
Having a single point of entry offers 2 main advantages:
- It avoids code repetition as scripts which perform common tasks (such as connecting to the database, session handling, etc.) only need to be included once - in index.php. It also means that if you want to add or remove such a task, you just have to change a singe file.
- It decouples the URL which the client sees from the actual, physical file layout on your webserver. That means that you can easily change your URL system (for example, for SEO purposes) without having to actually change the location of your scripts on the server.
-
In
index.php
, include some code which will set a variable$page_id
based on a parameter passed in the URL:// get the value of the page parameter from the URL // if no parameter detected... if (!isset($_GET['page'])) { $page_id = 'home'; // display home page } else { $page_id = $_GET['page']; // else requested page }
In the above, $_GET
is a built-in global variable, from which we can access any parameters that were passed in the URL during a GET request.
-
We will now use a
switch
statement to determine which view script to include, based on the value of$page_id
:switch ($page_id) { case 'home' : include 'views/home.php'; break; case 'record' : include 'views/record.php'; break; case 'artist' : include 'views/artist.php'; break; default : include 'views/404.php'; }
Note that these view scripts don't yet exist - so we now have to make them!
-
Cut and paste the query code from
index.php
(the part that retrives and outputs records from the database) into the appropriate view script. For example, if your query fetched and displayed records, paste it intoviews/record.php
. -
Remove anything from
artist.php
that has already been included byindex.php
(for example, you don't needmysqli_connect()
ormysqli_close()
anymore). -
Create
home.php
and404.php
scripts in the views directory. For now they could just have echo statements in them such as:echo("Home page");
and echo("Error 404: Page not found.");
-
Finally, in order to navigate the new app structure, we need to create a navigation element and incorporate it into
index.php
. Inside the templates directory, create a file,navigation.html
and add to it the following:<nav> <ul> <li><a href="?page=home" title="home">Home</a></li> <li><a href="?page=record" title="records">Records</a></li> <li><a href="?page=artist" title="artists">Artists</a></li> </ul> </nav>
-
Include this script in
index.php
:include('templates/navigation.html')
Notice how, this time, we're using include
, as our app could still retain some functionality without this include.
- Test your app to make sure the right view scripts are loaded for each nav link.
include()
to incorporate HTML
Task 4: Use -
In the templates directory, create a
header.html
file. This will include the document definition, head and opening body tag of your website. For example,<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Record Store</title> </head> <body>
-
Similarly, create a
footer.html
file:</body> </html>
-
Include both of these files in the appropriate locations of your
index.php
file.
Task 5: Incorporate HTML into views
-
Add some HTML to your view scripts to improve the layout and validity of the markup. To do this, it can be helpful to create a
$content
string which is appended bit by bit using the.=
operator. For example, yourrecord.php
view might end up looking something like this:<?php // create variable for content HTML $content = "<h1>Records</h1>"; // fetch records as a result set $sql = "SELECT title, genre, price FROM record"; $result = mysqli_query($link, $sql); // check query returned a result if ($result === false) { echo mysqli_error($link); } else { $content .= "<table border='1'><tbody>"; // fetch associative array while ($row = mysqli_fetch_assoc($result)) { $content .= "<tr>"; $content .= "<td>".$row['title']."</td>"; $content .= "<td>".$row['genre']."</td>"; $content .= "<td>".$row['price']."</td>"; $content .= "</tr>"; } $content .= "</tbody></table>"; // free result set mysqli_free_result($result); } // output the content HTML echo $content; ?>
Note that a <table></table>
element has been used here. This is fine as it is displaying tabular data.
- Test your app again.
Task 6: Add a README.txt
All applications should contain a README file to explain what they are for, and to instruct a user how to install and configure them. For now, your README.txt should contain, at the very least, a link to a live installation of the application. For example, you should add something like this to README.txt
:
Live Demo
---------
This app can be viewed at:
http://doc.gold.ac.uk/~YOUR_USERNAME/dnw/record-store-app/
This will also tell the tutor where to look for it!
Task 7: Push!
Now that you have done some significant work on your app, make sure that the changes have been committed and pushed to the GitLab server. Do:
git add 'LIST_OF_FILES', 'YOU_WORKED_ON', 'HERE!'
git commit -m 'Implementing SPOE navigation'
git push origin master
Task 8: Log a feature request!
In this task you are being asked to give careful consideration to the kinds of features that would be useful to a user of the record store app, and to log a feature request here:
https://learn.gold.ac.uk/mod/forum/discuss.php?d=127072
Try to make your suggestions sensible and not overly complicated! They should also be relevant to the database model we have established. For example, you might suggest that it should be possible for a user to order records by their release year, or that the artist names should be displayed with the records. We will discuss your suggestions in the next lecture, with a view to implementing some of the best ones!