Lucid MVC – Development Update 1

Development Update 1 For Lucid MVC

This is a small update on Lucid MVC. Although I haven’t started work on the FormHelper or Database classes yet, I have made several improvements, and fleshed out the demo site (which will be included with the release).

A contact form page

A contact form page

Most of the work has been on improving form validation, which has been further simplified and made more flexible;

It didn’t really make sense to have the validators created from within the controller, and due to the way validation worked previously, it had to be done after a call to Model::load();. Validators can now be added anywhere within the Model and at any time, which also allows for ad-hoc validation if you want to add/remove validation at any time during the Model’s life-cycle.

With that in mind, validators can be removed simply by passing in the same parameters that match the validator that was added via Model::addvalidator();.

So, if we wanted to remove email validation, we could, for example, remove it before validating our form within the controller;

This is just a simple example. You might wish to remove validation based on user-submitted data. For example, if the user wanted to skip a part of the form, or if the user only had to fill in at least one of two form inputs, you could check if one input was filled in, then remove the “required” validator from the other.

Helpers

Another area I’ve been working on are the Helper classes, so far we have;

  • AlertsHelper – for rendering Bootstrap alert messages
  • SessionHelper – various methods for handling sessions
  • UrlHelper – various methods for generating links (absolute, relative, etc..)

As well as the FormHelper class, I’ll also be creating a DebugHelper for logging output to file/screen.

Configurations

The final area I’ve been working on has been the configuration settings within the project, and how best to represent them. Two of the more common approaches are arrays and .ini files, however both would require additional coding to require them automatically where needed, or additional code to call them.

In the end I decided to use a static class representation;

This made the most sense, given that Lucid MVC requires in classes automatically. Configuration settings can be included anywhere within your project, just by accessing the static class property. For example;

You can of course create your own configuration classes if you wish. The private class constructor is just there to prevent the class from being instantiated.

Other ideas

I’m also considering adding in some of the following;

  • Events/Listeners – Add events to Models/Views/Controllers at certain execution points
  • Dynamic Models – the ability to create new model attributes dynamically outside of the class
  • Modifiers that can change/convert data before/after it’s loaded into the model using callables.

Lucid MVC – A light PHP framework for small online projects

Building an MVC framework from the ground-up

Having worked with several PHP MVC frameworks now (Laraval, Nova Framework, Yii2, Joomla), I thought it would be a rewarding challenge to develop my own framework, based on what I liked about these frameworks, and what benefits me as someone who works with PHP frameworks.

The main goals of this project are;

  • Light MVC framework that’s fast to learn
  • Easy to work with, with minimal boiler-plate code
  • Fast form-building
  • Easy form validation
  • Automated URL routing
An early screenshot of the Lucid MVC Framework

An early screenshot of the Lucid MVC Framework

With that in mind, I’ve been working on Lucid MVC; a light PHP Model-View-Controller framework designed for small projects, but with enough features and functionality to avoid repetition and too much boiler-plate code. For example, there is no manual URL routing to speak of, so URLs are automatically translated to direct to the correct controller, passing any additional parameters to the controller if the controller method accepts them.

For example, the URL:

library/books/author/richard-dawkins

Would instantiate the libraryController, run the books method, and pass in the parameters “author” and “richard-dawkins”. The route will only be successful if the controller method can be called successfully, otherwise, the user will be redirected to the ErrorController, telling them the URL they have reached is invalid (our standard 404 “page not found” page). If the controller allows for optional parameters, then they can be omitted from the URL, and the default parameters will be used. This allows for flexible controller paths, leaving it up to the developer to handle any further validation if they require it.

Like Yii2, a layout template can be applied to the entire view, rendering the view content inside it. Different layouts can be applied in the controller before a view is rendered, or the default layout can be used.

Views themselves are fairly straight-forward. Model attributes, variables or other values are passed to the view via the controller, and can be accessed like normal variables.

Contact Form Controller

This is the controller for the contact form page at the beginning of this post. So far, models can load POST data (assigning it to the model attributes), store data, and perform data validation through a growing-list of validation filters.

Controllers can render views, and redirect to different routes. Controllers also have some basic functionality for dealing with web requests such as checking for POST data.

 

Automated PHP file-inclusion

Because this is designed to be an MVC framework for small projects, the framework uses a custom autoload function to automatically include any PHP files when you call a new Class. So, rather than using Namespaces, every PHP file will be included automatically at the moment it is needed. For large-scale projects this might cause problems with naming conflicts, but for a library that’s designed to be quick to use and build with, it’s perfectly serviceable.

What’s next

The next two features that need to be implemented are the Database class, and the first of the Helper classes to aid in quick form-building. The Database class will be a wrapper class for PHP’s PDO extension, providing easy-to-use methods for standard database CRUD operations, and will handle variable binding automatically for the highest security and less coding.

The FormHelper class will aid in building HTML forms programmatically, automatically handling the form action, various input types and options, and binding the model attributes to the form.

Once the FormHelper and Database class are complete, I think the project will be complete enough to release on GitHub for anyone who wishes to use it.

Building an Online Retail Store – Update 4

The store is almost in a functional, usable state. I still have several extensions to install, which deal with the following;

– SEO Module: SEO friendly links, auto meta data generation, and more
– Extended Coupons: More functionality, time limits, auto-generated banners
– Extended searching: AJAX auto-suggestions in the search bar, ala Google
– Enhanced Shipping – Custom creatable shipping methods, based on multiple rules/options

With these in place, the store will be in a state in which I’ll be happy with using. Before installing these final modules, however, there is one more extension I need. Unfortunately, despite extensive searching, I’m unable to find what I’m looking for. The built-in order display system in OpenCart is extremely basic. You have to go into each order manually to see what has been ordered, and navigate multiple tabs to see products, customer address, order status, and so on. This is extremely slow and inefficient, not to mention very difficult to manage. When dealing with the shipping of customer orders, this is going to take up an inordinate amount of time. With no way to filter orders by status, or a quick way to pull customer data or product purchases, it’s just not feasible to use for shipping orders.

Because of this, I need to develop a custom order picking script. It doesn’t need to be overly complex at first, but it does need to be well-designed enough to be extensible in future. It needs to display orders sorted by date, and filtered by order status. Additionally, each order needs its own “complete order” button, which will change an order’s status from “processed” to “complete”, thereby removing it from the processed orders list. A timestamp may need to be placed in the order notes of when the order was shipped/completed.

The order picking list needs to display the customer’s order number, their name, address, purchases, including product name, model number, and purchase price. The available stock quantity needs to be displayed next to each product. The data needs to be formatted into tables, as to be easy to read.

One task will be in writing the necessary MySQL queries to retrieve all the data. For ease, this will comprise of three queries; the first will obtain the customer orders, based on order status, and auto-arranged by date. The second query will obtain the product information for each of these orders. The third query will update each order’s status. The queries will need to be written in such a way that any part of the query that is likely to change will be inserted as a variable, and then later linked to any forms or buttons that may be added at a later stage for filtering on orders or updating them. A drop-down list to filter orders by status is highly likely, but this can be added later. Beyond that, being able to filter orders by date range or overall product availability may be advantageous, but not a priority initially.

The table formatting code could be written as procedural inline code, but it makes much more sense to create a table-generating utility class, which will be easier to manage, and flexible enough to be re-used in future. This class can be generalised enough so that I can determine the number of columns, the number of rows, and insert the data row by row, building up the table until I’m finished with it, then move on to the next order. Most of scripting time will be spent in creating the table utility class, but this doesn’t require the database data beforehand, so I’ll likely work on this first, and create some mock orders through testing before I create the main picking list script, as I want to be able to work on it from start to finish without having to take time away from it to work on the table class.

Building an Online Retail Store – Update 3

I decided to opt for a relatively low cost extension to import my products into the database via CSV, rather than write an entirely new product importer from scatch. For the most part, it does everything I need it to do. I had to write another small PHP script to format the CSV feed to some of the product importer’s specifications though, as the importer only has one secondary image field, but the field does accept multiple image locations split by a custom delimiter. With the amount of secondary images and products I had to import, it was quicker to write something that would combine all the secondary images into a single string split by the custom delimiter, and insert an additional column into the CSV file. As I’ve done extensive work with PHP and CSV files in the past, I already had most of the necessary functions.

The products have now been imported into the website, but they will require some manual editing, as the descriptions provided by the product feed weren’t html formatted.

Today I’ve been looking at the shipping options for the store, and I’ve finished setting those up using the built-in “Weight Based Shipping” module in OpenCart. It’s a little too basic for my needs, though, so I’ve already picked out a suitable extension that will provide additional flexibility, which I’ll install tomorrow.

I’ve also fixed two major issues that I’ve had with OpenCart 2.0. The first problem was with installing new extensions. I was constantly getting “method not implemented” errors every time I tried to install an extension from a zip file. The problem turned out to be with how OpenCart handles uploads. If you don’t configure it to use FTP, it can’t handle zip files. I got around the problem by using a small extension that bypasses the need for an FTP connection.

The second problem was with not being able to modify customer orders, which meant I wasn’t able to change an order from pending to processed. This problem was a little more difficult to figure out as the error message wasn’t particularly clear;

SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data

It turned out to be a problem with the default .htaccess file that was created in the root of my store’s installation directory. Removing it fixed the problem.

I have a few more extensions left to install and configure, but once that is done, I can focus on the product descriptions, and start testing the store fully by placing a few orders using Paypal’s sandbox mode.

I’ve already decided on a ticket support system for the store. I’ve decided to go with Hesk, which I’ll be manually installing for my customer support system. It was either that, or osCommerce, but as I’ve used osCommerce before, Hesk looks like a much better alternative by comparison, with more features, so I’ll install that fairly soon.

Building an Online Retail Store – Update 2

I’ve been looking at what extensions I’ll need for my online store. A good SEO module is unavoidable, as I need SEO-friendly urls for product links and easy access to meta data, as well as the ability to generate it. I’ve found just the extension I need that does all this, so I’ll be purchasing it soon. The second extension I’ll be getting is for improved search functionality. Auto-complete suggestions, much like google has when typing in a search, is pretty useful for product searching, and this is what the second extension will do. After that, any further extensions will be optional, but I feel these two are absolutely essential for any modern online store.

I’ve reinstalled the store on a new domain, so I’ll just use the current one for database testing/breaking. I’m making regular backups, as although I haven’t broken anything (yet), anything I do break may be irreversible. I’ll be using my test store for product importing until I’ve perfected my import system.

I’ve added Paypal as a payment option to the store, and I’m considering whether to also use Paypal as a Credit Card Processor, or to install a separate payment system to handle Credit Cards, such as SagePay. The latter would incur a small monthly cost, whereas Paypal charge you fees, so the sensible option would be to use Paypal to begin with to keep overheads to a minimum, and then consider switching to a system that charges monthly when the costs of doing so are less than the fees Paypal charge for Credit Card Processing.

I’ve enabled CloudFlare on my online store, which means part of the website will be stored “in the cloud”. Basically what this means is that CloudFlare stores a cache of the pages of the store, and shares some of the bandwidth load. This, theoretically, results in better load times and it should definitely result in reduced bandwidth. My only reservation with it so far is that if I make any changes to the site, in order to see those changes, I have to manually submit the page url to CloudFlare so it flushes its cache of the page.

You essentially have two copies of the website. Your copy, and the copy on CloudFlare’s servers. It’s not a good idea to have it enabled when you’re making a lot of changes to your website. You can force CloudFlare to re-cache your entire website, but this is slow, and will eat up your bandwidth. For now, I’m going to disable it, and re-enable it before the website launches. Overall I think the benefits are worth its use, especially when my web hosting provider includes CloudFlare with my hosting package at no additional cost, so I may as well take advantage of it, if only to reduce my monthly bandwidth usage.

I’ve also set up a completely new store theme. It’s clean, and very easy to navigate. I’ll spend some time tweaking the layout after I’ve imported all the products, which is what I’m currently working on.

OpenCart, unfortunately, doesn’t natively provide an extension for the bulk importing of products, and the free extension I tried seems to be broken in version 2.0.1.1 of OpenCart. This leaves me with two options; buy an extension, and hope it’s flexible enough to map all the product specifications and images, or write my own script in PHP to import the products in bulk. I’m of the opinion that the latter would be the best approach, as although it may initially take longer to have a workable solution, it will allow a much greater deal of flexibility in future, should I need to add more products. In the long run, that is what will be most beneficial.

I’m currently working on obtaining all the product images for the products I’ll be listing in my online store. I’ll be selling PC components, fans, computer cables, CPU coolers, mice, keyboards, and products of that nature. Before I can work on the main product importer script, I have to obtain high quality images for all the products, which I’ve written a separate script for. The process of obtaining the images will be in two stages;

1) Run the script to find and download the product images, putting these links in the product feed file for use later in the script for importing products into the website
2) Downloading all these images in bulk from those links

I’ve already written code to accomplish step 2 as well.

As you can see, writing scripts on the fly to accomplish tasks that would otherwise take considerably longer or be prohibitively expensive on a small budget is extremely advantageous. Of course, not every problem is best solved by writing a script, so one must always consider the time, the cost and reward of doing so.

Building an Online Retail Store – Update 1

I decided to avoid the Softaculous Script Installer that comes with my cPanel, and downloaded and installed OpenCart manually from their website instead.

It was a relatively painless experience. First I created a sub-domain for my store, then I installed the files to the FTP location associated with the new sub-domain, created a new database for the store, followed the installation instructions, and that was pretty much it.

http://www.store.coderiff.com/

Naturally, at the time of making this post, this is just a fresh OpenCart installation. I’ll probably experiment with changing the theme and installing extra extensions first as I familiarise myself with OpenCart. I’ll likely move this over to a new domain once it’s in any kind of fit and usable state, but for now, I have a usable website to write scripts for.

I’ve shortlisted a few domain names, as I’ve already settled on a product range should I ever decide to launch the store. There’s a lot of work that needs to be done before even considering that, though. If I ever decide to launch it at all, that is.

For the moment, I’m keeping the store in maintenance mode. Wouldn’t want anyone to think this is an actual live store. The site right now looks identical to this demo from OpenCart’s website. I’ll bring the site back up once I figure out how to disable registration.

Next I’ll create some dummy orders to see how they’re stored in the database orders table, and see how much work will be involved in importing and creating several hundred products from a spreadsheet.

Building an Online Retail Store – Development Log

These logs will mainly outline my progress as well as the steps required to manage multiple online retail stores via a single database, using a custom-designed series of systems to automate a lot of tasks that would be otherwise take up too much manual labour.

These include;
– Automating order imports
– Automating order tracking updates
– Automating stock levels
– Automating pricing

To handle this, a set of systems need to be put in place that manage the stock levels, prices and orders across multiple channels, and store them in one place. One solution would be to rely on systems already developed such as ChannelGrabber or ChannelAdvisor, however there are disadvantages to this, in case of problems with those systems, and being limited to the tools those systems provide. Instead, having a set of systems in-between a system such as ChannelGrabber and OpenCart to manage stock levels will allow a greater level of control, while maintaining the use of the functionality of both, and avoiding creating a single dependency on one system.

The store will use a central database to manage stock levels and pricing across multiple store channels, and act as a central storage for pricing, stock, orders and customer data. So, the overall aim will be a centralised management system that can manage an online retail store, and additional shop channels such as Ebay, Amazon, Rakuten, and be expanded upon in future. A lot of the code work has already been dome, but as these systems were built previously for an X-Cart website, the database script will need to be modified to conform to the database structure used by OpenCart. I’ve also also written an order importer that can import orders from ChannelGrabber into a database, but again, this was designed for X-Cart, so this will also need to conform to OpenCart’s database structure.

However, before all of these things can be looked at, I must first install a test version of OpenCart so I can take a look at the database stucture. The first script I may need to write would be one which will turn a .csv product feed into products to populate the store with.