Building Bespoke and Converting Legacy Systems with Laravel
The aim of this article is to blow my own trumpet a little bit and give a clear insight into my technical capabilities. The project I want to talk about is covered by an NDA so I can’t reveal the client but I can give you a rough idea of the challenges faced and how I overcame them. I’ve tried to keep the article easy to understand by not going into too much technical detail however if you do have any questions and want to pick my brains on any of the technical aspects please reach out on Twitter.
I’ve been working on the project for three years commencing in 2016 when we inherited the project from another agency after their sole web developer left the company. The original website was built using traditional ASP, with version two being 75% developed using OpenCart. I quickly took the decision that I wasn’t comfortable with OpenCart so took to rebuilding the site using Laravel.
Why ditch OpenCart? #
The site relies very heavily on bespoke functionality and to get this to work using OpenCart a system called vQmod was implemented. This is very ‘hacky’ way of extending the core code behind OpenCart. It’s basically a chunk of XML whereby you say I want to replace lines x to x in the following files with this chunk of code. It makes sense for small changes, but it started to get a wild with the amount of customisation required and also the load times of some of the page were extremely slow as a result (30+ seconds).
The Rebuild with Laravel #
When the decision to go bespoke (January 2017) was made the project was already two years down the line so it wasn’t an easy decision to make but it helps when you work with a client that trusts your abilities. Our deadline for go live was July 2017 giving us six months to plan and build the system. Luckily we could use 90% of the CSS for the front end, allowing me to concentrate on the backend of things.
The biggest challenge here was the database design and importing some 40,000+ product lines from their existing database (v1 of the website). Before committing to the table structure and relationships I spent a lot of my time figuring out how the products needed to stored in the database, not only in their current form but also making considerations future expansions.
Once the database design was decided upon, I could begin the code behind the website. This process involved creating all the usual endpoints and controllers you’d expect to see for an e-commerce site: category pages, menu system, add/removing to a basket, checkout via third party (PayPal, WorldPay), orders saved to a client account to which they would have access.
The biggest challenge was unlike many e-commerce sites the client required the product listings within each category to display in list form within a table. Each product can have any number of different price options and all of these needed to be displayed within one page.
Additionally, there are shipping rules that needed to taken into account such as depending on what products made up the order changed the cost for shipping, as well as accounting for overseas shipping.
New products are also added to the site on a regular basis. The client however wanted to release these in batches on a weekly basis. Here I made use of scheduled jobs in Laravel, this runs weekly to pick a selection of products to release. From this the weekly HTML email is created via a random selection of the selected items. These products are then automatically released to ‘go live’ on a Friday morning and a weekly email can be sent out to customer who have subscribed to the company’s newsletter.
In regards product images these are uploaded to Amazon s3 (40,000+). There is also the option to add watermarks to images before they are uploaded, this is handled via Intervention Image. This is a massive time saver in not having to do these individually before upload.
Laravel Updates #
The initial site was built using Laravel 5.4. The upgrade to 5.6 was fairly smooth aside from two main issues the first being the change to double encode HTML entities, resulting in special characters not being encoded correctly. Changes throughout the templates of the site fixed this issue.
The biggest issue however was that I’d opted to use a package to handle the Payment Gateways (OmniPay) mainly due to the tight timescales. This was no longer actively being developed and as a result was not compatible with the new version of Laravel. In hindsight and with new projects I’m now cautious about using Laravel Packages that aren’t actively maintained and would recommend and writing custom code where possible. For example the OmniPay package has now been replaced with our own custom methods.
Ebay API Integration #
As well as selling via the website the client also sells on Ebay. As you can imagine this brings the complexity of keeping stock levels in sync between the two platforms. Having taken the decision to go bespoke if we wanted this functionality we were going to write it ourselves.
Initially when first looking at Ebay’s API documentation things looked scary but after a good read of the documentation and setting up a test project I soon got to grips with the way that it worked. In simple terms you just pass a chunk of XML with certain properties set for things such as adding/edit items. An example where this is implemented is when an item sells on the website, the system sends a request to Ebay to remove item.
The second element of the Ebay API we implemented were Ebay’s Platform Notifications. These are events that you subscribe to on your Ebay store. In our instance we wanted to know when an item ended or was sold. Once subscribed to the event the site receives a notification every time an item is sold or is ended from which we can run any processes that are required to mark the items as sold on the website ensuring stock levels across by Ebay and the website are always in sync.
Additionally, the processing of Ebay orders using the old Access system was extremly slow taking up to ten minutes per order. This process is now reduced to less than 30 seconds. By pulling live Ebay order data into our system, complete with line items and shipping address a shipping note can be produced and printed with the click of a button.
Converting a Legacy Access system to Laravel #
Secondary to the e-commerce website side of the project, the client also had multiple legacy systems in Access;
- one for customer data
- a second that held customer data, stock and also carried out a series of day to day tasks such as printing letters/labels.
The ultimate aim was to deprecate these old systems and merge everything onto the web with our bespoke Laravel system (something that is still a work in progress). Once the e-commerce side of thing was stable work on this side of things commenced in Autumn 2018.
The biggest challenge here was importing 14,000+ customer accounts and related data onto the website system whilst ensuring all existing account numbers remained and keeping duplicate accounts to a minimum.
The system also required the ability to print address labels for sending out mailings for printed price list and other correspondence. This was achieved using PHPOffice this proved to be much quicker than using DOMPdf (PDF creator currently implemented within the system). Additional print requirements were the production of product cards for certain products, again these are created for Word using PHPOffice.
The Future #
As with all websites and applications this system is being constantly developed as we come across new functionality that is require, as well as general maintenance and bug fixes. The client is extremely keen automate as many processes as possible. Some things that are in the pipeline for development are;
- QuickBook API Integration
- MailChimp Integration
- Improved “offline checkout” for customers who phone to order
It is very difficult to summarise all of the technical workings of the system as it does now do a lot however hopefully it gives a flavour to the inner workings of a complex web system and shows what is possible when you build bespoke and how with the use of well planned out data and processes big time savings can gained on recurring business processes.
The key takeaways from this project and any other project for that matter is to properly think about what you are aiming to build and what it might need to do in the future.
Ask the client lots of questions to try to discover all the functionality that is needed;
- How do you do x?
- Do you need it to do x?
- Wouldn’t it be better to do x?
- Why do you need x?
- What is your ultimate aim?
Think like the client and their business. Put yourself in their shoes to try and think of things that they may not have considered. I find a lot of the time clients don’t know their own processes so it is up to you to try and unpick them hopefully preventing issues as systems develops over time.
Finally, consideration of whether you really need a package for certain functionality. Yes they will speed up your development time but it also consider the impact it would have if development ceased and it was no longer useable with your system – what impact would this have and is it easily replaced with an alternative?