AbanteCart Architecture Overview

Here you will find explanation for the architecture of AbanteCart open source eCommerce, directory structure and how all subsystems interact and used.


Directory Structure

The main category you will see after opening AbanteCart distribution archive is public_html. Below are the files/directories inside public_html that represent AbanteCart public site directory structure. Most important directories and files are shown and linked to GitHub repository for convenience. NOTE, not all directories/files are covered here.

AbanteCart Directory Structure
  • Expand all
  • Collapse all
  • public_html - AbanteCart public files
    • admin - Administration section files
      • controller - Admin section controllers
        • common - Commonly used admin controllers
        • pages - Admin pages controllers
        • responses - Admin response controllers
        • ... - more
      • model - Admin section models dealing with data manipulation
      • language/english - Admin section language XML files
        • english.xml - Main language file available in every admin page
        • ... - more
      • view/default - Directory for template related files
        • template - Directory for all admin template files
        • javascript - Admin javascript files
        • stylesheet - Admin stylesheet files
        • ... - more
      • index.php - Empty file / security protection
    • core - Core PHP classes and functional files to handle AbanteCart functionality
      • lib - Library files
      • engine - Core engine classes
      • helper - Files with supporting php functions
      • init.php - Main INIT files loaded at start for every page
      • ... - more
    • download - Working directory for storing download files
    • extensions - Directory to install and keep extensions for AbanteCart
    • image - Directory for static images used in AbanteCart
    • install - Single use installation folder. Folder should be removed after AbanteCart is installed.
      • abantecart_database.sql - Database definition file (DDL)
      • ... - more
    • index.php - Main index php files for AbanteCart application
    • php.ini - Custom PHP ini configuration file.
    • resources - Working directory to store resources added to application
    • robots.txt - Search engine control file
    • static_pages - AbanteCart static pages (error page)
    • storefront - Storefront application files
      • controller - Storefront controllers
        • common - Commonly used storefront controllers
        • pages - Storefront pages controllers
        • responses - Storefront response controllers
        • ... - more
      • model - Storefront section models dealing with data manipulation
      • language/english - Storefront section language XML files
        • english.xml - Main language file available in every admin page
        • ... - more
      • view/default - Directory for template related files
        • template - Directory for all storefront template files
        • javascript - Storefront javascript files
        • stylesheet - Storefront stylesheet files
        • ... - more
      • index.php - Empty file / security protection
    • system - Working system folder to keep system working files
      • cache - System cache files
      • logs - System log files
      • config.php - AbanteCart configuration file
      • ... - more
    • task.php - Task engine driver file
    • .htaccess - Custom Apache configuration file
  • install.txt - Installation Instruction.
  • LICENSE.txt - Open Software License ("OSL") v. 3.0.
  • release_notes.txt - New Features, improvements highlight and history works log

AbanteCart sub-systems

Below diagram shows layers and sub-systems in the AbanteCart:

Application areas and modules

MVC AbanteCart is built based on MVC concept. MVC stands for Model View Controller. In AbanteCart we also introduce dispatcher to concept of MVC. Dispatcher is in charge of running controllers in a set order and manages parent children processing between controllers. Fist controller in AbanteCart runs as a page or response controller. Others controllers can only be included and run as children of above two main controllers. This is done to prevent unauthorized execution of controllers.

Page controller - this a main parent controller that is building page content. Layout class is loaded for this controller to build page elements based on set layout. See layout section

Response controller - This is any first (main parent) controller that do not have a special layout and just provide data response. Example of this controllers can be AJAX response, XML Response, RSS feed, JSON, etc.

Below is the diagram to illustrate MVC process in AbanteCart.

Children Controller: These are children controllers that can only be loaded from any other controller and can not be accessed directly from the browser. These controllers can perform any operation, load other children controllers and process any template.
On start (construct), any controller loads corresponding model and language set that are with the same route (name) as controller.

Model: These are the modules that handle data load and management that corresponds to given controller. Each controller auto-loads corresponding model . For instance, for controller catalog/product there will be catalog/product model loaded automatically once the controller is loaded (initialized).

Languages and translations: AbanteCart language system is based on language translation saved in the database. Translations are grouped to sections that can represent given controller, page or section in the code. Each group needs to have unique identifier, for instance, product/category Initial translation entries for the languages are stored in XML files that are provided at installation. After installation all translation values are transferred to the database for further use in the system. XML Files are only used for initial load and resetting translations to default values.

Below diagram explains the process flow for the Language text depending on the action.

Database: AbanteCart is primarily set up to use Mysql database. You can see the database structure below that can give you an idea of types of data, tables and relationships used in the application.

Below diagram shows Database Relationship:

Layout: In layout we set a combination of elements or blocks on the given page. Blocks and elements are represented by controllers, models and views or templates (MVC) for each instance of the block or element. Any storefront page in AbanteCart needs to have a layout. Specific layout can be set to any page. If no specific layout is set default layout will be used. Layout can be stored in the database or set in the code. Layouts are set per template and will be reloaded if different template is selected.

Template: AbanteCart supports multiple templates for storefront and control panel. Templates can be set in the settings section of the control panel. Template files are loaded and processed by view class with the data loaded from model and controller management.

Blocks: These are smaller scope MVC sets with separate controller, template and/or model. Blocks are elements that can appear in the template in a special location (top, bottom, left, right, center, etc). AbanteCart can have 2 types of blocks: Static and Dynamic. Static Blocks - added in the particular part of main controller code as children. Dynamic Blocks - Blocks that are linked to the particular placeholder and parent controller with database setting of layout class. See Layout ...

Forms: In AbanteCart we introduce concept of FlexyForms, flexible way to set up forms in the application. Using FlexyForms you can configure any type of form with any type of fields quick and hassle free. This is very handy for creating extensions and quick forms management in the admin. FlexyForms are completely based on the settings loaded in the database and do not require code adjustment. In addition to FlexyForms AbanteCart offers blend of AForm and AHtml classes to provide unified interface to build regular forms in the code.

Dataset: Dataset offer quick and worry free methods to handle data without dealing with SQL and creating specific database tables. Data can be handled via easy dataset class methods. Dataset can be used in extensions to store relatively small data sets that do not require extensive relationships and transactional data records.

Resource Library: AbanteCart equipped with flexible and convenient way to store, manage and map media resources. System can handle media files or any other files or HTML codes that needs too have association to product, category, brand or any other data resource in the application. Simple example of the media file is image that can be mapped to one or many products or categories.

Extensions: AbanteCart is build based on flexibility and expandability in design. To allow expandability, there is an extension concept built into the core of AbanteCart application. This allows to add virtually any feature or service to AbanteCart and this is very important in current dynamically changing technology environment. Extension is a set of files and configurations that builds a plugin module. Extensions are located in one directory and all extension related file are located under one directory with corresponding extension name.

Caching: AbanteCart is set up to be fast performing eCommerce solution with optimized resources use and execution time. To achieve great performance AbanteCart utilize caching of commonly used database queries and requests. Upon changes in this areas in the control panel the cache for this section is automatically reset.

Messages: AbanteCart equipped with the notification system, that enables merchants to get notifications about their AbanteCart eCommerce activity. These messages are available in the control panel of AbanteCart upon login or in the messages section. Messages give you dynamic information about AbanteCart updates and upgrades, critical errors happened on your site, low stock notifications and other information. To communicate the error, warning and notices to administrator and users, AbanteCart utilise a message concept with help of AMessage class. Primarily purpose of this class is to pass the massage to the control panel users and make them aware of the activity and updates in the system. This system is configurable to the user desire and easily assessable in the code.

Debugging: To help and improve development process for core and extensions where is ADebug class available that can provide comprehensive details about the page load and execution process. This system is configurable to the user desire and easily assessable in the code. In addition, visual debug is available to help debug blocks and controllers loaded on the pages for the template.

Dynamic Menus: To offer more flexibility to navigation management a number of methods offered to control the menu item for the AbanteCart. Both Storefront and Control Panel (admin) utilize dynamic menu system that is stored in the Dataset. Menus can be edited at extension installation stage if particular extension requires to add new page to navigation menu.

User Friendly Control Panel: In the control panel (admin) of AbanteCart uses unique approach to display, list and edit of the data. To list data in Control Panel pages, AbanteCart utilise jqGrid (developed by Tony Tomov, [1] ) based on jQuery. This approach is unified and applied on all pages that use data listing. See below how grid controller can be used to manage any data in the cart. On the edit pages of AbanterCart control panel there is a unified approach to saving data. Most of the data elements can be saved individually to bring best customer UI experience. To improve UI experience even more, all the fields that are eddied are highlighted for convenience. User can see what is edited and avoid mistakes before saving.

Data Migration: AbanteCart helps existing eCommerce store owners to take advantage of the platform and migrate to it very quick and efficient. With offered migration tools, data can be transferred from third party eCommerce applications into AbanteCart in a matter of minutes.

Application Core

There is a core directory with engine and library sections in the AbanteCart architecture. These are the main components of the AbanteCart. Engine files represent the primary functional classes that organize execution flow and rendering of the result. Engine processes the controllers, in set order with help of dispatcher and connect it together with models and views . Libraries contain set of methods (routines) to help and support control over the engine and data management. In the libraries you can find classes that deal with processing translation (localization) exceptions and error handling, sessions, debugs, database and much more. We intend to keep AbanteCart with unified, clean and easy to use interface to all the engine classes and libraries. Functions are named base on their intention and produced result. In addition to standards, we also focus on providing flexibility and robustness to the interface. Data can be managed with direct access or via interface methods or with batch XML Load.

How controllers interact. There is always a main controller present in AbanteCart on every page load or request. Only 2 types of controllers can be loaded. These are page and response controllers.

Page controller - this a main parent controller that is building page content. Layout class is loaded for this controller to build page elements based on set layout. See layout section

Response controller - This is any first (main parent) controller that do not have a special layout and just provide data response. Example of this controllers can be AJAX response, XML Response, RSS feed, JSON, etc.

Other controllers are children for the above two main controllers. Children can be included statically in the code or with use of dynamic layout system loaded from the database. Dynamic layout system is only available for page controllers and organize elements to be displayed on the page and controllers to be loaded for that. Children controllers are processed in the order they assigned and return display result the the parent controller. This can be imagined as building Lego, where each peace is a controller that is processed individually and put together by dispatcher class into final Lego puzzle.

Static child controllers can be added inside any controller with example code:

copy
		$this->addChild('common/menu', 'menu', 'common/menu.tpl');
		

Dynamic controllers can be added with appropriate addition to the layout_block database that is explained later in extension section.

In addition to children controllers you can request dispatcher to run a new controller that can be executed separately. Main difference from child controller is in the way it is ran. Newly dispatched controller can accept arguments and most important it can be run with caller controller terminated. This can be done as redirect to different controller or page. You can dispatch new controller and capture the output passing it back to prior caller or just use the output internally. See examples:

1. Dispatch new controller and exit (redirect execution flow)

copy
		

public function main() {
….
//Instantiate new dispatch
$new_dispatched_controller = $this->dispatch('common/template_debug', array());
    return $new_dispatched_controller;
    //After return new controller will be run and we exit the current one.
}
		
		

2. Dispatch new controller and capture result (act like a regular child)

copy
		

public function main() {
….
//Instantiate new dispatch
$new_dispatched_controller = $this->dispatch('common/template_debug',
array(
	‘arg1’ => ‘value’,
	‘arg2’ => ‘value’
));
    $output = $new_dispatched_controller->dispatchGetOutput();
}
		
		

Global Data Structures and methods

Global structures (classes, functions) and how and where to use them. AbanteCart utilize one central location (registry) for all global structure and class instances. Registry is automatically available in controllers (set in based controller class) and can be accessed with $this->registry . If you use some other non-controller file you can get local instance of the registry with line below:

$this->registry = Registry::getInstance();

To have shorter access (from $this->registry->document to $this->document ) you can add below “magic” functions.

		
 public function __get($key) {
  return $this->registry->get($key);
 }

 public function __set($key, $value) {
  $this->registry->set($key, $value);
 }
 		
 		

Other global classes that are part of the registry:

This class stores data for head of the current page. Using this class methods you can manage meta tags and breadcrumbs. Check ADocument class for available methods. All data set in the ADocument class is store throughout execution and set to display at the end. Thus, this data can be effected in any controller.

$this->document, $this->registry->document

This is the class that provides access and control to the session data Example:

$this->session or $this->registry->session $this->session->data['stored_data']

This is the class that provides access to the request data and contains sanitized $_GET, $_POST, $_COOKIE, $_FILES and $_SERVER

$this->request or $this->registry->request

Class containing extensions details on running AbanteCart

$this->extensions or $this->registry->extensions

ALoader class provides interface to load models, language modules, configurations, etc. Once loaded data made available and accessible in global structures.

$this->load or $this->registry->load

Global access to HTML interface is provided to build and display HTML elements.

$this->html or $this->registry->html

Global access to configuration values. These are settings loaded for selected store id (0 store by default)

$this->config or $this->registry->config

Global access to database interface. Connection is already established in class constructor

$this->db or $this->registry->db

Global ALog class with interface to write to AbanteCart log file

$this->log or $this->registry->log

Global ALayout class with interface and data access to current page layout. This is used for storefront pages layout construction.

$this->layout or $this->registry->layout

In controller’s local data and structures, there is an automatic access to all registry global objects listed above. In addition, there are local objects that can be automatically accessed once base controller class is extended.

AView class that is in control of building the final output of current controller.

$this->view

This is a unique instance ID for a given controller. Since there is a possibility of same controllers be loaded and run in the same page multiple times, we need to identify each controller unique instance. This instance ID is set on controller class creation with ->new() method.

$this->instance_id

This is aa access to route string that identifies the name (rt) for the given controller. The route (rt) is also a partial directory path to the controller. It looks like this: pages/catalog/product

$this->controller

In case of nested controllers, we need to identify child to parent relationship. Most controllers are children to some main controller (page or response). This variable contains reference to parent controller object. This way children can have access to some interface and data of parent controller. This can be used to pass common parent controller data to all children . If you have data set up in parent controller with public scope, it will be available for children.

$this->parent_controller $variable= $this->parent_controller->data[‘variable_name’];

This is an array with all children references for given controller. Last child controller will not have any children controllers.

$this->children

See values in arrays or classes

To see detailed of any variable, array or class instance, you can use built-in echo_array(); function. Careful to echo full registry or nested structure as it can stole your browser. You can use debug methods to save output to file.

Error handling and AbanteCart Debug

AbanteCart offers sophisticated mechanism to handle errors and debug code.
Error handling controlled in admin -> system -> settings . Click System tab - here you have controls for error logging, debug info and debug level Following settings is available:

Display Errors:
Log Errors
Show Debug Info
Debug Level:
Level 0 - no logs , only exception errors
Level 1 - errors and warnings
Level 2 - #1 + mysql site load, php file execution time and page elements load time
Level 3 - #2 + basic logs and stack of execution
Level 4 - #3 + dump mysql statements
Level 5 - #4 + intermediate variable

Depending on these settings you are able to track program flow
If you want to debug some piece of code, you should surround it with checkpoint functions. Example:

		
AC_Debug::checkpoint('dev_checkpoint start');
.
.
some code
.
.
AC_Debug::checkpoint('dev_checkpoint end');
 		
 		

On dev_checkpoint end you could see something like this:

Example of debug level 4 checkpoint: - Memory: 7,872 (1,752,352) - Files: 0 (44) - Queries: 2 (9) - Time: 0.0032 (0.0111) Time File Line SQL 0.00076 Z:\home\projects\www\ac\core\lib\language.php 98 SELECT * FROM language where code='en' 0.00058 Z:\home\projects\www\ac\core\lib\currency.php 13 SELECT * FROM currency These means that - program allocate 7,872 bytes of memory since previous checkpoint ( total 1,752,352 bytes ) - included 0 files since previous checkpoint (total 44 included) - run 2 sql queries - spent 0.0032 sec on execution and below you see sql queries with info file, line etc.

There are 3 classes to work with errors
AException - use it in case of fatal error. execution is terminated in this case AError - use it in case you want to let user know that there is an error, but it is not fatal AWarning - use it to warn user

AException Usage

throw new AC_Exception(AC_ERR_LOAD, 'Error: Could not load library ' . $library . '!');

AC_ERR_LOAD - an error code, mean problem with loading some resources You could find all error codes in core/lib/exceptions/exception_code.php
Exception message will be either logged or saved for display. User will be redirect to /error/index.php - separate section with minimal class includes.

AError and AWarning Usage

AError class has methods - toDebug - add msg to debug log - toLog - write to log - toMessages - add to AbanteCart messages system - toMail - mail error message to store owner

$err = new AError( $msg, $code ); $err->toDebug()->toLog(); // or just $err->toDebug();

Code is an optional parameter and needed to describe message title You could find all error codes in core/lib/exceptions/exception_code.php In extension we could add new code error and add error description like

define('AC_ERR_ADDON', 9900 ); $error_descriptions[AC_ERR_ADDON] = 'some addon error';

AbanteCart Messages

AbanteCart offers message class that can handle information (massages) passed to the next page (result page) or stored to the database to be recorded and passed to control panel users and store admins. Admins can see messages and manage them in the control panel of AbanteCart. Messages can be of 3 types, Critical, Warning and just informative or notice Message class can be instantiated at any part of application code and extensions.

$registry->set('messages', $messages);

later on you can access it via registry object Message class has following methods - saveNotice($title, $message) - saveWarning($title, $message) - saveError($title, $message) these methods add message to db for further display

- saveForDisplay($title, $message, $status) - add message to session to display on page reload

you can use it as following:

		
// if you do not have access to registry - get it
// in controllers you can access messages like - $this->messages
$registry = Registry::getInstance();
$messages = $registry->get(‘messages’);

$message->saveNotice(‘Some notice’, ‘message text’);
		
 		

Suggestions to use: Say you need to notify store admin of critical errors happened during checkout. Below is the example what you do:

//for use in controller $this->messages->saveError(‘Checkout error’, ‘message text’);

If the form submit encounter and error you can pass the message to the next leading page. See example:

		
/**
    * save notice
    *
    * @param  $title - string - message title
    * @param  $message - string - message body
    * @param  $status - message status ( N - notice, W - warning, E - error )
    * @return void
    */

// in this case message will be added to session message pool and shown on page reload
$this->messages->saveForDisplay($title, $message, $status)
		
 		

Below diagram show error, warning and message relation and flow:

Related pages: