Beat PHP Over the Head With JSON

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

Using JSON with PHP

If you’re making a simple website with PHP but have some standardized data to loop through and display, then using a database may be a bit overkill. Yet we all want to have DRY code which will not happen if you are rewriting the same HTML over and over again. This is where a JSON file can get you out of the water.

So why JSON? Because it’s easy to write and even easier to read. Setting a standard pattern for your data in a JSON file makes it easy to return later, and edit or add to the data, or better yet having a coworker alter it. Having said all this, it is time to admit that although the JSON part of this post is lovely; the PHP is not so much.

You may have seen me bash PHP on Twitter or in other blog posts in the past, but please make no mistake… I truly hate PHP. Don’t get me wrong, everything that you can do in Ruby, you can do in PHP as well, it’s just more difficult, more code or just a pain in the ass. Yet PHP is still around because it is super lightweight compared to Ruby, Node.js, ASP and what have you, in the sense that you really don’t need to do much for PHP to use it on a server. Simple installation of PHP and an Apache module and you’re good to go. Where the others mentioned require another server to be running either next to or independently of Apache or Nginx.

Any how… Let’s Get Started

As of PHP 5.2.0 we received a couple of functions that allow us to work with a JSON string, json_decode() and json_encode(). These enable PHP to not only write an associative array to a JSON string but also convert a JSON string to an associative array. If you’re new to
PHP and/or programming in general, then let’s spend a minute to explain an associative array. Associative arrays are a list of key/value pairs that make organizing data a lot easier. These exist in other languages as well, and they are called hashes in Ruby, and objects in both JavaScript and ActionScript.

  /*== Array ==*/
  $arr = array("Athens", "Sparta", "Corinth", "Carthage", "Tyre", "Lilybaeum", "Rome", "Neapolis", "Brundisium");

  /*== Associative Array ==*/
  $arr = array(
    'greek' => ["Athens", "Sparta", "Corinth"],
    'punic' => ["Carthage", "Tyre", "Lilybaeum"],
    'roman' => ["Rome", "Neapolis", "Brundisium"]
  );

The real benefit here is that now all our cities are grouped under the culture that owns it. We can now grab a list of all Punic cities by simply calling $arr['punic'];.

  $arr = array(
    'greek' => ["Athens", "Sparta", "Corenth"],
    'punic' => ["Carthage", "Tyre", "Lilybaeum"],
    'roman' => ["Rome", "Neapolis", "Brundisium"]
  );

  print_r($arr['punic']);
  //=> "Carthage", "Tyre", "Lilybaeum"

When you run json_encode() on $arr, it will write the associative array to a string that is formatted the way that JSON wants it.

  $str = json_encode($arr);
  //=> "{\"greek\":[\"Athens\",\"Sparta\",\"Corenth\"],\"punic\"=>[\"Carthage\",\"Tyre\",\"Lilybaeum\"],\"roman\"=>[\"Rome\",\"Neapolis\",\"Brundisium\"]"

  $new_arr = json_decode($str, true);
  // this will recreate an associative array based on the JSON string

The true, passed as the second argument for json_decode(), tells PHP to create an associative array out of the string.

Making It All Useful

So what do you do with all this? Well, as I mentioned earlier, I use this to map through like-formatted content, such as a team page or portfolio that without which, you would be duplicating HTML repeatedly or setting up and connecting to a database. Look at a JSON file in this situation as a replacement for a database. In fact, if you’ve ever worked with MongoDB, that’s almost exactly what it is. The MongoDB saves entries as JSON, and the server is what parses it back to your application, often in JavaScript Objects.

Let’s take a look:

  // portfolio.json
  // JSON for a portfolio
  {
    "sparkmasterflex": {
      "title": "Sparkmasterflex Blog",
      "url": "sparkmasterflex.com",
      "desc": "An amazing blog that is not only informative, but also has literally saved my marriage.",
      "technology": ["jQuery", "Wordpress", "PHP"]
    },
    "rtw_map": {
      "title": "Rome Total War Campaign Map",
      "url": "totalwar.ifkeith.com",
      "desc": "Share your destruction of ancient empires with the world",
      "technology": ["Backbone.js", "jQuery", "PHP", "Handlebars.js"]
    },
    "marxjs": {
      "title": "MarxJS",
      "url": "marxjs.com",
      "desc": "Coming soon! Stay tuned for more information",
      "technology": ["jQuery", "Ruby", "Sinatra", "JSON"]
    }
  }

So how do we get this into PHP and build our views from it? We’ll use PHP’s file_get_contents() in unison with json_decode(). Here’s the code snippet:

  function get_portfolio_items() {
    $json_str = file_get_contents($_SERVER['DOCUMENT_ROOT']."/data/portfolio.json");
    $json = json_decode($json_str, true);

    return $json;
  }

First, we get a string from the contents of the JSON file, and set them to the $json_str variable, and we call json_decode() on said variable passing true to make sure this function returns an associative array. But… there’s a Gotcha here. PHP, being difficult as it is, I’ve found gets upset about our neatly formatted JSON. It’s looking to decode a JSON string with no line breaks.

I have literally lost hours to this on at least 3 projects before it sunk in because PHP has little to no means of debugging. We need to make sure that our string received from the file_get_contents() has no line breaks. Here’s the solution I came up with:

  function get_portfolio_items() {
    $str = file_get_contents($_SERVER['DOCUMENT_ROOT']."/data/portfolio.json");
    $json_str = preg_replace("/(\n)/", "", $str);
    $json = json_decode($json_str, true);

    return $json;
  }

I added the preg_replace() function to remove all \n from the $str variable before we decode the JSON. Of course we can trim this down a bit but I just wanted to spell it out so everyone can follow along.

The Views

Let’s then take a look how we would generate our views based on this information. Let’s keep it simple and just render out our portfolio in an index.php file:

  <?php 
    require_once '/path/to/functions.php'; 
    $portfolio = get_portfolio_items();
  ?>
  <!doctype html>
  <html>
    <head>
      <!-- ... omitting header info ... -->
    </head>
    <body>
      <div id="content">
        <section>
          <div id="portfolio">
            <?php foreach($portfolio as $key => $item) { ?>
              <div id="<?= $key ?>" class="item">
                <h3><?= $item['title'] ?></h3>
                <p><?= $item['desc'] ?></p>
                <ul>
                  <?php foreach($item['technology'] as $tech) { ?>
                    <li><?= $tech ?></li>
                  <?php } ?>
                </ul>
                <a href="<?= $item['url'] ?>" rel='external'>See it!</a>
              </div>
            <?php } ?>
          </div>
        </section>
      </div>
    </body>
  </html>

In this, we make sure to require_once for our functions.php, which houses our get_portfolio_items() function. Then we set a variable $portfolio, equal to the returned value from our function. Later on in the file, we do a foreach loop passing $portfolio and create the $key and $item variables for each iteration. $key will be equal to our sparkmasterflex, rtw_map, etc and $item will be the grouping of our attributes for the current portfolio item. (i.e. title, desc, etc)

Conclusion

That’s pretty much all there is to it. Minus the one bug in decode_json(), and line breaks in the JSON file, it’s pretty cut and dry. I like using this workflow rather than creating a database for such little data, and I especially do not want to create all this data in a PHP associative array. I’ve done that before, and you’ll want none of that noise, trust me.

Be sure to watch for the big Gotcha‘s when it comes to using JSON and PHP together:

  • Make sure you’re using PHP 5.2.0 or later
  • Pass the true as the second argument to decode_json()
  • Add the preg_replace() to remove all line breaks in the string retrieved from the JSON file

Another tip… Although I’ve mentioned avoiding the database for situations like a portfolio or a team page, be aware that there is a line where the data becomes too large or needs changed too often to make using JSON over a database illogical. Each project presents new challenges and new requirements, so use your best judgment. Nice cop-out, huh? I spend an entire article telling you to do one thing and then last paragraph, tell you it could be all wrong.

Well…

Deal With It

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