I found a standard Yii app's protected
folder structure nearly perfect. With a few simple moves and a little bit change to the code, I managed to bring it to the level, which I found as fully perfect. I want to share my point of view, in case someone would like to use this structure as well.
Some remarks
Note, that this is purely organisational approach. I don't think, that changing your application protected
folder structure will influence security or performance (in both negative or positive meanings) as well as any other aspect except code organisation.
Since some folders are separated into subfolders, I was able to resign from adding something to class names. For example, contact form model was renamed from ContactForm
to just Contact
, because it is separated from data models in models/form
subfolder. This means purity and simplicity for me, but my lead to classes names' conflicts more often. Keep that in mind.
components
folder
In default Yii application, virtually anything that looks similar to the component is kept all together in the protected/components
folder. I found this less useful, so I proposed to separate this folder into three subfolders:
- extenders -- all classes, that extends framework's base classes, for example
Controller
, - functions -- classes, that acts like common function repositories,
- widgets -- self-explanatory.
Changing structure this way, you have to also change small part of your app's configuration. I.e. change:
'import'=>array ( 'application.components.*',
to:
'import'=>array ( 'application.components.extenders.*', 'application.components.functions.*', 'application.components.widgets.*',
Using this structure, I was able to resign from adding for example E
to class names to distinct them from base classes (with C
in the beginning of a name). So base controller (but extended from CController
) remained named as Controller
(just like in auto-generated app) and CWebUser
, extended by me, remained just WebUser
, without need to rename it to EWebUser
.
models
folder
Similar change goes for models. Default Yii code organisation keeps all models together and distinguish form models from data models by adding Form
into form models class name. That was something, that I didn't like from the very beginning, so I split protected/models
folder structure into two subfolders:
- data -- all data related models`,
- form -- models for all forms.
Similar change to application's configuration must be taken here. Change:
'import'=>array ( 'application.models.*',
to:
'import'=>array ( 'application.models.data.*', 'application.models.form.*',
And also take all side-effects (name simplification as advantage and possible name conflicts as disadvantage) into consideration.
views
folder
There were some forum rummors a year or two ago, that putting layouts in the same structure level as all other controller-related views might be sometimes confusing. I fully agree with that. Situation gets even worse, if you're using widgets, that renders some views. So, to cleanup protected/views
folder structure, I've separated it into three subfolders:
- controllers -- moved all other views' folder here,
- layouts -- remains untouched, as in original, auto-generated app,
- widgets -- views for possible widgets.
Views that are general or application-wide (for example error.php
) are kept in original place, i.e. directly under protected/views
folder, without further spearation to some folder. But, you may consider creating general
subfolder and keep them there.
To make your application working with new views
folder strucuture, this time you don't change nothing in app's config. Instead, you have to modify your base controller (protected/components/Controller.php
in original Yii structure or protected/components/extenders/Controller.php
in above presented), i.e. the one from which all your app's controllers extends from.
All you have to do, is to copy there getViewPath
function's code, taken from Yii sources and modify path returned in it:
public function getViewPath() { if(($module = $this->getModule()) === null) $module=Yii::app(); return $module->getViewPath().DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$this->getId(); }
This will force all your controllers (all extending from this base controller) to look for their views in protected/views/controllers
subfolder.
Summary
Changes introduced here requires only a few minutes of work, but might result in cleaner (better in my opinion) folder structure. If you like my approach, go ahead and feel free to implement it in your own application. Good luck! :]