The Ugly Croissant

Posted to site: 20/09/18

The Ugly Croissant pre­sented the op­por­tu­nity to learn the fun­da­men­tals of the web, fo­cus­ing on re­spon­sive de­sign. I used PHP to pro­duce a ba­sic con­tent man­age­ment sys­tem which could han­dle both recipes and blog posts, and im­ple­mented a tag­ging sys­tem to help or­gan­ise the con­tent. Throughout the process I worked closely with the client to get the de­sign right for her and her au­di­ence.

Technologies used

Development Approach

From the start of the pro­ject, re­spon­sive de­sign was at the top of the agenda. The client had al­ready amassed a fol­low­ing on so­cial me­dia and was seek­ing a web­site in or­der to grow her pres­ence and dis­play her recipes to her fol­low­ers. As such, the web­site had to be de­signed with a mo­bile first ap­proach from day one as the vast ma­jor­ity of traf­fic would be mo­bile. This was achieved through the use of the viewport meta tag, CSS me­dia queries and CSS grids.


TUC Home Page on a Mobile Device
TUC Home Page on a Mobile Device
Desktop vs. mo­bile lay­out

Research has time and again shown that fast [page load speed is vi­tal to de­creas­ing bounce rate](https://​www.thinkwith­google.com/​mar­ket­ing-re­sources/​data-mea­sure­ment/​mo­bile-page-speed-new-in­dus­try-bench­marks/) so this was an on­go­ing piror­ity through­out the pro­ject. It’s no se­cret that good pho­tos sell food, so in or­der to en­gage the largest au­di­ence pos­si­ble good qual­ity pho­tos had to be front and cen­tre and thus the web­site had to be light­weight and fast. Throughout de­vel­op­ment I con­ducted page load tests us­ing [Google’s Lighthouse tool](https://​de­vel­op­ers.google.com/​web/​tools/​light­house/). Moreover, in or­der to keep the web­site light­weight and flex­i­ble I im­ple­mented a cus­tom con­tent man­age­ment sys­tem to serve the con­tent quickly.

Whilst the blog only has one au­thor, it was still nec­es­sary to cre­ate a scal­able so­lu­tion to al­low for con­tent to be ef­fort­lessly pub­lished on the web­site. This is achiev­able with a sta­tic site through a smart nam­ing scheme and struc­tured file sys­tem. However, stor­ing the con­tent on a data­base and us­ing PHP to load the con­tent posed a much more ro­bust, scal­able so­lu­tion. Moreover, this would al­low for eas­ier im­ple­men­ta­tion of fea­tures such as recipe tag­ging, search­ing and com­ment­ing in the fu­ture. Also, us­ing PHP would help pre­vent re­peated code in the web­site, thus sav­ing work and mak­ing it eas­ier to change the site through­out de­vel­op­ment and in the fu­ture.

Workflow

From the out­set I used Git and GitHub for ver­sion con­trol, this pro­vided an in­valu­able tool for man­ag­ing the code­base for the site, es­pe­cially in the early days when both au­thor and de­vel­oper were work­ing to­gether on the site. Moreover, when I even­tu­ally started mi­grat­ing the site to use the data­base, this al­lowed us to main­tain a work­ing sta­tic ver­sion of the site along­side the main de­vel­op­ment, should the au­thor want to pub­lish that site ear­lier. Development was done largely on my lo­cal Linux ma­chine, run­ning XAMPP for a ba­sic lo­cal web server and us­ing Atom for text edit­ing.

Early Development

As this was my first web de­vel­op­ment pro­ject, I started out by cre­at­ing a sta­tic site us­ing ba­sic HTML, CSS and some JavaScript. This al­lowed us to de­velop both the aes­thetic de­sign for the web­site and the struc­ture be­hind the con­tent. We ar­rived at the ini­tial de­sign for the web­site, and de­cided that con­tent would be clas­si­fied as ei­ther a blog post or recipe. This gave me the frame­work around which I could build the data­base and server-side logic.

At this point, the web­site could have gone live; al­though it was miss­ing some fea­tures, the con­tent was dis­played al­most ex­actly as it would be in the fi­nal ver­sion. The web­site was cer­tainly not scal­able as pub­lish­ing a new post re­quired copy­ing and edit­ing pre­vi­ous posts into a new folder then adding the rel­e­vant links to other pages. However, the client had not yet fi­nalised the con­tent they wished to pub­lish so we de­cided to start de­vel­op­ment of the data­base and server-side logic.

Database Approach

After con­sid­er­ing the var­i­ous op­tions, I de­cided on us­ing PHP for the server-side logic and MySQL for stor­ing the con­tent. This web­site is not de­signed to pro­duce a large rev­enue so would likely be hosted on a shared host­ing plat­form. The ma­jor­ity of these plat­forms pro­vided MySQL data­bases and PHP with­out any ad­di­tional setup or cost so this was the clear choice. Moreover, PHP pro­vides easy, se­cure com­mu­ni­ca­tion with data­bases through the PDO ex­ten­sion which was used through­out the pro­ject and pro­tects against SQL in­jec­tion at­tacks through pre­pared state­ments. In ad­di­tion, the lan­guage is well doc­u­mented through the PHP Manual and the large, well-es­tab­lished com­mu­nity.

This ap­proach also en­abled us to im­ple­ment a tag­ging sys­tem for the recipes, al­low­ing users to more eas­ily search for recipes rel­e­vant to them. Implementing this sys­tem pre­sented a de­sign de­ci­sion as there were a num­ber of ap­proaches to take, each with their own strengths and weak­nesses. Phillip Keller has com­pleted tests on the per­for­mance of each of these ap­proaches which proved an in­valu­able re­source. Recipes are writ­ten rarely, there­fore the main fo­cus was on max­imis­ing per­for­mance for SELECT queries since these would be much more fre­quent and im­pact user ex­pe­ri­ence. Thus, based on the ex­pected dis­tri­b­u­tion of our tags, we de­cided on a three table schema; one for recipes, one for tags and one for tag-maps which list which recipes have which tag (named the toxi” ap­proach in the linked ar­ti­cle). Note, this is also the ap­proach used by Wordpress.

Pagination and Object-Oriented PHP

With all of the recipes and blog posts stored and tagged in a data­base, this al­lowed me to cre­ate a search page where users could search the site for recipes that in­ter­ested them. However, re­turn­ing these re­sults on one page would lead to long page load times and a cum­ber­some ex­pe­ri­ence for the user. To solve this is­sue, we needed to au­to­mat­i­cally pag­i­nate the re­sults from the rel­e­vant data­base query. Aware that this was a com­mon prob­lem that might arise on fu­ture pro­jects, I cre­ated a tool for pag­i­nat­ing re­sults from a data­base query. Using an ob­ject-ori­ented ap­proach, this tool is highly portable and can be in­te­grated into any site in the fu­ture. View the PHP Paginator on GitHub.

Object-oriented pro­gram­ming was a much more or­gan­ised ap­proach to writ­ing PHP, and tak­ing the time to write portable code such as this will def­i­nitely pay off in the long run. Within this pro­ject, the pag­i­na­tor class was used on mul­ti­ple oc­ca­sions to or­gan­ise re­sults from the data­base.

Admin Section

At this stage, a ba­sic form for writ­ing recipe and blog post en­tries had been cre­ated, but edit­ing and delet­ing posts, as well as adding tags, had to be done man­u­ally within ph­p­MyAd­min. Although the client was tech­ni­cally lit­er­ate, this was not ideal and cer­tainly not a long-term so­lu­tion. The next step of the pro­ject was to cre­ate an ad­min sec­tion for the web­site, which would be pass­word pro­tected and pro­vide full con­trol over the con­tent. To im­ple­ment this, PHP ses­sions were used to iden­tify logged in users and user in­for­ma­tion was stored in a MySQL table with pass­words salted and hashed us­ing PHPs stan­dard password_hash() func­tion.

To col­lect recipe con­tent, the new en­try form fea­tures three Markdown ed­i­tors us­ing SimpleMDE, al­low­ing the au­thor to tai­lor the in­tro­duc­tion, in­gre­di­ents and method of the recipe. Markdown was cho­sen as it al­lows the au­thor to fo­cus on writ­ing the con­tent, and pre­vents any is­sues aris­ing from ask­ing the au­thor to write in un­fil­tered HTML. This Markdown is con­verted into safe HTML by Emanuil Rusev’s Parsedown and the two for­mats are stored in the data­base. This al­lows the con­tent to be quickly loaded to the web­site, whilst al­low­ing for fu­ture edit­ing of the orig­i­nal Markdown.

One stand­out fea­ture of the user in­ter­face is the tag sys­tem; when pub­lish­ing a recipe or blog post, the au­thor is able to add tags to their post. This is ac­com­plished through an AJAX live search box which searches the data­base for pre-ex­ist­ing tags as the au­thor types. The first step was to cre­ate a PHP file which ac­cepts the query through the GET method and echoes a table of re­sults from the data­base. Then, when the con­tents of the search box are up­dated, a HTTP re­quest is made to this file and the con­tent re­ceived is em­bed­ded into the page. This pro­vides a seam­less ex­pe­ri­ence for the au­thor as there are no page re­loads, mak­ing tags quicker and eas­ier to add be­fore post­ing.


TUC Admin Section demo
Demonstration of the ad­min sec­tion

Lessons Learned

This pro­ject pro­vided a great op­por­tu­nity to de­velop my un­der­stand­ing of the fun­da­men­tals tech­nolo­gies of the web; HTML, CSS and JavaScript. Moreover, I had the op­por­tu­nity to learn PHP and MySQL which are fan­tas­tic tools for quickly cre­at­ing dy­namic sites ca­pa­ble of scal­ing to ac­com­mo­date more con­tent. Learning about the ba­sics of se­cu­rity was a valu­able ex­pe­ri­ence, as I had to en­sure the site was pro­tected against com­mon at­tacks such as SQL in­jec­tion and cross-site script­ing.

Working with PHP had its strengths and weak­nesses, the lan­guage of­fers ex­cel­lent in­te­gra­tion with data­bases out of the box, mak­ing it ideal for web de­vel­op­ment. The mas­sive com­mu­nity, and man­ual make trou­bleshoot­ing rel­a­tively pain­less in most cases. The dy­namic typ­ing of PHP al­lows the de­vel­oper to spend less time deal­ing with pedan­tic is­sues such as chang­ing the type of a sin­gle vari­able through­out an en­tire code base. However, sta­tic typ­ing makes for in­her­ently more rig­or­ous code which re­duces the like­li­hood of care­less er­rors at the cost of writ­ing ar­guably over-ver­bose code. Moreover, us­ing the naive ap­proach to PHP de­vel­op­ment of ba­sic scripts nes­tled amongst HTML, code can quickly be­come dis­or­gan­ised and dif­fi­cult to main­tain.

If us­ing PHP in a larger fu­ture pro­ject, I would at­tempt to use an ob­ject-ori­ented ap­proach from the start as it al­lows the de­vel­oper to fos­ter a more or­gan­ised code base which is more man­age­able as the pro­ject grows. Moreover, us­ing a PHP frame­work such as Laravel would al­low for swifter, more el­e­gant cod­ing, through greater con­for­mity to the MVC pat­tern which is pro­lific in mod­ern web de­vel­op­ment. On a sim­i­lar note, in or­der to cre­ate a more or­gan­ised style sheet, I would use a CSS pre-proces­sor such as SCSS for its nest­ing and logic. The front-end code­base of this pro­ject was in­ten­tion­ally small to re­duce the load on mo­bile de­vices so JavaScript frame­works were avoided. However, in larger pro­jects, more de­pen­dent on their front-end, the power of JavaScript frame­works makes them an at­trac­tive op­tion.

Update

We have since re­designed and rewrit­ten The Ugly Croissant. The whole site is new hosted for free on Netlify, us­ing Netlify CMS for con­tent man­age­ment.