Skip to content

XELOS Coding Conventions

Abstract

XELOS strives to comply and follow the [PHP Standards Recommendations (PSR)]](https://www.php-fig.org/psr/) if coding style and decisions are to be made. For historical reasons not all code parts are following these recommendations yet, but the goal is to convert all active code parts step by step to follow the PSR.

Info

This document is to be followed for new developments. Pull Requests not meeting these standards are to be declined.

Common Code Conventions

Based on PSR-1 XELOS follows these conventions:

  • Files MUST use only <?php tags.
  • Files MUST use only UTF-8 without BOM for PHP code.
  • Files SHOULD either declare symbols (classes, functions, constants, etc.) or cause side-effects (e.g. generate output, change .ini settings, etc.) but SHOULD NOT do both.
  • Namespaces and classes MUST follow an “autoloading” PSR: [PSR-4].
  • Class names MUST be declared in StudlyCaps.
  • Class constants MUST be declared in all upper case with underscore separators.
  • Method names MUST be declared in camelCase.

File and Class Naming

Folder "class" in each module is the root folder of all PHP classes. All folders and class files are named in StudlyCaps. The class file name must match the class name.

Example:

Class: MyAwesomeClass
File:  MyAwesomeClass.php

Abstract classes

An abstract class does not have any prefix or suffix. The name of the class should be meaningful to show it's type / functionality.

Interfaces

Interfaces must be named with the suffix "Interface". They should be bundled into a separate "Interfaces" folder if there is more then one interface.

E.g.

Class: XELOS\Modules\MyModule\Hook\Interfaces\MyHookInterface
Location: <XELOSROOT>/modules/my_module/class/Hook/Interfaces/MyHookInterface

General Class Suffix

Some classes have to use a suffix to make their functionality obvious. The following classes should have a class name suffix:

Class / Type Suffix Example Class name
Controllers Controller AwesomeController
Pages Page AwesomePage
Actions Action AwesomeAction
Helpers Helper AwesomeHelper
Interfaces Interface AwesomeInterface
Traits Trait AwesomeTrait

Variables and Constants

Variable names are written in lowerCamelCase and should be

  • self-explanatory
  • not shortened beyond recognition, but rather longer if it makes their meaning clearer

Correct naming of variables

  • $singletonObjectsRegistry
  • $argumentsArray
  • $aLotOfHtmlCode
  • $firstName

Incorrect naming of variables

  • $sObjRgstry
  • $argArr
  • $cx
  • $myVar

As a special exception you may use variable names like $i, $j and $k for numeric indexes in for loops if it’s clear what they mean on the first sight. But even then you should want to avoid them.

Methods and Functions

New method names should be written in lowerCamelCase. In order to avoid problems with different filesystems, only the characters a-z, A-Z and 0-9 are allowed for method names – don’t use special characters.

Make method names descriptive, but keep them concise at the same time.

Stick to existing verbs when creating methods:

  • setStatus($status_value=myClass::STATUS_NEW)
  • getStatus()
  • hasStatus($status_value=myClass::STATUS_NEW)
  • isHidden()
  • can..() (check rights for current user)
  • find..() (lookup in database)
  • search..() (search in local collection)
  • trigger..Event() (Manually trigger an event)
  • on..Event() (Function is usually binded to an event)
  • process..() (Execute a set of procedure, usually no direct in or output)
  • render() (Create Output)

Example in XELOS Form:

/** @var FormCheckbox $checkbox */
$checkbox = $form->add_field_checkbox('my_checkbox');//old naming
$checkbox->setLabel('LabelText');//Returns $checkbox for chaining
$checkbox->isReadonly();//Returns bool when field is readonly

Namespace

XELOS uses the PSR-4 autoloading standard for namespaces, which means that the namespace of each class must match the folder structure the class is located in. The class folder of each module is mapped as namespace root of the contained classes. Following namespace root mappings are used:

Namespace root Mapping path
XELOS\Framework <XELOSROOT>/class
XELOS\Modules <XELOSROOT>/modules
XELOS\Modules\Example <XELOSROOT>/modules/example/class
XELOS\Vendor\<vendor>\Modules <XELOSROOT>/vendor/<vendor>/modules
XELOS\Vendor\<vendor>\Modules\Example <XELOSROOT>/vendor/<vendor>/modules/example/class

Example for a module controller of the module "Awesome":

File: <XELOSROOT>/modules/awesome/class/AwesomeController.php
FQN of the class: XELOS\Modules\Awesome\AwesomeController

Hooks

Some modules offer one or more hook API interfaces. Modules can use these to implement their own hook, which may be consumed by the compatible module if both modules are installed within XELOS. Hooks have a special location and naming convention which relate to the hook definition in the module configuration. The structure of a defined hook in the configuration is a combination of module name and hook type separated by a dot.

For example the module selector will consume hooks from type browser, so the name of this hook is:

Module: Selector
Hook:   selector_browser

The module, that wants to provide a "selector_browser" has to create a new hook class. The folder in which the hook class is placed must have the following convention:

<XELOSROOT>/modules/<my_module_name>/class/Hook/<hook_module_name>/

The hook class also has a naming convention which consists of the provided hook name and the hook type. In the case above the class should be specified as follows:

Location (Path):  <XELOSROOT>/modules/my_module/class/Hook/Selector/MyBrowser.php

Class (FQN):      XELOS\Modules\MyModule\Hook\Selector\MyBrowser

Module Controller

The module controller is located in the class folder of each module. The class name of the controller consists of the module name and the suffix "Controller".

E.g. the module controller of the module Forum

Path:   <XELOSROOT>/modules/forum/class/ForumController.php
Class:  XELOS\Modules\Forum\ForumController

Install Event

Since XELOS 8 the install event class is located in the class folder. The class name of each install event is the same.

E.g. the install event for module forum

Path:   <XELOSROOT>/modules/forum/class/InstallEvents.php
Class:  XELOS\Modules\Forum\InstallEvents
The InstallEvents class of a module should extends the XELOS\Framework\Module\InstallEvents class

Crons and Daemons

The cron and daemon classes always use the same name in each module.

E.g. forum cron:

Path:   <XELOSROOT>/modules/forum/class/SystemCron.php
Class:  XELOS\Modules\Forum\SystemCron

E.g. forum daemon

Path:   <XELOSROOT>/modules/forum/class/SystemDaemon.php
Class:  XELOS\Modules\Forum\SystemDaemon

PHP Documentation

All classes, properties, methods, functions and constants should be have a PHPDoc comment, which should at least contains a short description and if exists, params, information, return and throw information. You should use only official PHPDoc tags .

Example class with PHPDoc:

<?php

namespace XELOS\Modules\MyModule;

/**
 * Summary description of this class
 *
 * Long Description of this class may contain markdown:
 *
 * **Example**
 * ```
 * $MyModuleController = Factory::get('MMC');
 * $MyModuleController->doSomeThing('example');
 * ```
 *
 * @method MagicReturn MagicMethodYouShouldKnow($param = 'example')
 * @see https://my.xelos.net/dev-doc/ for more documentation
 * @mixin MyModuleControllerMagicDocs
 */
class MyModuleController {

    /**
     * This is a short description of this property.
     * 
     * @var string
     * @see MyOtherModuleController::$property For possible values
     */
    protected $property;

    /**
     * This is a short description of the functionality.
     * 
     * @param int $number
     *
     * @return int
     *            
     * @throws \InvalidArgumentException
     * @example ../example.php 5 3 See Usage Example at line 5-8
     * @source 2 3 Exception includes your argument
     */
    public function doSomeThing($number){
        if( ! is_numeric($number) ){
            throw new \InvalidArgumentException($number);
        }
        return $number;
    }

}

This will result in something like:

PHP Doc