Naming rules & recommendations

Contents...

The operation of the Webasyst framework relies on a number of naming conventions (for files, classes, and database tables). Non-compliance with these conventions will make an application inoperable; therefore, correct naming is a strict requirement for each Webasyst application developer.

In addition to strict rules, this section also contains some non-obligatory recommendations.

Database #

Tables

Requirement. All table names must begin with the application identifier (APP_ID) followed by an underscore character.

Recommendation. Tables containing certain entities' data (e.g., guestbook messages, individual notes in Stickies, files, etc.) should be named using nouns in singular form.

Examples:

Recommendation. Tables containing information about various connections as well as tables containing auxiliary data, should be named according to the following rule: table name is composed of two words (in addition to the obligatory APP_ID used as a prefix) separated by an underscore character; the first word is the main entity's name in the singular form followed by the secondary entity's name in the plural form (if applicable, otherwise the singular form is used or vice versa).

Example:

Table for storing contacts' email addresses.
wa_contact_emails: one-to-many relationship, i.e. one contact relates to several email addresses

Plugin tables

Requirement. Names of plugin tables must be formed according to template app_plugin_name, where app and plugin stand for app and plugin IDs, and name must be replaced with an arbitrary table name.

Table fields

Recommendation. A table's own fields should be named without extra prefixes. Under own fields are understood fields which are not used as external keys to records contained in other database tables.

Examples:

If several fields are supposed to store similar types of data, a clarifying prefix should be added to each field's name based on their purpose within an application; e.g.:

Recommendation. External key fields should be named according to the following rules: the name of the table (without a prefix) to which the field is referencing followed by the corresponding field name in the referenced table.

Examples:

Where necessary, an explanatory prefix may be added to a field name for better comprehensibility.

Examples:

PHP classes, methods, and variables #

Naming of classes and methods

Requirement. Names of all application classes must begin with the application identifier (APP_ID). This is required to avoid naming conflicts between classes of different applications.

Requirement. For naming of PHP classes and methods the "lowerCamelCase" convention must be used: all words in a name are written together (without a separating character), the first word (APP_ID for class names) is written completely in lower case, other words are capitalized.

Example:

<?php

class filesFile
{

    public function getInfo()
    {
        ...
    }
    ...

}

PHP class files naming

PHP classes are automatically included by the system during the execution of an application using the Autoload mechanism. In order for the auto-loading mechanism to be able to locate the required PHP file, each of them must be named in accordance with a certain rule.

Requirement. All class files must be located in lib/ subdirectory inside the application main directory.

Requirement. A class file name must have the following form: {CLASS_NAME}.class.php. For example, if a class name is contactsCollection, then its file's name must be contactsCollection.class.php.

Requirement. For files containing the source code of actions, controllers, and models additional naming format is used, which is recommended to use: if the class name contains prefix Actions, Action, Controller, or Model, then the class file name must have the following form: {CLASS_NAME_WITHOUT_SUFFIX}.{suffix}.php ({suffix} is written in lower case). Several examples:

Naming of classes and methods of controllers and actions #

The application logic implemented in the controller layer is organized as the two-level hierarchy "module/action". The request routing rules set the relationship between the request URL and the module+action couple, i.e. each user request actually triggers execution of a certain action inside a certain module.

The routing mechanism determines the names of a module and an action (if no action is specified, the default is executed). To ensure that the system is able to correctly determine which method of which class must be called for the processing of a user request, the following controller classes and methods naming rules must be complied with:

Requirement. The name of a class and a method chosen by the system for the processing of a user request must comply with the rules which are used by the routing system to find the correct class and method. The search is performed in the following order (parts of class names are concatenated according to the "lowerCamelCase" rule without separating characters):

  1. First of all, a class named according to rule {APP_ID}{MODULE}{ACTION}Controller, or {APP_ID}{MODULE}Controller (if no action name is specified), is searched. If such a class is found, its instance is created and its method execute is called; this is the starting point of the requested web page's controller.

  2. If no class has been found, then a class named to a different rule is searched: {APP_ID}{MODULE}Actions. If such a class is found, its new instance is created and its action named according to rule {ACTION}Action, or DefaulAction (if no action name is specified), is called. Such controllers whose methods are individual actions are popular in many programming frameworks.

  3. If the second class name variant has not been found, either, a third class variant name composed according to rule {APP_ID}{MODULE}{ACTION}Action, or {APP_ID}{MODULE}Action (if no action is specified),is searched. If such a class is found, its instance is created and its method execute is called.

  4. If no class has been found, error code 404 is returned.

Below are given several examples of pairs "module+action" and the names of classes and methods.

Application myblog, module mail, no action is specified:

  1. myblogMailController->execute()
  2. myblogMailActions->defautAction()
  3. myblogMailAction->execute()

Application myblog, module mail, action test:

  1. myblogMailTestController->execute()
  2. myblogMailActions->testAction()
  3. myblogMailTestAction->execute()

Read more about the routing system in sections "Backend request routing" and "Frontend request routing".

Template files naming #

Each template is rigidly tied to a specific action of a certain module. The HTML template location mechanism uses the names of the requested module and action.

Requirement. The template file is searched inside the following path in the main application directory: templates/actions/{MODULE}/{MODULE}{ACTION}.html. For example, for module mail and action test the system will use template file templates/actions/mail/mailTest.html.

Requirement. In cases when no action name is specified, template naming rule depends on the action class type used:

Read more about different types of action classes in section "Actions and controllers".

Naming globally accessible identifiers (JavaScript, CSS, sessions) #

Globally accessible identifiers (JavaScript variables and functions, CSS classes, request parameters managed by waRequest class, user session variables) must be named in such a way that they do not cause conflicts with the backend and frontend of other software products which may be installed in the same Webasyst account. To avoid conflicts, add your plugin or app ID as prefix to such identifiers.

Examples

//JavaScript
var myplugin_var; //if there is no other option, add plugin ID to global variable name
//or, better, re-organize your JavaScript code by using closures as shown below

//CSS
.myplugin-settings .fields .field .name //e.g., wrap settings fields with an HTML element with a custom CSS class and override styles using a prefix
    
//PHP sessions
wa()->getStorage()->set('shop_myplugin_custom_var', $data);
    
//Request parameters
waRequest::setParam('myplugin_custom_param', $data);

Recommendation: When writing JavaScript code, try to avoid using globally accessible identifiers and use closures instead.

Example

//Not quite good
var myplugin_global_var = '...'; //even with a custom prefix, this variable is still accessible to other plugins' and the app's JavaScript code
if (myplugin_global_var) {
    ...
}

//Better
(function () {
    var global_var = '...'; //this variable is accessible only within the plugin's code and will not conflict with other plugins
    if (global_var) {
        ...
    }
})();

Recommendations on PHP code formatting #

Recommendation. It is advisable to comply to common code formatting rules during development of Webasyst applications (especially for developer teams). We recommend adhering to the formatting style used throughout the framework source code and Webasyst applications:

<?php //use only this opening tag and no others

/**
* @desc always leave comments to custom classes in the PhpDOC format
*/
class CodingStyle //name PHP classes using the "lowerCamelCase" notation
{
  
  	//place the opening curly bracket on the NEW line

    //tabs are replaced by 4 spaces
    //character encoding: UTF-8
    //UNIX-style newline characters: \n instead of \r\n

    /**
    * @desc variable naming format should differ from that used for method names
    * variable names should contain only letters in lower case with words separated using underscore characters
    */
    public $is_right;

    /**
    * @desc Write comments for methods and functions
    * @param $code int — describe input data
    * @return boolean — describe returned data
    */
    public function doIWriteValidCode($code) //name methods using the "lowerCamelCase" notation
    { //place the opening curly bracket on the NEW line

        //write comments inside methods and functions using ONLY this tag
        //NEVER use multi-line commenting tags

        $this->is_right = false; //symbols +-=*/{} etc. must be separated by spaces


        if (! $code) { //place any opening bracket inside methods in the CURRENT line
            //no code — no problems
            $this->is_right = true; //use brackets, even if there is ONLY ONE statement in a structure
        } else { //write else/elseif in the SAME line after the closing bracket of the if operator
            $this->is_right = $this->checkMyCode($code);
        }

        return $this->is_right;
    }

    /**
    * @desc Write a description even if a function/method name speaks for itself
    */
    public function checkMyCode($code)
    {
        return false; //Don't worry, we will always find something to find fault with! ;)
    }
}

//no closing PHP tag at the end of the file