19

I'm trying to figure out the directory structure for a php website.

The website will use:

  • a very basic php MVC framework (namely, MinimalMVC, but I'm looking for a generic solution, so the framework can probably be ignored)
  • composer to manage PHP dependencies
  • SCSS for styling
  • gulp to compile the SCSS (for the dev build), and to also minify and concatenate JS and CSS output as well as minify images, etc. (only for deployment build)
  • Travis CI for CI stuff

So after a lot of thinking and planning and looking at issues with different kinds of directory structures that I came up with, I still cannot find something that meets my criteria:

  • gulp deploy should be able to generate a deployment folder, which when put into a /var/www/html/ directory on an Apache server, should Just WorkTM

    Note: MinimalMVC (and also CodeIgniter and other similar frameworks) require their index.php file in the root directory, with an app and sys folder in the same directory

  • Since the PHP is never really processed by the build process, it would be great if needless copying of the src/**/*.php files into something like build/**/*.php was avoidable. Basically, the PHP part does not keep gulp, I'd prefer for it to remain unaffected by gulp.

Now, my thoughts are a little bit of a mess because I've been thinking about this too much, so forgive me for this question being a bit of a mess too, but the basic question is, how should the directory structure look?

An idea:

. |-- composer.json |-- gulpfile.js |-- package.json |-- src | |-- app | | |-- controllers | | |-- models | | `-- <other_framework_stuff> | |-- assets | | |-- css | | |-- img | | |-- js | | `-- raw | | `-- scss | |-- index.php | `-- sys | `-- <framework_stuff> |-- test `-- vendor `-- <composer_stuff> 

In this structure, the developers only work within the /src directory. The SCSS gets compiled from /src/assets/raw/scss/ to src/assets/css. This way, the PHP remains removed from the build process. When trying to generate a deploy directory, the src folder is copied over, the /src/assets/raw/ (so no /build/assets/raw) directory doesn't exist, and the production/deployment ready CSS, JS and images are found in /build/assets/.

The first problem with this solution is the weird src/assets/raw directory, which seems ugly imho. The second problem is the /vendor directory. This means that the php references stuff from outside src. So if /src/index.php is taking care of it, it would include ../vendor/autoload.php. Then that would mean the same code gets copied over into /build/index.php. And then /build/ won't run by just dropping it into /var/www/html, unless vendor is in /var/www which just seems weird.

There's a lot of other stuff I've thought of, but all of it seems ugly some way or the other. To avoid making this question too long, I'll stop here.

Help, please. Should I just put vendor into /src/ using vendor-dir in composer.json? (I know, eww.) What sort of a directory structure should I use?

5
  • 4
    You should take inspiration from existing frameworks, for example Laravel uses a structure pretty close to what you are doing: laravelbook.com/laravel-architecture BTW, if you can, I'd recommend not having the vendor folder in your build directory, and running composer install in your production server instead. Commented Jul 16, 2015 at 15:05
  • 2
    Agree with the @Korri's comment. As long as you commit your composer.lock file, composer install should not take long when you deploy.Not directly related to your question, but the main thing I would change would be separating what actually gets accessed statically from the web server from src. That will protect you from users trying to directly access php files, which is where many security issues happen. The web server would be configured to access a public directory as the document root. Most frameworks follow that way of setting up. Commented Aug 17, 2015 at 16:11
  • I usually have a boilerplate directory in the root of my app, which contains development assets, like less, javascripts, bower.json, packages.json, fonts, images, and then I either use grunt or gulp to process them and send them to dist/ directory. Commented Aug 28, 2015 at 13:05
  • put your index.php inside a folder. /public/index.php .. i think a good framework should allow the developer to choose the best directory structure. for example in Laravel you can do what ever you want with the directory structure. the behavior of the framework should never affect the directory structure, it should be easily customizable. Commented Sep 4, 2015 at 6:13
  • @astroanu "framework should never affect the directory structure". Many argue the opposite ("convention over configuration" is touted by the Ruby on Rails folks). I'm not saying either is "correct", there are strong cases for convention over customization: you can start straight into learning "here's how to do A" instead of first having to learn the many ways A can be accomplished and then choosing the one appropriate to you. Another reason is that if you work with those conventions in one org, you can expect them to remain the same elsewhere. Finally, configuration requires more code (bloat). Commented Mar 28, 2018 at 21:47

1 Answer 1

16

I agree with the comment from Korri above, in that you could benefit from taking inspiration from existing frameworks.

Personally, this sort of directory structure feels right, to me.

. |-- composer.json |-- gulpfile.js |-- package.json |-- changelog.md |-- readme.md |-- /src (This is the API code that *I'm* responsible for, and that I *own*.). | |-- /app | | |-- /controllers | | |-- /models | | `-- <other_framework_stuff> | /public (Keeping this outside of the src dir, means that you can give this to your front-end devs without needing to have the entire codebase). | | |-- /styles | | |-- /images | | |-- /js | /config (Put all configuration files outside of the src scope, so you can keep it outside of source control) | /build (CI build related configuration) | | |--phpcs.xml | | |--phpdocx.xml |-- /tests (separating out your tests in this way can help you run tests separately, more easily) | | |--acceptance | | |--integration | | |--unit |-- /vendor (Depenedencies installed via Composer) 

Really, there's no community driven correct answer to your question. The correct answer is specific to your business, the team you work in, and the project itself.

I'd never put the /vendor directory within your /src directory - because you don't own it. You're not responsible for the changes to the code within your project's dependencies, so it should be left in its own scope outside of your projects walls.

With PSR-4 autoloading, it really doesn't matter too much about your directory structure, it can be changed easily at any time, with no impact on your code. So, experiment and see what feels right for you.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.