Sparkmasterflex’s PHP Project Boiler Plate

Spread the word
Tweet about this on TwitterShare on Google+Share on FacebookPin on PinterestShare on RedditShare on TumblrEmail this to someonePrint this page

In this post I want to give an insight into my PHP workflow and project setup. It utilizes PHP, HTML5 Boilerplate, GruntJS, CoffeeScript and SASS.

Unlike Ruby on Rails standard PHP sites don’t really have a standardized structure that everyone follows. This is due to PHP not being a framework but rather just a programming language. There are, however PHP frameworks out there, such as Laravel, CakePHP and CodeIgniter. But all of these are generally overkill for most PHP based websites. Hence my boiler plate…

I have updated the GruntJS portion of this PHP boilerplate with some really nifty changes. See them here. — updated 8/12/2014

Get the code by using git clone command:

  $ git clone git@github.com:Sparkmasterflex/php_boilerplate.git <project-name>
  $ cd <project-name>

Let’s take a quick look at the file structure:

PHP Boiler Plate File Structure

Why don’t we break it down.

Images

Pretty straight forward for anyone who’s done any web development. Though everyone organizes their image assets differently, I like to set mine up like this.

  • images/
    • icons/

      This is for common icons that you may have to help the user navigate your site. This becomes more relevant if you’re building an application but I still use icons in most of my regular websites as well.

    • slideshow/ (if applicable)

      This directory is not included in the git project because its not always needed, but if you are using a JavaScript slide show like jQuery Cycle Plugin then this makes sense.

    • ui/

      Here I store things like background images, patterns, etc.

Includes

This directory contains three files, _footer.php, _header.php and functions.php.

_footer.php and _header.php contain markup required for an HTML page. Both contain HTML pulled from the HTML5 Boilerplate, but I have made some modifications to fit my needs. Don’t worry about the _ at the beginning of these two files, this is just a Rails habit that I like. Basically any file that begins with the underscore you know at a glance is a partial of a page that is being included.

_header.php

  <!doctype html>
  <html class="no-js">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="keywords" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Place favicon.ico and apple-touch-icon(s) in the root directory -->

    <link rel="stylesheet" href="/stylesheets/vendor/reset.css">
    <link rel="stylesheet" href="/stylesheets/main.css">
    <script src="/javascripts/vendor/modernizr-2.8.0.min.js"></script>
  </head>
  <body>
    <!--[if lt IE 8]>
      <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
    <![endif]-->
    <header>
      <section>

      </section>
    </header>
    <div id="content">
      <section>

This uses the HTML5 tags <header> and <section>. The <section> tag, in my boiler plate is used to house and manage the width of the site’s content. Look into the base.scss file to see the styles of this <section> tag.

_footer.php

  </section>
  </div>
  <footer>
    <section>

    </section>
  </footer>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>window.jQuery || document.write('<script src="/javascripts/vendor/jquery-1.11.0.min.js"><\/script>')</script>
  <script src="/javascripts/base.js"></script>

  <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
  <script>
    (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
    function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
    e=o.createElement(i);r=o.getElementsByTagName(i)[0];
    e.src='//www.google-analytics.com/analytics.js';
    r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
    ga('create','UA-XXXXX-X');ga('send','pageview');
  </script>
</body>
</html>

In the functions.php file I add any standard functions that may be used by the website. Good examples of functions to expect in this file are form validation functions, emailing contact forms and various view helper functions. Let’s take a look what we got in here as of now:

  <?php
  /*
   * Contact forms post to this file
   *   => this handles this post from an $.ajax request
   */
  if($_POST) {
    header('Content-Type: application/json');
    echo json_encode(mail_contact($_POST));
  }

  /* An easy way to include a partial housed int the includes directory
   *
   * Parameters:
   * $partial::String
   */
  function render($partial) {
    include $_SERVER['DOCUMENT_ROOT'] . "/includes/_" . $partial . ".php";
  }

  /* Validates information required builds email and sends to given email
   *
   * Parameters:
   * $partial::String
   *
   * Returns:
   * Boolean
   */
  function mail_contact($params) {
    $name    = $params['name'];
    $email   = $params['email'];
    $message = $params['message'];

    if($name == "" || $email == "" || $message == "") {
      return false;
    }


    // creates body of email
    $body = "
      name: $name\n
      email: $email\n
      message:\n\n
      $message";

    // emails form and returns true/false base on success of email
    return mail("some@email.com", "Contact from example.com", $body, "From: $email") ? "true" : "false";
  }
?>

Javascripts

This directory contains coffee and vendor directories. vendor comes with latest minified version of jQuery and Modernizr and this is where you should put any other third party libraries, frameworks or plugins. If you haven’t ever used Modernizr, I highly recommend you look into it. Modernizr is a JS library for feature detection in browsers, basically it detects if, say, CSS animations are supported in the browser being used to view your website. It’s super powerful and helps with progressive enhancement.

The coffee directory houses any .coffee files you need. It is important that you store all your .coffee files in this directory for when we start up the GruntJS task runner. Grunt will be watching for these files within this directory for changes and will then compile them down into JavaScript that browsers can read and run. We’ll touch on that later in the post.

Not familiar with CoffeeScript? You’re in luck! Check out my three part series on it; install to syntax to features.

We have one file in the coffee directory and it’s just a standard base.coffee file. Let’s take a look:

  $ ->
    console.log "Sparkmasterflex's PHP Project Boilerplate"

    # for links to open in new tab or window
    $('a[rel=external]').bind 'click', () -> this.target = "_blank"

    # look for .hide class and set display: none
    $('.js-hide').hide()


    # handle's $.ajax post from contact form
    #
    # sends POST hash to url designated in
    #   'action' attribute of the form
    $('form#contact-form').submit (e) ->
      $.ajax
        url: $(e.target).attr('action')
        type: "POST"
        dataType: "json"
        data: $(e.target).serialize()
        success: (response) ->
          if response
            $(e.target).prepend "<p>Post successful and no validation errors</p>"
            console.log response
          else
            $(e.target).prepend "<p>Please enter all fields</p>"
        error: (err, response) ->
          console.log "An error occurred while posting."
          console.log err
          console.log response

      false

Stylesheets

Our stylesheets directory contains scss, vendor and src directories. scss holds all of our Sass files and vendor contains a reset.css. This is a local copy of Eric Meyer’s reset css that basically removes most of the default browser styles. Things like font-size, margin, etc for <p> and <h*> tags to name a couple. You could substitute in normalize.css if you prefer, but it doesn’t reset as much and I prefer the clean slate.

The src directory is really just where our .scss files are going to compile into standard .css files. We’ll use GruntJS and the cssmin plugin to combine and minify that css into a single main.css file that will be the only <link> tag we have in our HTML.

The .scss files contained in this boiler plate include:

  • base.scss

    Contains mostly styles specifically for DOM elements. e.g. <p>, <li>, <table>, etc. But it also is a place for very common classes with simple styles.

  • icons.scss

    Sets up different icon styles.

    • .icon for square DOM element with contents hidden and background image, with variations for different sizes.
    • .with-icon sets up an <(icon) text> object, again with variations for different sized icons.
    • Setup individual icon classes that only style the background-image. The idea here is to have an icon element contain a structure class (either .icon or .with-icon) and then a skin class, like .edit

      So <span class=”edit icon”>Edit</span> would hide the “Edit” and only show a pencil icon, for example

  • mixins.scss

    If you’re not familiar with mixins in SASS, I recommend you spend some time researching. They are a great way to DRY-up your SCSS/CSS. Here we have a lot of simple mixins that mainly handle browser prefixes. But there are a few nice snippets as well, such as:

    • @mixin square(): sets width and height to the argument passed.
    • @mixin hidden: sets text-indent to -9999px and overflow to hidden used in an .icon type scenario.
    • @mixin clearfix: creates a standard clearfix
    • and a few more…

    Add mixins here for any common blocks of styles you are going to use more than twice.

  • modules.scss and ui-elements.scss

    These are empty SASS files that are decently commented. Basically modules.scss is for elements in your website that you are using often. ui-elements.scss is where I put my styles for things like navigation, logos and pagination.

  • structures.scss and skins.scss

    I pulled this idea from OOCSS. The idea here is to keep all styles that alter the structure (i.e, width, height, margin/padding, etc) of a DOM element in structures.scss and things like color, background and fonts in skins.scss. I liked the idea of this but found it very hard to stick with it 100%. Mostly because I think it can be confusing for someone else coming into your code who is not familiar with OOCSS.

    In structures.scss, we have my version of a grid system. It’s super simple and everything is named out as .per-##, which stands for percent ##. There are a couple that are spelled out more, like .half, .full, etc. Also in here we have different classes for margins and paddings, as well as some hard sets for font-size

    skins.scss contain some standard color classes based on our color variables in mixins.scss

  • z-responsive.scss

    Lastly we have z-responsive.scss which is name so, so that it will be concatenated to the end of our main.css and therefore will over-write any similar styles above it. This file is for all of our responsive media queries.

index.php

The index.php is very simple and is really just a “Put content here…” type file until you Put your content here. For any additional pages on your website, such as an about page or a contact page, you would use this same template. Let’s explain what’s going on in this file.

  <?php
    require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.php";
    render('header');
  ?>

  <p>Hello world! This is HTML5 Boilerplate.</p>
  <!-- Add your site or application content here -->

  <?php render('footer'); ?>

require_once ... functions.php makes our PHP functions available to us in this page. This is very important for the next line; render('header');. The render() function grabs and includes our partial with the name that we pass. If you remember we have a _header.php and a _footer.php, so render('header') brings the _header.php where we specify.

The rest of this page is really just filler waiting for you to replace and amaze the world with your content.

GruntJS & Friends

Grunt is a task runner that I, and many others, use to run processes in the background while I develop. It can do so very many things and I really have only scratched the surface of its capabilities. In this boiler plate I have Grunt handling a very specific list of tasks that have already sped up my workflow by nearly double.

My Grunt does:

  • Compiles my CoffeeScript
  • Compiles my SCSS
  • Concats and Minifies my CSS
  • Watches all .php, .scss and .coffee files for changes
  • Refreshes my browser upon changes
  • For production:
    • Concats and Minifies my Javascript
    • Optimizes my Images

So how to use this wonderful tool? Well I’ll get into the nuts and bolts of it in a future post, because there is way too much to discuss in what is left of this post. This, however, does not mean that you cannot use Grunt to make your project fly in development. I already have Grunt configured to do the above within this boiler plate. If you wish it to do more or do something differently then you will need to alter the Gruntfile.js to fit your needs.

But let’s assume that you’re happy with what I proposed above and you want to get started. First step is to open up your terminal or command line application.

NOTE: This assumes that you have npm installed already. If you don’t already have npm installed then you also don’t have CoffeeScript installed and you will need both to for this boiler plate. See this post for instructions on how to install both. You will also need to have SASS installed as well. See here.

  $ cd /to/project/directory
  $ npm install
  $ grunt

Leave your terminal or command line application up and running while you work. Grunt will listen for changes in your .coffee, .scss and .php files and run the appropriate task at that time.

To use the livereload functionality of this boiler plate you must have this installed in Google Chrome. If you are using another browser you will need to research how to do so.

You will not need to do anything with the package.json file unless you really know what you’re doing and need to change what you want Grunt to do. Also once you have run $ npm install a directory named node_modules will be created in your project and will house all the plugins that are setup in that package.json file. You will not need to do anything with these either and you should avoid committing this directory to any repository you may be using for versioning.

Support Files

All that’s left is our support files.

  • .htaccess
  • robots.txt
  • humans.txt

The .htaccess file is pulled straight from the HTML5 boiler plate and is used to optimize how your code is served to browsers, to add security for your website and to, in general, handle how your website is received and viewed by the end user. You should not need to do anything in this file and I urge you not to do anything in here unless you know what you are doing.

One thing to note in this file:

  # around line 246
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME}\.php -f
  RewriteRule ^(.*)$ $1.php

This bit of magic removes the need to have .php on the end of your files being served up. Example: sparkmasterflex.com/about.php can now be served up as sparkmasterflex.com/about. This is a much cleaner url for the user and is more SEO friendly.

The robots.txt is used to restrict access to Search Engine crawlers to certain areas of your website. Such as, if you have a CMS for your website you do not want Google crawling and indexing your Admin areas where you add and edit content for your site. Click here to learn more about robots.txt and how to use it.

The humans.txt is completely unnecessary but is just a hip thing to have in your project. Its basically to counter the robots.txt in the way that robots get all this attention when what’s really important is the people who made the website possible. I’m sure I’m not explaining it quite the way others would, but that’s the general idea. You can read up on it here.

Reources

Spread the word
Tweet about this on TwitterShare on Google+Share on FacebookPin on PinterestShare on RedditShare on TumblrEmail this to someonePrint this page