5

I'm in the very early stages of making an MVC web application. I want to try and do things composer style. Here is my directory structure so far:

public_html
    |-vendor
    |   |-MyVendorName
    |   |   |-DomainObjectClass.php

So that's where I am storing domain objects.

I'm also trying to do MVC as close as I can to the way it is done in the answer to this question

Where I am a bit stuck is where to put the Model, Controller, View, Services, DataMappers etc. Should I make subdirectories of MyVendorName (eg MyVendoreName/DomainObjects/DomainObjectClass.php and MyVendorName/Services/SomeServiceClass.php etc) or would it be wiser to make a directory separate from vendor called classes or src or something and do MVC stuff there?

Edit: Everyone is saying that vendor is for third party libs, I get that. But the way I am writing my domain objects is very decoupled from the MVC side of things. In fact, they do not even know they are part of an MVC app. They could very easily be reused in other projects (I intend to do this). So it seems illogical to me to put it in src/ or app/

Community
  • 1
  • 1
Cameron Ball
  • 4,048
  • 6
  • 25
  • 34

5 Answers5

4

This is an extremely debatable topic and there's no one right answer. However, I'd dispense the following hints:

  • the vendor directory is for third party dependencies, you should not be writing your own code in it
  • put your own code in a src or lib directory, next to the vendor directory
  • neither of these directories should be in the public webroot folder; the webroot should be a separate directory containing only publicly served files like CSS and JS files, anything else is outside the webroot
  • structure your class names in namespaces
  • from the namespaces follows the directory structure
  • explicitly having a MyVendorName\Controller, MyVendorName\Model etc. makes sense
  • structure as deeply as makes sense, e.g. MyVendorName\Model\DomainObjects\Foobar\Subclass makes sense
deceze
  • 510,633
  • 85
  • 743
  • 889
  • I am currently doing most of what you suggest. However, look at my edit about the vendor directory, what do you think? – Cameron Ball Jun 10 '14 at 16:53
  • Yes, I see your point. I've done the same thing on occasion. In fact, I think it's a pretty good idea to try to abstract things into a framework or independent libraries if they're suited for it; it makes things more reusable and really helps you to ensure your code is decoupled. So it does belong into the `vendor` folder, if you're actually treating it like a 3rd party library and are installing it using the same `composer require` mechanism. – deceze Jun 10 '14 at 17:12
1

I would suggest this approach:

project_dir
    |-vendor
    |    -(vendor directories, installed via composer)
    |-public_html (images, javascript, css, html files/angular views)
    |-app

Inside of your app directory is where you put your PHP code. Inside of there you can organize your controllers, services, data mappers however you like, but this structure provides a strict separation between what should be accessible from the outside (public_html) and what should only be executed by apache or cli (everything else).

As @deceze said, though, besides breaking out the vendor directory and the public directory, how you organize your application code is wholly up to you and should match whatever is most appropriate for the task you're attempting to accomplish.

Jeff Lambert
  • 24,395
  • 4
  • 69
  • 96
1

Application

It depends on you, how you want to structure your application. It's a good practise to put your stuff inside a src or app folder. MVC is just a helper method providing a more or less clean folder structure for it. You should read about PSR and namespaces, to understand how to name your classes. If you follow PSR standards, you get a direct relation of folder names, file names and namespaced class names inside these files.

/src
 - /controller
    - ModuleAController.php
    - ModuleBController.php
 - /model
 - /helper
 - /view
 - bootstrap.php
 - config.php
 - index.php

or

/src
 - /core
      - corefiles.php
      - ...
 - /modules
    -/aModule
      - /controller
      - /model
      - /helper
      - /view
 - bootstrap.php
 - config.php
 - index.php

Composer

Composer is a package manager. You can fetch packages with it. These packages are stored into the vendor folder. Packages are defined inside the composer.json file of your project. You might define two seperate require sections: require, which defines the dependencies for your project, and require-dev, which defines the dependencies only needed for the development of your project.

Composer acts also as an autoload generator, for your whole project (your app and all it's dependencies).

{
    "autoload": {
        "psr-4": {"YourApplicationNamespace\\": "src/"}
    }
}

You simply have to require composers autoload file from the vendors folder in the bootstrap of your project.

require 'vendor/autoload.php';

If the components are standalone and reusable, you might create them as seperate composer packages and require them in your main application. This would for instance work for a "logger" package. Some of framework projects compose their main project this way.

Composer Custom Installer

If components are coupled to a common base layer (CMS or Framework), you might utilize a custom composer installer, so that packages get installed into the correct folder. You find a lot of folder layouts and structure information here: http://github.com/composer/installers

project
  -vendor
      -(packages installed via composer)
  -public_html (assets and main index.php)
  -src
    - core
    - helpers
      (composer packages for this application, installed into specific folders)
    - themes
       - sunshine (theme package installed into themes folder)
    - modules
       - guestbook (module package installed into modules folder)
Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
  • I know what composer is and how to use it. My domain objects are so standalone that they can be their own package. Check out my edit and let me know what you think. – Cameron Ball Jun 10 '14 at 16:54
0

I included an example below that you might like. When deciding on my directory structure, I came across a helpful post here: https://softwareengineering.stackexchange.com/a/123320

/app
 - /controller_http.php
 - /controller_cron.php

/data  # content uploaded by users or generated by scripts

/lib
 - /[MyName]/Controller/
 - /[MyName]/Myclass.php

/test

/vendor
 - /[vendorName]/assets/images/
 - /[vendorName]/ClassName.php
 - /[VendorName]/Module/

/www  # or /public_html
 - index.php
 - /css
   - [theme name]/stylesheet.css
   - [theme name]/images/ # images specific to a theme/stylesheet
 - /images # general images for any theme
 - /js

.gitignore
bootstrap.php
composer.json
licence.txt
README.md

The application might be run from different contexts, for example:

HTTP request from a browser: index.php includes controller_http

Cron Job: controller_cron.php is called directly

API call: controller_api.php called from www/api.php

In each case, the controller would include bootstrap.php to define directory paths and other hard coded configuration. It would then run the appropriate scripts based on the request parameters or command line arguments

Community
  • 1
  • 1
Frank Forte
  • 2,031
  • 20
  • 19
-2

Here is an example of an MVC app written in PHP and which closely follows MVC principles:

https://github.com/fulldecent/cameralife

The developer guide explains how MVC is organized and applied in the file: https://github.com/fulldecent/cameralife/blob/master/CONTRIBUTING.md but it is summarized below.

File storage:

  • /.htaccess -- sends all requests to index.php
  • /index.php -- sets up PSR-4 autoloader and sends all requests to a controller
  • /vendor/ -- stuff you get from Composer
  • /assets/ -- images and css files (feel free to use /images/ and /css/)
  • /caches/ -- temporary files (feel free to move this outside the webroot)
  • /photos/ -- please ignore, this is another place I store user content, which is specific to this photo sharing app
  • /sources/Controllers/ -- the routing target for each URL request
  • /sources/Models/ -- all data models
  • /sources/View/ -- Controllers use these and pass in Models, they usually print HTML
William Entriken
  • 37,208
  • 23
  • 149
  • 195