You are on page 1of 14

‘Delve into Derby’: Report on Implementation

A brief report on the implementation of my application, ‘Delve into Derby’.

Carl Linley – 100298658


University of Derby
c.linley1@unimail.derby.ac.uk
Contents
Introduction ............................................................................................................................................ 3
What is ‘Delve into Derby’? .................................................................................................................... 3
The ‘Home’ screen .............................................................................................................................. 3
Viewing a Venue ................................................................................................................................. 4
Viewing a review ................................................................................................................................. 5
Writing a review .................................................................................................................................. 6
Review confirmation ........................................................................................................................... 7
Installation .......................................................................................................................................... 8
Technologies ........................................................................................................................................... 8
HTML5 ................................................................................................................................................. 8
W3.css ............................................................................................................................................. 9
Font Awesome ................................................................................................................................ 9
PHP .................................................................................................................................................... 10
Database Management – MySQL ..................................................................................................... 11
Google Maps ..................................................................................................................................... 12
Challenges ............................................................................................................................................. 12
What should I do? ......................................................................................................................... 12
Database woes .............................................................................................................................. 12
Debugging ..................................................................................................................................... 13
$_SESSION wasn’t saving .............................................................................................................. 13
Conclusion ............................................................................................................................................. 13
References ............................................................................................................................................ 14
Introduction
I was tasked with creating an application of some description – I had relative freedom, aside from certain con-
straints: the project had to use a client component written in HTML5 or C#, a server component of any lan-
guage, and a relational database of some description. Ideally, it would also use a web service.
After struggling to come up with a good idea that adhered to these constraints, I asked for suggestions and set-
tled on creating a simple web application that allows users to browse venues in Derby – restaurants, cinemas,
and museums – as well as view and leave reviews for them.

What is ‘Delve into Derby’?


The application is a utility; its purpose is to provide users with information on venues in Derby. It
would be aimed primarily at tourists, and other visitors to Derby.

It currently provides users with three categories of venue to choose from: restaurants, cinemas, and
museums. This is fully extensible, new categories can be added simply by adding them to the data-
base. New venues can be added the same way. However, for either of these changes to take effect, a
user would have to change venue type or reset their session.

In designing it like this, I was aiming to adhere to the ‘Open/Closed Principle’ of SOLID object-ori-
ented design.

The ‘Home’ screen


The ‘home’ screen, for a better name, is displayed when the user is not focused on a specific venue.
A list of venues under the selected category is displayed in a navigation bar to the left. Each list entry
contains a venue’s name, its average rating, and a ‘note’ – this can be anything, the purpose varies
depending on the venue’s type. For a restaurant, this may be something like “Italian, European” to
display what type of food is served. The venue list is ordered by the venues’ average rating descend-
ing, so the highest ratings are towards the top.

Ratings are submitted by users in their reviews, and work on a conventional ‘stars out of five’ sys-
tem. The average rating of a venue is calculated by finding the mean rating of its reviews. This value
is then stored in the database. I can see this being an issue if there are multiple users, it would be a
better idea to either re-load the list before submitting or simply re-calculate the average when nec-
essary – the latter, I was doing originally.

Each venue in the list is displayed on the map, powered by Google Maps, along with the user’s ap-
proximate position (displayed in a ‘U’ marker). Hovering over entries in the venue list causes the re-
spective map marker to ‘bounce’. On the other hand, hovering over a map marker displays a tooltip
reading the relevant venue’s name. Clicking the marker has the same effect as clicking the list entry
– setting that venue as the focus and re-configuring the interface appropriately (see figure 2).
w
Figure 1 - The application's 'home', displaying restaurants

The map element is fully interactive, and includes both terrain and street view. It uses JavaScript,
and is built off of Google’s Maps web service. The user’s approximate position is acquired through
HTML5 geolocation, again utilising a web service.

The box reading ‘Restaurants’ is a drop-down list, in which a user may change the current venue
type. Doing this will cause the application to hang slightly whilst the database is queried for the new
venue list. In hindsight, storing every venue of every type in one large array and forcing it to re-load
under certain circumstances (e.g. starting a new session each time the application is opened –
clear.php provides this sort of functionality) may have been a better way to do this.

Viewing a Venue

Figure 2 - Displaying the venue 'Le Bistrot Pierre', a restaurant

Figure 2 demonstrates the lack of a feature I really wanted to include – that of using HTML5’s
<canvas> element and JavaScript to create partially-drawn stars. The mean rating for this venue is
technically 3.6 – just over three and a half stars – but the application works on integral ratings, so
the decimal is discarded. This could be easily changed by removing a call to intval, but it would
yield the same results without implementing the aforementioned <canvas> approach.

The ‘home’ button seen in the menu bar removes the focus, returning to the state seen in figure 1.
This is done by using $_POST to provide the server with a venue ID of -1.

Viewing a review

Figure 3 - Displaying a review

User reviews can be ‘enlarged’ for a better word – clicking on the review in the list displays the
modal seen in figure 3. The modal includes the full body of the review and the date it was written, in
addition to the information already displayed in the list. As one would expect, modals are closed by
clicking the X in the top-right corner. I intended to allow them to be closed by clicking outside the
‘card’ element, on the shaded area, but I did not manage to implement this feature and it seemed
rather low-priority in comparison to more pressing matters.
Writing a review
Users can review a venue by clicking on the speech bubble button in the menu bar. As you may have
noticed, this button is only present when focused on a venue.

Figure 4 - Leaving a review for 'Le Bistrot Pierre'

Review titles have a maximum length of 32 characters, and bodies a maximum length of 250. If ei-
ther field exceeds these bounds on submission, an error message is shown – this is done in JavaS-
cript simply by checking the length of the input and setting the innerHTML property of an invisible
span element accordingly. This error message is used to alert the user in the event that:

A) Their input is too long – it also displays how many characters they’re over the limit by
B) They have not provided a rating
C) They have not provided a title
D) They have not provided a review

The five stars located under the title are interactive, and are used to select the rating. Hovering over
one fills the row out to display the proposed rating. Hovering off of the section causes them to dis-
play the current rating, which is of course set by clicking a star. This is a really simple feature, but the
effect provides a lot of polish.

When the user presses the ‘submit’ button, their review is checked for errors – as mentioned previ-
ously – by calling the function:
checkReviewSubmission(reviewSummary, reviewBody)
If all is in order, this function returns ‘OK’ and the review is sent to the server using the postValues
utility function. If something is amiss, the function returns the appropriate error message.

When the server receives the review submission, it’s processed in DatabaseManager. Since input is
taken directly from the user, attempting to add the review to the database is done using prepared
statements. This prevents susceptibility to a SQL injection attack.
After the review has been processed, the result of the attempt to save it is stored in a session varia-
ble, and the user is redirected to index.php – effectively refreshing the page – using the header func-
tion. Doing this clears the client’s POST, meaning that the review will not be re-submitted if the user
refreshes the page.

When the application is building the HTML, a value of ‘OK’ in the aforementioned session variable
will display a confirmation window (figure 5). Anything else – and it is worth noting that ‘something
else’ would be an exception error message, which is then logged – causes an error window to dis-
play (figure 6). Either way, the variable is then un-set, preventing the modal displaying repeatedly.

Review confirmation
Once a review has been submitted, the user receives confirmation (figure 5). If the submission was
successful, as will be the case in most instances, it’s a simple thank you message.

Figure 5 - Thanking me for leaving a review

If leaving the review is unsuccessful for some reason – such as in the event that the database server
is inaccessible – an error message is shown (figure 6). Figure 6 is not truly an error, as you’ll notice by
my review being successful – I merely changed a condition in index.php to make it display the modal
after a successful review.
I’ve only legitimately had this error once – leaving reviews was failing due to a primary key violation.
This is because I was retrieving the next primary key by counting the number of rows in the Reviews
table. As I had deleted some of the earlier reviews, the primary key was duplicated. I fixed this issue
by modifying the query to retrieve the highest ReviewID, and then incremented that value.

Installation
The application’s files must be run on a PHP-enabled web server, along with a locally accessible
MySQL database. The database must include a schema named ‘venues’, create one simply by run-
ning the query:
CREATE SCHEMA ‘venues’;

Once that schema exists, Build DB.sql can be imported or ‘restored’ using MySQL Workbench, or a
similar database administration tool. This will create and populate the database, data included. Fi-
nally, the constants in DatabaseManager.php (DB_HOST, DB_NAME, DB_USER, DB_PASSWORD) must be
checked and altered if necessary. The database should then be accessible to the application.

The application is accessed by users using a conventional web browser – they should be directed to
index.php.

Technologies

HTML5
As the application is a web application, it primarily uses HTML5: HTML, JavaScript, and CSS. The cli-
ent is the user’s browser, which displays the application’s HTML. There are no raw HTML files – the
HTML is constructed through the server-side PHP code through the use of the echo statement. In do-
ing this; I’ve tried to make the code as elegant as possible but the combination of PHP and HTML is
still a bit of an eye-sore in places.

JavaScript is used primarily to send values to the server using the $_POST method. I went so far as to
create two utility functions to this end to minimise code duplication:
postValue(name, value)
postValues([[name, value], . . .])

JavaScript also handles the behaviour of several elements, specifically:

a) When rating a venue – the proposed rating is filled out when the user hovers over a star, re-
turning to the current rating when the user hovers off. The current proposed rating is stored
in a variable and displayed when the user is not selecting a new one.
b) When a modal is active (‘write review’ and ‘display review’) – it is hidden or shown by the
hide(element) and show(element) functions. The former is called when the user presses the
‘close’ button. The latter is used only in the ‘write review’ modal, and is called when the user
presses the ‘leave review’ button in the menu bar.

CSS is used for styling. I haven’t authored much CSS at all – what I have done is found in
stylesheet.css. It contains a single style, a derivative of the a tag (hyperlink) named ‘fill-div’. This
style simply causes the hyperlink to fill the entire parent element – it’s used in composing both the
list of venues and the list of reviews for a given venue. Even this style, I did not author from scratch –
it’s based on example code found on StackOverflow.
The vast majority of the styling in my application stems from the use of W3.css, which has really
proved invaluable.

W3.css
W3.css is a publically available stylesheet, created by Jan Egil and Borge Refsnes (Egil and Refsnes, n.d)
and hosted on W3Schools. I include it in my HTML by referencing its URL in a <link> line:
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">

I stumbled across it when reading about CSS. Virtually all of the styling in the application uses
W3.css. Without it, I’d have a very primitive-looking application. The stylesheet has enabled me to
add aesthetic lists, modals, combo boxes, and a number of other features with ease.

The file itself is relatively small – 29KB – so there’s very little performance impact in loading it. The
benefits of using it outweigh this negligible impact by a long shot.

I initially opted to use W3.ccs because I wanted to make the application responsive, allowing it to
display well on screens of varying size. This end was half-achieved – whilst the application responds
to differences in size, it doesn’t do so very well. This is something I intended to rectify but I never got
around to actually doing so. The implementation of the Google Map complicated things further.

The W3.css Reference page (w3schools, n.d) proved invaluable in using it, it’s effectively a large glos-
sary of the various styles.

Font Awesome
Font Awesome is a publicly available stylesheet that provides a wide range of vector-graphic icons
(Font Awesome, n.d). It’s not used as much as the other technologies listed here, but it is responsible
for providing the icons for both the menu bar and the ‘header’ section of venues, as shown in Figure
6.
Figure 6 - "Font Awesome" icons in action

Whilst it provides a nice effect, the application could live without it. It provides a nice effect, and as
in the case of W3.css is very small – a mere 26KB.

PHP
The server component is powered by PHP. It’s used in everything from connecting to the database,
to storing session data, to building the client-side HTML. The main file is index.php, which is 594 lines
long. There are three other PHP files, containing classes of their namesake – DatabaseManager.php,
Venue.php, and Review.php. The classes are represented in figure 7, a UML class diagram.

Figure 7 - The class diagram, with associations

The classes are all very simple. Review and Venue are essentially just ways to store the data loaded
from the database. DatabaseManager is somewhat more complex due to the fact that it’s responsi-
ble for handling contact with the database – this is elaborated on in the next section.
I make use of a PHP library named ChromePHP to log console messages – the appropriate files can
be found in the ‘lib’ directory.

Database Management – MySQL


MySQL is used to manage the database – I was originally going to use PostgreSQL as that’s the fla-
vour of SQL I’m most familiar with, but I switched to MySQL due to lack of native PHP support. This
section is really an explanation of the DatabaseManager diagram in figure 7.

Whenever contact to the database is necessary, a connection is established using the connect()
method. When the database operations are complete, this connection is closed using disconnect().
If it were not, the connection will remain open and an exception will be thrown when the session is
saved.
The member variables shown in bold are constants – as mentioned in Installation, these must match
the database.

loadVenueTypes queries the database to retrieve a list of ‘types’, executing the SQL statement:

SELECT * FROM Venues.VenueType;

There are only two fields in VenueType – “TypeID” and “Description”. The function parses through
the rows and returns an associative array in the format array[TypeID] = Description. The TypeID
value is a single character, and is used extensively in the application. The Description value is simply
what that ID represents. Restaurants, for example, are [‘R’] = “Restaurants”. The description is used
where the type of venue is referenced – such as in the review confirmation window (figure 5).

loadVenues queries the database for venues matching the specified type. Instances of Venue are
constructed, assigned to an array, and the completed array is returned. This is done by executing the
SQL statement:

SELECT * FROM Venues.Venues WHERE TypeID = '$venueType' ORDER BY


AverageRating DESC;

The results are ordered by rating. After the venues have been loaded, ordering is handled server-
side afterwards to void having to re-load them when an average rating is changed.

loadReviews queries the database for reviews for the specified venue. The results are parsed, in-
stances of Review are constructed and added to an array, and the completed array is returned. The
SQL statement behind this is:

SELECT * FROM Venues.Reviews WHERE VenueID = '$venueID' ORDER BY


StarRating DESC;

When constructed, the list is assigned to the venue using Venue’s setReviews method.

The remaining methods pertain to storing data, not retrieving it, and they’re all part of one process.
saveReview is called after the user submits their review. This method connects to the database,
starts a new transaction, and calls storeReview (which calls getReviewID to retrieve the new pri-
mary key) followed by storeRating. These methods return a similar value to saveReview, which was
mentioned earlier: a status – either ‘OK’, or an exception message.
If either of these calls fail, the entire process fails, the transaction is rolled back, and the offending
exception message is returned. This displays the error window (figure 6) to the user.
If both return ‘OK’, the transaction is committed and the function returns ‘OK’. This displays the con-
firmation (or ‘thank you’) window (figure 5) to the user.

Google Maps
The map functionality is discussed more or less fully in the introductory “What is Delve into Derby?”
section, so I shan’t go into too much detail.

I make use of Google Maps’ JavaScript web API to render a map of Derby, placing markers in to dis-
play venues where appropriate. This is done by loading each venue’s latitude and longitude from the
database – acquiring this information took a little data input, and was done so using Google’s ge-
ocoding tool (Google Developers, n.d). I could have done this remotely, but opted to do it myself so
there’s less performance impact and I’m certain the latitude and longitude is correct.

Challenges

What should I do?


Right from the onset, I met challenges with this project – I couldn’t think of a suitable idea that
matched the constraints imposed. I had very little experience in application development having
only ever developed games and game-related tools. I wanted to build an application that runs in
HTML, relies on a database, and makes use of a web service, but I could only get any two of these
factors.
After asking for suggestions, the basic idea that I went with was proposed – I developed it further.
Much of what I wanted to include didn’t make the cut, but the major parts did.

Database woes
Before development had begun, I’d created a database design and a PostgreSQL script to construct
the schema. I rented a virtual private network in the cloud (a ‘droplet’) through DigitalOcean, run-
ning Linux Ubuntu. I updated the installation and then installed the PostgreSQL server, configured it
to allow connections, and connected from my PC using pgAdmin III. I tried to connect to the data-
base through PHP on my web server, but was told that the relevant functions did not exist. I believe I
was simply missing the necessary library, but I switched to MySQL as its support is built into the lan-
guage.

I installed a MySQL server onto my droplet, configured it to allow connections, but I couldn’t connect
via the MySQL Workbench application or by my PHP code. I spent a few hours trying to sort this out
and then started exploring other options.

I then tried creating the database server through Microsoft Azure – both as a database server and on
a virtual machine, much like the droplet. After an entire day trying to sort this out and getting abso-
lutely nowhere, I gave up.

I created a clean Ubuntu installation on my droplet and tried setting up a MySQL server again, as a
last ditch effort. I had much the same results as the first attempt.

After that, I figured that I’d already wasted far too much time on this seemingly simple objective,
and started using a MySQL server on my local machine – it would at least allow me to develop the
application. I destroyed my droplet and deleted my various Azure resources.
Debugging
Due to the lack of a console in PHP, I found it relatively difficult to debug effectively. I had to use
echo statements to ‘print’ HTML so I could see what’s actually going on.

After a little research, I stumbled upon ChromePhp – a PHP library that allows messages to be logged
to the JavaScript console through PHP, assuming that Chrome has its extension installed. This works
as you’d expect, in the format:

ChromePhp::log(“Hello world!”);

I found this incredibly useful during development, simply because I could see what’s going on and
print things without dumping messages onto the application itself.

$_SESSION wasn’t saving


I had trouble using $_SESSION initially. I was storing values in $_SESSION, but on reloading the page
it was empty. I was using session_start() as required, and session_write_close() at the end of
the script.

It transpired that an exception was being thrown at the end of the script, but wasn’t being displayed
or conveyed to me in any way. The script was being terminated prematurely but it looked like it was
working as expected.

The exception was being thrown when I assigned the active instance of DatabaseManager – a data-
base helper class – to its appropriate index in $_SESSION at the end of the script. DatabaseManager
held an instance of PDO – PHP Data Object, which handles connections to the database – that was
actively connected to the database. The exception was thrown because this cannot be serialised.

I was only trying to store the connection in $_SESSION so the application would be faster and more
responsive. This issue led to an epiphany – why on Earth was I unnecessarily connecting to the data-
base anyway? It was a stupid idea. I stopped doing so, fixing both the issues with $_SESSION and the
sluggishness of the application. The database connection is now created only when necessary using
the methods – connect() and disconnect().

Conclusion
Creating this project was an experience. It involved utilising a number of technologies that I was only
passingly familiar with, and just generally creating something that was outside my usual endeavours.
I feel that I’ve learnt a lot. Now, I will be applying what I have learnt in creating this to a personal
project I’d like to create.
References
1. Aslam, S. (2011). Unable to connect PostgreSQL to remote database using pgAdmin. [Online] StackO-
verflow. Available at: https://stackoverflow.com/questions/1287067/unable-to-connect-postgresql-
to-remote-database-using-pgadmin [Accessed 14 Apr. 2016].
2. Egil, J. and Refsnes, B. (n.d.). W3.css. [Online] W3Schools.com. Available at:
http://www.w3schools.com/lib/w3.css [Accessed 26 Apr. 2016].
3. Gandy, D. (n.d.). Font Awesome, the iconic font and CSS toolkit. [Online] Font Awesome. Available at:
https://fortawesome.github.io/Font-Awesome [Accessed 28 Apr. 2016].
4. Google Developers. (2016). The Google Maps Geocoding API. [Online] Available at: https://develop-
ers.google.com/maps/documentation/geocoding/intro#Geocoding [Accessed 1 May 2016].
5. w3schools.com. (n.d.). W3.CSS References. [Online] Available at:
http://www.w3schools.com/w3css/w3css_references.asp [Accessed 26 Apr. 2016].

You might also like