Application Modules - Structure

Each module represents a separate physical directory, where placed it's all files. Some of the files may be moved to another folders according to develop needs while installation/unstallation process. All modules must be placed in protected/modules/ directory.

Below the minimum file structure for the standard module. Take in account that you may define update files like: update.002.mysql.sql, update.003.mysql.sql, etc. While updating procedure the system will run them automatically according to their order.

Here the file structure for a real News module:

info.xml - change log file
Version 0.0.1
Initial release    

info.xml - main information file
<?xml version="1.0" encoding="utf-8"?>
<install version="1.0" type="module">
    <description>News module allows creating and displaying news on the site</description>				 
        <config installationPath="protected/config/">
            <filename exclude="yes">main.php</filename>
        <images installationPath="assets/modules/news/images/">
        <robots exclude="yes">
        <messages installationPath="protected/messages/*">

config/main.php - main configuration file
return array(
    // Module classes
    'classes' => array(
    // Management links
    'managementLinks' => array(
        A::t('news', 'News') => 'news/manage'

config/news.php - special configuration (movable file, will be copied to protected/config/ directory)
return array(
    // Module components (optional)
    'components' => array(
        'NewsComponent' => array('enable' => true, 'class' => 'NewsComponent'),               

    // URL manager (optional)
    'urlManager' => array(
        'rules' => array(
            'news/view/id/([0-9]+)' => 'news/view/id/{$0}',
            'news/view/id/([0-9]+)/(.*?)' => 'news/view/id/{$0}',
            'news/view/([0-9]+)' => 'news/view/id/{$0}',
            'news/view/([0-9]+)/(.*?)' => 'news/view/id/{$0}',
            'news/([0-9]+)' => 'news/view/id/{$0}',
            'news/([0-9]+)/(.*?)' => 'news/view/id/{$0}',

    // Default Backend url (optional, if defined - will be used as application default settings)
    'backendDefaultUrl' => 'news/manage',

    // Default settings (optional, if defined - will be used as application default settings)
    'defaultErrorController' => 'NewsError',
    'defaultController' => 'news',
    'defaultAction' => 'view',

components/NewsComponent.php - module main component
class NewsComponent extends CComponent
    const NL = "\n";

     * Draws last news side block
    public static function drawNewsBlock($title = '')
        $output = '';
        $headerLength = 80;
        $newsCount = 3;

        $headerLength = ModulesSettings::model()->param('news', 'news_header_length');
        $newsCount = ModulesSettings::model()->param('news', 'news_count');
        // Fetch datetime format from settings table
        // Or $settings = Bootstrap::init()->getSettings();
        $settings = Settings::model()->findByPk(1);
        $dateTimeFormat = $settings->date_format;
        $news = News::model()->findAll(
                'condition'=>'is_published = :isPublished AND created_at < :currentDate',
                'order'=>'created_at DESC', 'limit'=>'0, '.(int)$newsCount
            array(':isPublished'=>1, ':currentDate'=>LocalTime::currentDateTime())

        $output .= '<div class="side-panel-block">';
        $output .= '<h3 class="title">'.$title.'</h3>';
        if(is_array($news) && count($news) > 0){
            foreach($news as $key => $val){
                $output .= '<div class="block-body">	
                    <p class="block-title">
                        <a href="news/view/id/'.$val['id'].'">
                            '.CString::substr($val['news_header'], $headerLength).'
                    <p class="block-date">'.date($dateTimeFormat, strtotime($val['created_at'])).'</p>
                    <p class="block-content">'.CString::substr(strip_tags($val['news_text']), 125, '', true).'
                        <a class="more more-news" href="news/view/id/'.$val['id'].'">
                            '.A::t('news', 'read more').' »
            $output .= A::t('news', 'No News Found');
        $output .= '</div>';
        return $output;