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:
~~~
[php]
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](http://resurtm.kz/extensible-yii-directory-structure)
[Chinese Version](http://www.itkuaixun.com/bbs/thread-39-1-1.html
"中文版")