Development - Namespaces


General

A namespace refers to a logical grouping of some class names so that they can be differentiated from other class names even if their names are the same. Do not confuse path alias with namespace, because a path alias is merely a convenient way of naming a file or directory and it doesn't related to a namespace.

NOTE:
Because PHP prior to 5.3.0 does not support namespace intrinsically, you cannot create instances of two classes who have the same name but with different definitions. For this reason, all ApPHP Framework classes are prefixed with a letter 'C' (meaning 'class') so that they can be differentiated from user-defined classes. It is recommended that the prefix 'C' be reserved for ApPHP Framework use only, and user-defined classes be prefixed with other letters.

ApPHP Framework minimum requirements from v1.2.0 is PHP 5.4

Namespaced Classes

A namespaced class refers to a class declared within a non-global namespace. For example, the application\modules\blog\models\Posts class is declared within the namespace application\modules\blog\models\. Using namespaced classes requires PHP 5.3.0 or above.

From version 0.8.0 it is possible to use a namespaced class without including it explicitly. For example, we can create a new instance of application\modules\blog\models\Posts without including the corresponding class file explicitly. This is made possible with the enhanced ApPHP Framework class autoloading mechanism.

In order to be able to autoload a namespaced class, the namespace must be named in a way similar to naming a path alias. For example, the class application\modules\blog\models\Posts must be stored in a file that stored in the same path in the system.


Namespaced Controllers

By default ApPHP Framework uses controllers from the global namespace. These classes are located under protected/controllers/. The same rules are used for Directy CMF controllers. But for modules namespaces are used by default.

Here the example:

namespace Modules\News\Controllers;

// Modules
use \Modules\News\Components\NewsComponent,
    \Modules\News\Models\News,
    \Modules\News\Models\NewsSubscribers;

// Framework
use \A,
    \CAuth,
    \CConfig,
    \CController,
    \CDatabase,
    \CWidget;

// Directy
use \LocalTime,
    \Modules,
    \Website,
    \ModulesSettings;

class NewsController extends CController
{
    // ...

    // Example usage global class:
    $msg = A::t('core', 'Cache is On, but currently turned off because you are logged in'));

    // Example 1 of usage:
    $this->_view->tabs = NewsComponent::prepareTab('news');

    // Example 2 of usage:
    $this->_view->tabs = \Modules\News\Components\NewsComponent::prepareTab('news');
}


Namespaced Models

Models are also used from the global namespace by default. These classes are located under protected/models/. But for modules namespaces are used by default.

Here the example:

namespace Modules\News\Models;

// Framework
use \A,
    \CActiveRecord,
    \CModel,
    \CDatabase,
    \CConfig,
    \CHtml;

// Directy
use \Website;

class News extends CActiveRecord
{
    // ...

    $link = Website::prepareLinkByFormat('news', 'news_link_format', 1, 'Header');
}


Namespaced Components

Components are also used from the global namespace by default. These classes are located under protected/components/. But for modules namespaces are used by default.

Here the example:

namespace Modules\News\Components;

// Framework
use \A,
    \CActiveRecord,
    \CModel,
    \CDatabase,
    \CConfig,
    \CHtml;

// Directy
use \Website;

class NewsComponent extends CComponent
{
    // ...

    $link = Website::prepareLinkByFormat('news', 'news_link_format', 1, 'Header');
}


Using namespaces in view files

In View files we have to specify namespaces explicitly.

Here the example:

// Global namespace
Website::setMetaTags(array('title'=>$newsHeader));

// Local namespace
Modules\News\Components\NewsComponent::drawLatestNewsBlock(array(
    'title'=>'', 'showThumb'=>false, 'newsCount'=>3)
);


Using namespaces in widgets in view files

For widgets in View files we have to specify namespaces explicitly.

Here the example:

CWidget::create('CDataForm', array(
    'model'         => '\Modules\News\Models\NewsSubscribers',
    'primaryKey'    => $id,
    'operationType' => 'edit',
    'action'        => 'newsSubscribers/edit/id/'.$id,
    'successUrl'    => 'newsSubscribers/manage',
    'cancelUrl'     => 'newsSubscribers/manage',
    'method'        => 'post',
    'htmlOptions'   => array(
        'id'   => $formName,
        'name' => $formName,
        'autoGenerateId' => true
    ),
    'requiredFieldsAlert' => true,
    'fields'    => $fields,
    'buttons'   => array(
        'submitUpdateClose'=>array('type'=>'submit', 'value'=>A::t('app', 'Update & Close'), 'htmlOptions'=>array('name'=>'btnUpdateClose')),
        'submitUpdate'=>array('type'=>'submit', 'value'=>A::t('app', 'Update'), 'htmlOptions'=>array('name'=>'btnUpdate')),
        'cancel' => array('type'=>'button', 'value'=>A::t('news', 'Cancel'), 'htmlOptions'=>array('name'=>'', 'class'=>'button white')),
    ),
    'buttonsPosition' => 'bottom',
    'events' => array(
        'focus' => array('field' => $errorField)
    ),
    'messagesSource'    => 'core',
    'showAllErrors'     => false,
    'alerts'            => array('type'=>'flash', 'itemName'=>A::t('news', 'Subscriber')),
    'return'            => false
));


Using namespaces in config files for modules

If you use namespaces for moudle, you have to define classes in special format in configuration files.
For example (main.php file):

return array(
    // Module classes
    'classes' => array(
        'Modules\News\Components\NewsComponent',
        'Modules\News\Controllers\News',
        'Modules\News\Controllers\NewsSubscribers',
    ),
    // Management links
    'managementLinks' => array(
        A::t('news', 'News') => 'news/manage',
        A::t('news', 'Subscribers') => 'newsSubscribers/manage'
    ),
);