The directory structure of the Yii project site

94 followers

In this article, we describe the directory structure used by yiiframework.com - the official Yii framework website. While this structure may look overly complicated for small projects or may not be optimal in some sense, we believe it is appropriate for medium or large projects in a team development environment. In fact, we have successfully used the similar structure in some other big projects.

Overall Structure

Below is the directory structure we are using:

/
    backend/
    common/
        components/
        config/
            params.php
            params-local.php *
        lib/
            Pear/
            yii/
            Zend/
        migrations/
        models/
            Comment.php
            Extension.php
            ...
    console/
        commands/
            SitemapCommand.php
            ...
        config/
            main.php
            main-local.php *
            params.php
            params-local.php *
        runtime/
        yiic.php *
    frontend/
        components/
        config/
            main.php
            main-local.php *
            params.php
            params-local.php *
        controllers/
            SiteController.php
            ...
        lib/
        models/ 
            ContactForm.php
            SearchForm.php      
        runtime/
        views/
            layouts/
            site/
        www/
            assets/
            css/
            js/
            index.php *
    yiic
    yiic.bat

In a team development environment, we should have some source code revision system (e.g. SVN, GIT) to manage the above structure. File names annotated with an asterisk should NOT be put in the revision system, as we will explain shortly.

Top-level Directories

At the top level, we have four directories:

  • backend: the backend application which is mainly used site administrators to manage the whole system.
  • frontend: the frontend application which provides the main interfaces to our target end users.
  • console: the console application that consists of the console commands needed by the system.
  • common: the directory whose content are shared among the above applications.

As we can see, we divide the whole system into three applications: backend, frontend and console. If needed, we can add more applications (e.g. api, to provide Web API service). We use common to store files that are shared among the applications.

Application Directories

The directory structure of each application is very similar. For example, for frontend and backend, they both have these directories:

  • components: contains components (e.g. helpers, widgets) that are only used by this application
  • config: contains the configuration used by the application
  • controllers: contains controller classes
  • lib: contains third-party libraries that are only used by this application
  • models: contains model classes that are specific for the application
  • runtime: stores dynamically generated files
  • views: stores controller actions view scripts
  • www: the web root for this application

The directory structure for console is slightly different as it does not need controllers, views and www. Instead, it contains a commands directory to store all console command class files.

The Common Directory

The common directory contains the files that are shared among applications. For example, every application may need to access the database using ActiveRecord. Therefore, we can store the AR model classes under the common directory. Similarly, if some helper or widget classes are used in more than one application, we should also put them under common to avoid duplication of code.

To facilitate the maintenance of code, we organize the common directory in a structure similar to that of an application. For example, we have components, models, lib, etc.

As we will soon explain, applications may also share part of the configurations. Therefore, we also store the common configurations under the config directory in common.

When developing a large project with a long development cycle, we constantly need to adjust the database structure. For this reason, we also use the DB migration feature to keep track of database changes. We store all DB migrations under the migrations directory in common.

Application Configurations

Applications of the same system usually share some common configurations, such as DB connection configuration, application parameters, etc. In order to eliminate duplication of code, we should extract these common configurations and store them in a central place. In our setting, we put them under the config directory in common.

When working in a team environment, different developers may have different development environments (e.g. operating system, directories, DB connections). These environments are also often different from the production environment. In order to avoid interference among developers, we divide the configurations into two parts: the base configuration (e.g. main.php, params.php) and the local configuration (e.g. main-local.php, params-local.php).

The base configuration should be put under version control, like regular source code, so that it can be shared by every developer.

The local configuration should NOT be put under version control and should only exist in each individual developer's working folder. A developer has full freedom to modify his local configuration.

In the application's bootstrap script index.php, we can merge the base and local configurations and then configure the application instance, like the following:

require('path/to/yii.php');
$local=require('path/to/main-local.php');
$base=require('path/to/main.php');
$config=CMap::mergeArray($base, $local);
Yii::createApplication($config)->run();

Path Alias

To facilitate referencing files in different applications, we also declare a root path alias site which points to the root directory containing the four top directories. As a result, we can use site.frontend.models.ContactForm to reference the ContactForm class declared in the frontend application.

Deployment

During development or after finishing a project, we need to deploy it to the production server. Instead of uploading files to the server using FTP or other similar services, we can use revision control system to do the deployment.

We can treat the production server as a special developer who has the production server as his development environment.

We first check out an initial copy or update an existing copy from the revision control system to the desired location on the production server.

We then create or modify the local configurations specific for the production server. For example, we may need to adjust the DB connection parameters. We may want to define YII_DEBUG to be false in index.php.

Because we store each application in a separate directory, if needed, we can deploy them to different servers.

Links

Russian version

Total 20 comments

#11275 report it
nsanden at 2013/01/03 12:06am
themes and extensions

don't suppose theres any clean way to put a theme in the common dir and use it for multiple apps? My 'admin' app and my 'user' apps will use the same theme but my 'frontend' app will use something else.

Update i achieved this by using in my common config:

'themeManager' => array(
    'basePath' => '/xampp/htdocs/myapp/common/themes/',
    'baseUrl' => 'http://static.myapp.com/themes/', //this is the important part, setup a subdomain just for your common dir
),

and in my apps i use simply: 'theme' => 'whatever'

#10898 report it
Arivan Bastos at 2012/11/30 04:41pm
What about shared (common) modules?

I do have a module that should be used both in admin and site areas (SRBAC, access control module). I think that it should be in the "common/modules/" folder. But, how can I load it from the backend or frontend application? Should I change the modules folder? If yes, how can I do this? I tried 'modulePath'=> $common.'/modules' in the backend config file but it didn't work.

Edit (solved):

The following changes (in main.php) solved my problem:

Yii::setPathOfAlias('srbac', $root.'/common/modules/srbac');

and

'modules'=>array(
       'srbac' => array(
            'class' => 'common.modules.srbac.SrbacModule',
#10375 report it
Ivica at 2012/10/24 01:40am
@Hieu Vo

Themes folder should be under frontend/www/themes and backend/www/themes, and you will want to setup your document roots to frontend/www and backend/www, so no files outside of www folders can't be accessed via web. BTW, why you would want to place theme folders under frontend/themes and backend/themes?

#9900 report it
Hieu Vo at 2012/09/20 01:24am
Themes folder

with this structure, where the themes folder should be put? I applied this structure for my project, and it seems themes folder is supposed to be placed in backend/www/themes or frontend/www/themes, but I want to move it to backend/themes or frontend/themes. I tried to change config.php file but it doesn't work

#9444 report it
mgk at 2012/08/11 05:42am
Sample setup

Quick steps to setup your environment:

1) Create a root folder and subfolders : common, console, backend and frontend. You can use the folder structure given above. Tip : In the root folder you can use "yiic webapp frontend" to create folders quickly, then just make some organization inside frontend folder.

2) Copy yii inside common/lib. Don't forget to edit your frontend and backend /www/index.php files to point yii installation folder.

3) Edit your config files. I've some additional lines on backend main.php:

Yii::setPathOfAlias('root', $root);
Yii::setPathOfAlias('common', $root . DIRECTORY_SEPARATOR . 'common');
..
..
'import' => array(
    'common.components.*',
    'common.extensions.*',
    'common.models.*',
    ..
    ..

If you're using local config files, use CMap::mergeArray to merge configs ( explained in the article )

If you want to use Gii just enable it in main.php. You can create files in common ( e.g. enter common.models as model path )

4) For apache do some virtual host configuration :

FRONTEND :

<VirtualHost *:80>
    DocumentRoot "c:/wamp/www/root/frontend/www"
    ServerName sp.com
    ServerAlias www.sp.com
</VirtualHost>

BACKEND :

<VirtualHost *:80>
    DocumentRoot "c:/wamp/www/root/backend/www"
    ServerName admin.sp.com
</VirtualHost>

On windows you need to add following to your hosts file:

127.0.0.1 sp.com
127.0.0.1 admin.sp.com

If you're on production, don't forget to add subdomain to your DNS conf ( CNAME or A record )

That's all. Now you can access your frontend : www.sp.com and Backend: admin.sp.com

#9194 report it
Alex.Sh at 2012/07/27 05:11am
Sample/Source

Would be greate to have working source or more detailde tutorial of this architecture.

It's possible to use it on shared hostings and how?

#9157 report it
TBIKC at 2012/07/24 03:00pm
there is an example of this architecture?

please give me a link to the source code

#8891 report it
hnam at 2012/07/06 06:43am
Getting confuse

Instructions are not so clear creating to much confusions. please upload a video if can or provide a proper documentation for same according to latest yii version.

#7742 report it
Jason K at 2012/04/13 12:59pm
Suggestions for Path Aliases

This is a great article and we are using this structure in a business application.

A suggestion I have regarding the Path Alias is to use 'root' instead of 'site'.

The reason for this is we have a module named 'site', so attempting to use an alias of something like 'site.common.models.*' inside of an application that has a site module, would be ambiguous and choose the module over the root path incorrectly.

Instead, we can do the following at the top of each application's config file: Yii::setPathOfAlias('root',realpath('../../'));

Then, within the config file: 'import'=>array( 'root.common.components.*', 'root.common.models.*', ... )

#7551 report it
JFReyes at 2012/03/29 10:57am
What about Gii?

I'd like to use this structure but would like to keep using Gii as well. Is it possible?

#6028 report it
isreal at 2011/12/06 02:40pm
modules url

Hi all,

I am implementing this structure on my project but I have an issue with a module, how can I redirect from backend to a controller on ..common/modules/app/controller ?

i expect you understand what I am talking

#4624 report it
resurtm at 2011/07/27 02:14am
Tests?

What about tests? Should i create separate standalone application called tests for them or just create tests folder in each application directory? Which solution will be painless and extendable?

#4482 report it
Ivica at 2011/07/13 02:46am
Look good for bigger projects

I like this folder structure idea, it look for me more natural to have backend folder for all administrative tasks, then using module. Off course this have sense only for bigger projects, because it will take some time to setup this structure, and more time to maintain/deploy it.

#4322 report it
Joe Storm at 2011/06/25 11:24pm
what is a difference between this?

I am doing this now : http://www.yiiframework.com/wiki/63/organize-directories-for-applications-with-front-end-and-back-end-using-webapplicationend-behavior/

What is the main difference between this setup? I am too new to see the bigger picture..

#4158 report it
pcs2112 at 2011/06/10 06:31am
Entry script

Qiang,

Something is not clear to me, does each application have its own entry script under /www ??

e.g

index.php for the frontend app, admin.php for the backend app, etc

#3853 report it
Cherif at 2011/05/13 08:31pm
A sandbox

Hi I tried to do this configuration to build a cms but i have some issues espacialy with the assets sttuf a sandbox for this organisation will be appriciated. Good article.

#3763 report it
revo110 at 2011/05/05 11:24pm
Few things left to be cleared.

Hi I do not see where did you include the main.php(from the common config folder) in the bootstrap file of the frontend application(index.php)?

And I assume, that the backend application will have its own bootstrap file with the same name e.g: index.php, right?

Thank you!

#3306 report it
R.K. at 2011/04/01 11:07am
Translations

There not mentioned translations, where i need to put all translations, and how to set in configuration? i tried save translations in /common/messages/ but backend or frontend applications can't access to that directory.

bellow is part of common/config/main.php

'message'=>array(
            'class' => 'CPhpMessageSource',
            'basePath'=> 'site.common.messages',
        )

also i tried and not worked. :?

'message'=>array(
            'class' => 'CPhpMessageSource',
            'basePath'=> dirname(__FILE__) . DS . '..'. DS  . 'messages',
        )
#3192 report it
Seal at 2011/03/25 02:38am
Create Directory Structure

@lightglitch

I found this to be useful ;)

mkdir -p enterprise/{backend/{components,config,controllers,lib,models,runtime,views/{layouts,site},www/{assets,css,js}},common/{components,config,lib/{pear,yii,zend},migrations,models},console/{commands,config,runtime},frontend/{components,config,controllers,lib,models,runtime,views/{layouts,site},www/{assets,css,js}}}

or if you prefer, you may use the top level directories down approach:

mkdir -p backend/{components,config,controllers,lib,models,runtime,views/{layouts,site},www/{assets,css,js}}
mkdir -p common/{components,config,lib/{pear,yii,zend},migrations,models}
mkdir -p console/{commands,config,runtime}
mkdir -p frontend/{components,config,controllers,lib,models,runtime,views/{layouts,site},www/{assets,css,js}}
#3167 report it
lightglitch at 2011/03/23 10:52am
Sandbox?

A sandbox containing this structure would be nice.

Leave a comment

Please to leave your comment.

Write new article