LiteCommerce:Object Model

From X-Cart 4 Classic
Jump to: navigation, search

LiteCommerce is an object-oriented application, therefore some OOP (object-oriented programming) background is required to use its API. There are a lot of excellent textbooks on OOP available on the Internet and off-line, both for novices and experienced programmers. Please refer to the bibliography section for a list of recommended reading on OOP. The current section covers only the basic OOP principles and some LiteCommerce-specific features required to understand LiteCommerce architecture and cannot be used as an OOP guide. You should also be familiar with PHP4 Object Model (see http://php.net/manual/en/language.oop.php) to make modifications to LiteCommerce core or create your own LiteCommerce modules.

Firstly, almost all of the LiteCommerce functionality is built up of classes, which consist of functions (or methods in OOP terminology) and properties. A method is a function which is a constituent part of a particular class instance at run time. Class instances are also called objects. You may say that an object is an implicit argument of all its class methods. This argument can be accessed using the pre-defined variable this inside the method’s body. The following example will produce "foobar" string to the output:

Example 1.1 Using this variable from methods.

// define a class

class MyClass {
function myFunc($a) {
return $this->b . $a;
}

var $b; // define the class attribute

}

// create and initialize the class instance
$object = new MyClass;
$object->b = "foo";

// call the class method on the $object instance
print $object->myFunc("bar");

Good style is placing each class in a separate file which is named after the class name. You can find LiteCommerce classes in the classes directory under the LiteCommerce installation dir and use them as examples. They also provide more detailed information than this guide does.

Object can hold some data in its attributes (or fields). As you may have already noticed, object attributes can be retrieved using the -> operator. One of the basic ideas behind OOP is encapsulation, e.g. accessing data through methods instead of attributes, so that $object->b = "foo"; from the previous example becomes:

Example 1.2 Defining a class property.

class MyClass {
...
function setB($bValue) { // setter
$this->b = $bValue;
}

function getB() { // getter
return $this->b;
}

var $b;

}

$object->setB("foo");

print $object->getB(); // output “foo”

The reason is to hide internal class data structures by providing some compact and clear interface to the object's state and functionality. This is where properties emerge, denoting some piece of data, stored inside an object. Each property has a setter and a getter method, responsible for settings and fetching its value respectively. Getter and setter methods are usually called after the corresponding property name, with the 'get' or 'set' prefix.

Thus, you should define a couple of methods and define a property, which in some cases causes overhead. Instead, most of the properties simply map to the object attributes, as in the previous example. To simplify creating such properties, LiteCommerce object model includes a common getter and setter for all properties, namely get(name) method and set(name) method, where name is the property name. The usage is illustrated in the following example:

Example 1.3 LiteCommerce style.

class MyClass extends Object {

var $someProperty;

}

$object = func_new("MyClass");

$object->set("someProperty", "someValue");

...

print $object->get("someProperty"); // output "someValue"

Here extends Object means that the MyClass class has all the methods and attributes as the LiteCommerce Object class has, plus those which are defined in the MyClass explicitly. This class extending technique is also known as inheritance in OOP. Each class in LiteCommerce must extend the Object class or a class that extends it either directly or indirectly. In this example, MyClass just inherits the get and set methods defined in the Object class.

By using the common getter/setter mechanism, we are not limited to only attribute properties: you can define a getter and/or setter for a property as well and use the get and set methods to access them. First, the “get” method looks for the property getter method, which must be called either getName or isName and accept no arguments. The last name is useful for boolean properties, e.g. isEmpty, and the Object defines the common “is” method which is a synonym for get. Thus the $cart->isEmpty() is the same as $cart>is("empty").

A property in LiteCommerce itself may be an object which can, in its turn, have properties. The “get” and “set” methods can accept a sequence of property names to access the nested object's properties:

Example 1.4 LiteCommerce dot-syntax.

$object->get("name1.name2. ...")

this is equivalent to:

$temp =& $object->get("name1");

$temp->get("name2. ...")

When defining a getter method that returns an object, always declare it by reference, otherwise PHP will crash.

Example 1.5 LiteCommerce getter.

function &getObjectProp()
{
...
return $result;
}
Note: Unlike “get”, the “set” method does not pass objects by references. Every time you call set(property, object), the object copy is assigned to the property.

LiteCommerce style also requires an object creation mechanism other than the built-in PHP new operator. All new operators must be replaced with the func_new function. The function syntax is:

Example 1.6 Create an object.

$object =& func_new("ClassName" [, arg1, arg2, ...])

The first argument of the func_new is the string containing a class name. Each time the object is created, func_new function calls its constructor method. Typically, constructor is used to initialize the new object instance and is called just after the instance has been created. The Object class defines the constructor method which performs basic initialization tasks. You can redeclare the constructor method in your classes:

Example 1.7 Declaring object constructor.

class MyClass extends Object {
function constructor($propValue = null) {
parent::constructor();
$this->prop = $propValue;
}
var $prop;
}

$object =& func_new("MyClass", "someValue");

print $object->get("prop"); // output "someValue"

You can pass one or more arguments to an object constructor in the func_new method by enumerating them after the class name, as shown in the example above. The parent::constructor(); calls constructor defined in the Object class.

Note: Always call parent::constructor(); from your constructors, as it initializes some critical properties. See Object properties description for more details.

There are two reasons for using func_new instead of standard new:

  • func_new is capable of locating and including the class file. In standard PHP, you have to require_once() all the classes before you can use them in the source file. This is rather an error-prone approach for handling file dependencies. In LiteCommerce there is no need to require all the needed files since the information about classes and their files is automatically indexed and stored in the classes.lst file. This index is then used by the func_new function to locate the appropriate file.
  • func_new can replace the original class with the module replacement class, enabling modules to extend LiteCommerce functionality. See modules section for more details.

Always use func_new to create new instances in LiteCommerce unless you are going to create a third-party class instance, e.g. HTTP/Request class. Strictly speaking, you should use func_new to create an object of a class that extends (directly or indirectly) the Object class.

Note: You can use command line PHP utility provided by LiteCommerce to build classes listing or create classes index manually.

Classes index has the following format

class:file:parent

where “class” is a lowercase name of the class you are going to define, “file” is a case-sensitive name of PHP source file with ”class” code, “parent” is a class parent name.

Example 1.8 Classes index file classes.lst

cpager:view/Pager.php:component
cproductselect:view/ProductSelect.php:component
cregisterform:view/RegisterForm.php:component
cstateselect:view/StateSelect.php:cformfield
cstatusselect:view/StatusSelect.php:cformfield
csubmit:view/Submit.php:cbutton
ctabber:view/Tabber.php:widget
tabberpage:view/TabberPage.php:object
ctopcategories:view/TopCategories.php:component

Every time you add or define a new class into LiteCommerce, you should rebuild classes index and clean up compiled classes cache (running http://your_cart_url/path/cleanup.php).