Organizing your code with folders

Published on and tagged with cakephp  configuration

If you have, for example, a lot of model classes and you wanted to organize them with folders, you had to add the path for each folder to the $modelPaths array in /app/config/bootstrap.php like:

$modelPaths = array('/path_to_model_folder_A/', '/path_to_model_folder_B/');

Thanks to some recent changes in the development branch this is no longer necessary. You can now create as many folders as you want within the “/app/models” folder, and CakePHP will automatically find the models in those folders. So you could have a structure like:

/app
    /models
        /A
        /B
            /C
            /D

A model can now be in the “models” folder as usual, or it could be in one of the other folders (A, B, C, or D). It doesn’t matter. And in your code you do not have to care about in which folder a model is stored, you use your models as usual.

What I described for models also works for controllers, components, and helpers (and probably behaviors, but I didn’t test it with them).

28 comments baked

  • Tarique Sani

    Wonderful – being lazy here – but does putting controllers inside a folder affect the URL?

    If it does that would be indeed doubly wonderful

  • cakebaker

    @Tarique: No, it doesn’t affect the URL.

  • Nils Hitze

    This will definitly help, thanks for the tip.

  • Nik Chankov

    Nice approach, now I have hudge project and I was wondering how to separate everything without building tons of pluings.

  • Chad Weaber

    good tip. I just wish modelPaths worked in app controller :/

  • Zonium

    Being able to put models, controllers, etc. into folders and have them loaded auto/dynamically will help us better organize our code. We can’t afford to have a large amount of controllers (or models) in the same folder.

    ( In fact, before this feature becomes available in 1.2 I have used this similar approach for some projects
    http://bakery.cakephp.org/articles/view/flexible-controller-and-modelpaths )

    However, I still feel that the current cake’s app structure – separating Model, View, Controller at the application level no mater how big your application is – is not the best organization method in many cases.

    We often want to organize our application into smaller ones (think sub-applications or features), each has its own MVC structure for the sake of easy development , delegation and maintenance. Usually one such sub-application has some of its own set of logic, data and related resources such as images, swf and fla files, css and js etc.
    js and fla files may contain a large amount of code to maintain in development environment (take flash based shopping cart as an example).

    When we develop a new feature or update an existing one we have to touch multiple pieces of code, both back-end and front-end. Having to find /remember all related files which reside in multiple locations is not fun and even significantly slows down the development process (we’re targeting rapid development, aren’t we?)

    Our front-end developers often complaint about having to put all their code and supporting resources in predefined places in webroot. To make some simple change for a SINGLE feature of the site they have to look into different places (views, js, css, img etc.), and because these places are shared by the WHOLE application, there are ton of files (that do not belong to the feature) that the developers have to search through. Yes, they can put them in sub-folders but these folders are still not in the same umbrella representing the feature.

    We really want to place front-end stuff closer to, or in the same place as back-end stuff which includes related Models and Controllers, to save our time.
    We’ve got to find our own way to more or less accomplish this, but we wish the fragmentation issue in Cake’s app structure is noted and solved.

  • Vladimir Luchaninov

    @Zonium: use .htaccess and mod_rewrite

  • cakebaker

    @all: Thanks for your comments.

    @Zonium: Sounds like you are looking for plugins, as each plugin has its own MVC structure. I am not sure whether they have their own webroot now (a corresponding ticket, https://trac.cakephp.org/ticket/1897, is still open), you may have to ask one of the devs. It is possible it has been added in the meantime.

  • titang

    This is a great feature. Does this work for the “elements” folder? I work on a project with more than 60 elements in “elements” folder. i planned to organize it by using folder, but i was discouraged to rename all the references in the project…

  • cakebaker

    @titang: No, it doesn’t work for the “elements” folder, you still have to specify in which folder an element is located.

  • Zonium

    @cakebaker:
    I have used plugins, I know plugins enable implementation of separate MVC packages. However, there is paradox: while the plugins in cakePhp are meant for self contained sub-applications (sharing models with the main application is not expected), all front-end stuff (js, css, img) are tied to the main app (they got to be in the main app’s webroot).

    There were some requests to increase the flexibility of plugins
    http://groups.google.com/group/cake-php/browse_thread/thread/8526219c24ce3a8b/0d8ff47ad5e89faf?lnk=gst&q=plugins+gwoo#0d8ff47ad5e89faf

    and some positive responses:

    http://groups.google.com/group/cake-php/msg/17895d05b0a65397

  • DarkRyder

    Although I needed no modification by adding $modelPaths as suggested, or in this case $controllerPaths, sub folders worked fine and correctly found the file.

    However the class declaration “class Comment/commentController”

    has led to this error:

    Parse error: syntax error, unexpected ‘/’, expecting ‘{‘ in [omitted path to app]/app/controllers/comment/comment_controller.php on line 2

    When using the bootstrap method doesn’t find the controller in the sub folder.

  • cakebaker

    @Zonium: Yes, it seems plugins are a bit restricted.

    @DarkRyder: Why do you want to create a “Comment/commentController”? If you use subfolders then the controllers are named as usual, in this case it would be “CommentController”.

    HTH

  • Dieter
  • Brandon P

    @Dieter:
    Great read! It’s nice to see people discussing these kinds of issues which test the limits of cake!

    You mentioned naming conflicts in one of your replies and I agree this is a serious hindrance of cakephp’s extensibility. Even within it’s own code base there are serious conflicts. For example, just one I ran into:

    Controller Model vs. Component
    ————————-
    EmailsController
    var $uses = array(‘Email’);
    var $components = array(‘Email’);
    Question: What does $this->Email reference to in the EmailsController?

    IMO, there needs to be a better way to (generically) namespace parts of the cake core and 3rd party classes. Vendor apps, plugins, etc would catapult the framework to a whole new level.

  • cakebaker

    @Brandon: I agree with you that this is a problem. Any idea how this could be solved (without waiting for support of namespaces in PHP)?

  • brandon

    @cakebaker
    I think the problem can be solved in 2 parts:

    1. There is a need for more strict assignment conventions of components and helpers. It would also help remove much of the ambiguity when reading code:

    $this->component->Email->send();
    $this->helper->Form->create();

    One could even take it as far to make a static/ad-hoc class to load these classes dynamically and store them as singletons (those that don’t need to be injected into cakes runtime process … ie. for callbacks).

    2. Assignments of components and helpers should work in similarity to how models are constructed. A person should be able to “plug-n-play” different components that share the same basic functionality. For example:

    var $components = array(‘Acl’ => array(‘className’ => ‘MyAclComponent’));

    This way if you decide to switch the Acl component out you aren’t left with having to search & replace all “$this->Acl” with “$this->MyAcl”.

    I think there should be more of a movement into making abstract API’s so there can be multiple classes that are 100% interchangeable. A good example would be a jQueryAjaxHelper that uses jQuery (instead of prototype) for Ajax.

    Btw, here are a few more examples of possible conflicts:

    Helper vs. Controller::set()
    —–
    var $helpers = array(‘List’);
    $this->set(‘List’, array(1, 2, 3)):
    Question: What does in the view print out?

    Model vs. Core Lib. Class
    —–
    Model: Folder (references folders table)
    Question: What happens when you do uses(‘folder’)? Can you even USE the Folder class in the core?

  • cakebaker

    @brandon: Thanks for your answer!

    1) Yes, that’s a possible solution, even though it looks a bit ugly ;-) Another solution could be to forget the current concepts “helper” and “component” and to rethink it completely.

    2) I agree with you. Such abstract API’s would also help with testing, and the framework could provide mock implementations of core stuff for testing.

  • brandon

    @cakebaker

    Beauty is in the eye of the beholder :) I see the code and my brain goes “ah, thats a component because it says component”. But I agree with you that the concepts of both helpers and components need to be refined. Actually, IMO, you can add behaviors to that list too :)

    Why behaviors? Again, mainly because of naming conflicts. If you have two behaviors that have a semantically equivalent method names (which is legal in PHP) :

    Behavior1::test();
    Behavior2::test();
    Model … $actsAs = array(‘Behavior1’, ‘Behavior2’);
    Question: Which behavior does $this->Model->test() refer to?

    Not sure if this issue has been looked into or fixed but you can imagine how this would be a major conflict! I have already ran into the problem where you can’t have method names that match Model’s methods: read(), create(), etc.

    2. Glad you agree! I think more time should be invested into making 3rd party classes/packages work WITH cake (not along side it). The argument could be made that any class within cake can be extended — but you get into situations where sloppy programming can overwrite dependent code. I’d personally like to see cake branch off a PHP5 version and take advantage of these concepts and practices.

    Also, thanks for bringing up testing. That would be so great because then new classes/packages could be run against the core tests (there is no need for developers to create redundant tests).

  • cakebaker

    @brandon: Thanks for your answer!

    Yes, you can also add behaviors to that list. I always forget them, as I don’t use them very often ;-)

    2) Hm, I don’t understand what you mean with “making 3rd party classes/packages work with cake”. Usually, you don’t have any control about 3rd party classes and you cannot change them (well, you could change them, but if there is an update you have to re-apply your changes).

    I would like to see a PHP5-only version of Cake, too. Unfortunately, PHP4 is still widespread…

  • Tim Daldini

    Not sure if this is what Dieter or Zonium is also saying but I think it would be useful to group certain classes, (especially views and controllers) together…maybe even in the same directory.

    Sometimes I think it would be cool if controllers could be split up in that way that each action represents a file and these files could be grouped with corresponding views or something.

    But then again, that really resembles the ASP.NET codebehind concept…oh well.

  • cakebaker

    @Tim: Yes, sometimes it would be really useful if you could group certain classes together. At least to a certain degree you can do that with plug-ins or by setting additional view paths, but it is not very handy in my opinion.

  • Robby

    I tried doing this with controllers, and it worked nicely (be interesting to see what happens with name conflicts) – but its not working with views. Is it supposed to with views?

  • Pravin Gundawar

    Similarly how can we use multiple databases as we can organize models and controllers

  • cakebaker

    @Robby: No, this doesn’t work with views.

    @Pravin: You can define multiple database connections in app/config/database.php and then in your model you specify with the variable $useDbConfig which connection should be used by the respective model.

  • Peter Lombardo

    It’s a nice feature although a bit confusing. Usually there are many views to a single controller so grouping of views would seem higher priority if argued by pure number of files.

    We’re grouping controllers as mentioned above and in those controllers we have to specifically set $this->viewPath for cake to find the correct view which is also stored in a subdirectory below views.

    Maybe this is the planned process or is it just that the auto-find for views hasn’t been completed yet?

  • cakebaker

    @Peter: I think that’s the planned process. And as you already group the views by controller I don’t see the need for a more flexible way to organize views. But as I don’t know what features are planned, it is possible that such a feature will be implemented in the future. We will see :)

  • CakePHP Developer Links - PRONIQUE Software

    […] : ArticlesBrief Overview of the new EmailComponent | The Bakery, Everything CakePHP : Articlescakebaker » Organizing your code with foldersHow Easy Are Web Services in CakePHP 1.2? Really Easy! — @TheKeyboardDeprecated stuff in CakePHP […]

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License