When starting out with PHP, it can be daunting figuring out how best to organize a project. If you’ve ever been confused with where to put your images, external libraries, or keeping your logic separate from your layout, then check out these tips; they’ll get you heading in the right direction.
Tutorial Details
- Program: PHP/Projects
- Version: 1
- Difficulty: Easy
- Estimated Completion Time: 20 minutes
Directory Structure
I’d say the number one thing in getting your project up and running quickly is having a solid directory structure you can reuse for multiple projects. If you are using a framework, usually it will provide a structure to use, but in this scenario we’re working on a simple site or app.

Breakdown
-
You are probably very familiar with the
public_htmlstructure. This is the Document Root in which all your public files are accessed (/public_html/page.phpis accessed atexample.com/page.php).- img — All your image files. I decided to split content images from layout images.
- css — All your css files.
- js — All your javascript files.
-
The
resourcesdirectory should hold all 3rd party libraries, custom libraries, configs and any other code that acts as a resource in your project.- config.php — Main configuration file. Should store site wide settings.
- library — Central location for all custom and third party libraries.
- templates — Reusable components that make up your layout.
The Config File
As designers and developers our main goal is to do as little work as possible. One way to reach this goal is with config files. To get a better idea of what the configuration file should have check out this example.
<?php
/*
The important thing to realize is that the config file should be included in every
page of your project, or at least any page you want access to these settings.
This allows you to confidently use these settings throughout a project because
if something changes such as your database credentials, or a path to a specific resource,
you'll only need to update it here.
*/
$config = array(
"db" => array(
"db1" => array(
"dbname" => "database1",
"username" => "dbUser",
"password" => "pa$$",
"host" => "localhost"
),
"db2" => array(
"dbname" => "database2",
"username" => "dbUser",
"password" => "pa$$",
"host" => "localhost"
)
),
"urls" => array(
"baseUrl" => "http://example.com"
),
"paths" => array(
"resources" => "/path/to/resources",
"images" => array(
"content" => $_SERVER["DOCUMENT_ROOT"] . "/images/content",
"layout" => $_SERVER["DOCUMENT_ROOT"] . "/images/layout"
)
)
);
/*
I will usually place the following in a bootstrap file or some type of environment
setup file (code that is run at the start of every page request), but they work
just as well in your config file if it's in php (some alternatives to php are xml or ini files).
*/
/*
Creating constants for heavily used paths makes things a lot easier.
ex. require_once(LIBRARY_PATH . "Paginator.php")
*/
defined("LIBRARY_PATH")
or define("LIBRARY_PATH", realpath(dirname(__FILE__) . '/library'));
defined("TEMPLATES_PATH")
or define("TEMPLATES_PATH", realpath(dirname(__FILE__) . '/templates'));
/*
Error reporting.
*/
ini_set("error_reporting", "true");
error_reporting(E_ALL|E_STRCT);
?>
This is a basic drop-in config file. A multi-dimensional array serves as a flexible structure for accessing various config items such as database credentials.
- db — Store database credentials or other data pertaining to your databases.
-
paths — Commonly used paths to various resources for your site.
- log files
- upload directories
- resources
- urls — Storing urls can be really handy when referencing remote resources throughout your site.
- emails — Store debugging or admin emails to use when handling errors or in contact forms.
Using constants for commonly used paths makes include statements (require or include) a breeze, and if the path ever changes you’ll only need to update it in one place.
Using Different Config Files For Multiple Environments
By using different config files for multiple environments you can have relevant settings depending on the current environment. Meaning, if you use different database credentials or different paths for each environment, by setting up the respective config files you ensure that your code will work without hassle when updating your live site. This also allows you to have different error reporting settings based on the current environment. Never ever display errors on your live site! Displaying errors on the live site could expose sensitive data to users (such as passwords).
The Layout
Reusable templates are another big time saver. There are some great libraries for templating (such as Smarty), and I always encourage using such a library rather than reinventing the wheel. These libraries offer a lot of functionality (like helper methods for formatting currency and obfuscating email addresses). Since this is a simple site however we don’t want to take the time to setup the library and will be using the most basic of basic templates. We achieve this by including common sections or modules in to our site pages; this way if we want to change something in the header, like adding a link to the global navigation, it is propagated throughout the site.

header.php
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Simple Site</title> </head> <body> <div id="header"> <h1>Simple Site</h1> <ul class="nav global"> <li><a href="#">Home</a></li> <li><a href="#">Articles</a></li> <li><a href="#">Portfolio</a></li> </ul> </div>
rightPanel.php
<div id="siteControls"> <ul class="categories"> <li>PHP</li> <li>HTML</li> <li>CSS</li> </ul> <div class="ads"> <!-- ads code --> </div> </div>
footer.php
<div id="footer"> Footer content... </div> </body> </html>
index.php
Let’s say that we put all of our layout components (header, footer, rightPanel) in our resources directory under templates.
<?php
// load up your config file
require_once("/path/to/resources/config.php");
require_once(TEMPLATES_PATH . "/header.php");
?>
<div id="container">
<div id="content">
<!-- content -->
</div>
<?php
require_once(TEMPLATES_PATH . "/rightPanel.php");
?>
</div>
<?php
require_once(TEMPLATES_PATH . "/footer.php");
?>
Taking It Further
While this basic template system gets you off to a great start, you can take it a lot further. For instance, you can create a class or functions that include all the template files and accept a content file as an argument to render within the layout. This way you don’t need to keep including the template files in every page of your site, but rather abstract that logic out meaning even less work down the road. I’ll show you a quick example.
/resources/library/templateFunctions.php
<?php
require_once(realpath(dirname(__FILE__) . "/../config.php"));
function renderLayoutWithContentFile($contentFile, $variables = array())
{
$contentFileFullPath = TEMPLATES_PATH . "/" . $contentFile;
// making sure passed in variables are in scope of the template
// each key in the $variables array will become a variable
if (count($variables) > 0) {
foreach ($variables as $key => $value) {
if (strlen($key) > 0) {
${$key} = $value;
}
}
}
require_once(TEMPLATES_PATH . "/header.php");
echo "<div id=\"container\">\n"
. "\t<div id=\"content\">\n";
if (file_exists($contentFileFullPath)) {
require_once($contentFileFullPath);
} else {
/*
If the file isn't found the error can be handled in lots of ways.
In this case we will just include an error template.
*/
require_once(TEMPLATES_PATH . "/error.php");
}
// close content div
echo "\t</div>\n";
require_once(TEMPLATES_PATH . "/rightPanel.php");
// close container div
echo "</div>\n";
require_once(TEMPLATES_PATH . "/footer.php");
}
?>
index.php
This is assuming you have a file called home.php in your templates directory that acts as a content template.
<?php
require_once(realpath(dirname(__FILE__) . "/../resources/config.php"));
require_once(LIBRARY_PATH . "/templateFunctions.php");
/*
Now you can handle all your php logic outside of the template
file which makes for very clean code!
*/
$setInIndexDotPhp = "Hey! I was set in the index.php file.";
// Must pass in variables (as an array) to use in template
$variables = array(
'setInIndexDotPhp' => $setInIndexDotPhp
);
renderLayoutWithContentFile("home.php", $variables);
?>
home.php
<!-- Homepage content --> <h2>Home Page</h2> <?php /* Any variables passed in through the variables parameter in our renderLayoutWithContentPage() function are available in here. */ echo $setInIndexDotPhp; ?>
Benefits of This Method Include:
-
Greater separation of logic and view (php and html). Separating concerns like this makes for cleaner code, and the job of the designer or developer becomes easier as they are mostly working with their respective code.
-
Encapsulating the template logic into a function allows you to make changes to how the template renders without updating it on each page of your site.
Symlinks
On Unix based systems (os x, linux) there is a neat little feature called symlinks (Symbolic Links). Symlinks are references to actual directories or files on the filesystem. This is really great for when you have a shared resource, such as a library used between multiple projects. Here are a few concrete things you can do with symlinks:
-
Have two versions of your resource directory. When updating your live server you can upload your latest files into an arbitrary directory. Simply point the symlink to this new directory instantly updating your code base. If something goes wrong you can instantly rollback to the previous (working) directory.
-
Shared resources are easily managed with symlinks. Say you have a custom library you’ve been working on, any updates to the library you make in one project will be immediately available in another.
Using Symlinks
Symlinks vs Hardlinks
Symlinks, or softlinks, act as references to full paths on the filesystem. You can use symlinks in multiple locations and the filesystem treats them as if they were the actual file or directory they reference. Hardlinks on the other hand are pointers to a file on the disk (think shortcuts in windows); they take you to the actual location of the file.
There are a few things you should consider when using symlinks. Your server configuration must be set up to follow symlinks. For Apache this is done in the httpd.conf file. Find the Directory block and make sure that Options FollowSymLinks is there. If not add it and then restart Apache.
<Directory /> Options FollowSymLinks AllowOverride None </Directory>
Creating Symlinks in OS X
There are 2 ways to create symlinks in OS X:
-
Via the command line, navigate (cd, change directory) to the directory in which you want the symlink to be created, then use the following command:
$: ln -s /path/to/actual/dir targetDirSo if our custom library lives in
~/Sites/libraries/myCustomLibrarywe’d cd to where we want to use that librarycd ~/Sites/mySite/resources/libraryand enter:$: ln -s ~/Sites/libraries/myCustomLibrary myCustomLibraryNote that this method should work in all Unix based operating systems.
-
The alternative is through the finder. By holding alt + cmd while clicking and dragging a file, a Symlink (or alias in os x) that points to the file is created.
Creating Symlinks in Windows
To accomplish this in windows you’ll need to use the mklink command in the command prompt:
C:\mklink /D C:\libraries\myCustomLibrary C:\Users\derek\Sites\mySite\resources\library\myCustomLibrary
Summary
These tips are meant for beginners or those creating simple sites or applications. Ideally for larger applications or sites, you’ll want to consider something more advanced like the MVC architecture and Object Oriented programming. I encourage you to look into these once you’ve gotten your feet wet and feel that you’ve outgrown most of the steps above. I decided not to cover source control as it’s a pretty large subject on its own, but these tips should help you in organizing your files for easier source control if desired (hint: store stuff like layout images in your resource directory and symlink it into your /public_html/img dir). Definitely look in to using source control, like subversion or git for all of your projects.
Hope you find these tips helpful when starting your next PHP Project. Thanks!
Resources
- Smarty Templating Engine
- Multitier Architecture
- MVC
- Object Oriented Programming
- Subversion For Designers (version control)
- Symlinks
- Hardlinks
- Follow us on Twitter, or subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.

Derek,
I don’t know a thing about building a web site, with or without a framework. But I do know about technical writing; I write process and procedural scripts as part of my job. Your article incorporated the organization that you write about, making the article simply flow. Outstanding! Applying organization skills to any project allows us to reach success much sooner. You also sparked a lot of conversation and thought, and much gratitude!
I couldn’t be prouder!
Love, Mom
What a cool Mom, and for beginners it’s very important to understand the business of separating logic and view code well before going any where near a framework, if you understand PHP you should not need to use templates anyway. Nice work Derek A+ Bro.
thanks for this. I was just asking about program structure in PHP projects in IRC and didn’t really get a response.
Excellent article. Thanks for your good work! I want to take this opportunity and invite you all to use the free courses (PHP courses incl.) I develop available for free at http://www.abelski.com. Best, Haim.
This is very useful tutorial… Thanks, Derek.
Thanks for post. THis is just a basict. You should use a framework…
Very good..
Great post.
I have issue with the way you present a solution that provides a template directory, and then proceed to embed php code in them. I think that one of the hardest things for new php developers moving into the professional world and tackling their first large project is to learn how to separate presentation from application logic. I’ve been met with many a walleyed stare from a new developer when I try to explain how to use templating systems. I believe that this is truly the biggest thing keeping php from being widely accepted as an enterprise ready platform.
My opinion is that if you can’t manage to write a small template parser, then use something like Smarty or one of the HTML_Template_* pear packages. It will pay huge dividends for applications that might one day need to be changed, as well as really do a lot to clean up your code.
Nice to see how others get set up! thanks for this.
I would rather do it this way,
move config file to public_html
move images folder down to resources
Why, personal preference or ?
Ha ha I alreadydo this, I must be a web developer genius..(joke)
Very useful tut. I’ll surely grab these ideas for my next php project.
Can anyone advice on which is much better, going for personal organization of files or going to CodeIgniter?
Useful post for php Programmers. Thanks for sharing.
Very nice one I like it
Nice article!
Thanks for the useful information, it is nice to see how other developers organise their work.
what if i have a multiple data to be displayed? is there anyone can teach me how to do it…for example i will post 2 diffrent information like name 1 and name 2..
how can i loop this 2 in order to pass it to where i wanted it to be printed..
tnx a lot for the future help..tnx
hmm TEMPLATES_PATH doesnt see to contain a path. When I echo it theres nothing there but if I echo LIBRARY_PATH it shows up fine.
This is true when using the example code or my own.
Very strange, any ideas?
Awesome! But I think having tag in the start and ending of each file is not so useful. Say in a header file, you should have html/php tag required for that file only. Your proper tags should be in the file you are including in. Php will compose whole page for you
I’m actually fairly competent with PHP, but for some reason having issues with understand why index.php (in the public_html) is calling in ‘home.php’ as content to be rendered. I understand seperation of php/HTML, but does that mean if I want to create ‘about.php’ in my public_html folder, I’d also need to create an about.php in my /resources/templates folder for the actual content? It seems like double the work. I could easily be missing something, though.
ditto.
anyone have an explanation?
What an excellent tutorial… the one I was searching for, for a long long time.
How to start php projects i am newly entered into php projects so i need to know how i am going to start and how many folder i have to maintain plz let me know the correct directory structure of php .
I have single criticism. Thats in the part where you talk about creating symlinks
ln -s
Is not just for OSX it works on all major unix/linux distributions
adsd
Great post for me.
what the problem, I can’t found. show this warning and fatal error in localhost.
Warning: require_once() [function.require-once]: Filename cannot be empty in K:\xampp\htdocs\public_html\index.php on line 3
Fatal error: require_once() [function.require]: Failed opening required ” (include_path=’.;K:\xampp\php\pear\’) in K:\xampp\htdocs\public_html\index.php on line 3
pl z help me.
Hello!
thanks very much!
I am Spanish
always had problems when starting a project PHP clutter of files and folders kept me from finishing.
But with your help I believe that we managed to work well. Thanks
I know my questions about this GREAT article are very – extremely – basic… but the answers will surly save me some time… So:
1) how do I refer to the arrays defined in the config file (images->content and layout…) ((the correct directory path isn’t ‘/img’ in this example??)) f.e. when i insert a bg img in the css…
2) can someone help me with the exact connection string when I have 2 – a local and an online – server connection?
3) the titles usually change page-by-page, as the keyword… in the header i used: ?php if (defined (‘TITLE’)) {print TITLE;} else {print ‘Site Title Not Set.’; }? and define in the page files, my question. is there a better way doing this?
Thanx a lot!
instead of realpath(dirnam(__FILE__).”…/”) you can use $_SERVER['DOCUMENT_ROOT'] instead, right?
In Joomla directory structure they using dirnam(__FILE__).”…/”) however you may stick to old fashion $_SERVER['DOCUMENT_ROOT']
Im using the same technic. Do you have a solution for hiding the public_html folder in de url, so:
localhost/mywebsite/public_html/page.php
becomes
localhost/mywebsite/page.php
Im struggling like 3 days now with htacces bit not one clearly solution for me ..
Hope you could point me in the right direction
Very mature folder structure for PHP project beginner.
However it would be nice practice if you keep config file in outside from sub-folder.
As in MVC pattern keeping configuration file outside is common practice.
Hope this will be fine!
- Yogi Ghorecha
For security, you should move the config file above web directory. Especially when you forgot to change its permission.
Using WAMP server to follow this guide.
When i put the config.php outside the public_html the config does not run.
Although i set the path Can’t even get past the first part, great :(
Excellent article, is an excellent source of information for those just starting out and want to start right now! Congratulations!
I just can’t understand why my variable won’t pass trough templateFunctions.php to home.php…
I understand all the rest but…
if (count($variables) > 0) {
foreach ($variables as $key => $value) {
if (strlen($key) > 0) {
${$key} = $value;
}
}
}
Bug me allot… (this variable need to pass trough 2 php’s files !)
Super beginner in pass trough variable…
Ok It’s my fault… forgot an “s” at Variable`s`
Can you continue this super tutorial with include_once img/content, img/layout, css ? I’d love to know how to do it via variables call from index.php true home.php… and add .css to the template…
thank you very much!
Very good tutorial. Could someone post how to use the multidimensional array in config.php to reference an image?
I tried this:
<img class="hw_logo img" src= . “logo_banner.png” alt=”description” width=”400″ height=”141″ />
but it does not work.
Thanks.
hi,
sorry but something most important is missing from this tutorial…
as raised by some named [vin] above.
how do you map http://localhost/script.php ie.the localhost in your location() header to your website.com
my example:
header (“Location: http://” . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) .”register.php?jsc=1″);
this gives me: http://localhost/register.php?h=0
so when i go live and localhost is no longer there what does the above url look like? and what changes to the header() code above is required to have:
http://mywebsite.com/somesript.php
someone please explain in detail with example so that everyone can benefit.
thank you.
Thanks For giving me very good PHP framework..
Thanks. Very good article. Still after all this time many of us fight the same things. I realize taking the PHP code out of the root and starting to create a structure is key. I work on intranet stuff only but on a small/mid size project I ended up with lots of programs in the root (like personadd.php, personedit.php etc) and that’s when you learn that you gotta rethink the way you work.
I’m reluctant though (given the size of my projects) to adopt frameworks or to even roll out some full OOP solution of my own. I still love the fact of basic PHP simplicity, but taking necessary steps for modularity and security.
I also got some good information in this link:
http://paul-m-jones.com/public/organize-php-project-2007.pdf
I don’t understand how exactly is the array passed in the home.php page ? Because in the renderLayoutWithContentFile function it just loads the page it does not pass the array anywhere.
i don’t realy understand the meaning of /resources/library/templateFunctions.php
can somebody please explain it exspecally the new index.php file is seem like double work to me
$setInIndexDotPhp = “Hey! I was set in the index.php file.”;
// Must pass in variables (as an array) to use in template
$variables = array(
‘setInIndexDotPhp’ => $setInIndexDotPhp
);
renderLayoutWithContentFile(“home.php”, $variables);
Really great article, I find it very useful for beginners as me. Thank you very much!!