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.
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.
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.
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 applicationconfig: contains the configuration used by the applicationcontrollers: contains controller classeslib: contains third-party libraries that are only used by this applicationmodels: contains model classes that are specific for the applicationruntime: stores dynamically generated filesviews: stores controller actions view scriptswww: the web root for this applicationThe 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 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.
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();
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.
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.
Total 20 comments
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:
and in my apps i use simply: 'theme' => 'whatever'
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:
and
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?
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
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:
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 :
BACKEND :
On windows you need to add following to your hosts file:
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
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?
please give me a link to the source code
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.
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.*', ... )
I'd like to use this structure but would like to keep using Gii as well. Is it possible?
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
What about tests? Should i create separate standalone application called
testsfor them or just createtestsfolder in each application directory? Which solution will be painless and extendable?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.
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..
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
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.
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!
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
also i tried and not worked. :?
@lightglitch
I found this to be useful ;)
or if you prefer, you may use the top level directories down approach:
A sandbox containing this structure would be nice.
Leave a comment
Please login to leave your comment.