The New Myth family: SprintPHP Bonfire Practical CodeIgniter 3

New Myth Media Blog

Serving the New Myth Media Family.

Practical CodeIgniter 3 Released

My new book about making the most of CodeIgniter 3 is out!

As part of the in-progress 0.7.1 release, I've rewritten the modular code that we use from the ground up. Let me clear that up. I didn't write most of the code. It's an combination of WireDesignz' HMVC code and jenssegers' HMVC code.

Additionally, this does include a new Route class that provides very much improved routing for your CodeIgniter apps.

Why the Rewrite?

The primary reason for the rewrite was to allow for a more complete separation between the core Bonfire code and your application. To do that, required hacking some core files, so I thought it was time to move the routing system into being a core part of the system as a whole, not just an addon. This gives us lots of opportunity for the future to improve things as we need to.

Second, though, was the integration of a new, light-weight menu system that is going to be taking care of the admin menus in this next release. This is going to let us revisit the way that we handle Contexts currently, and the new Route class is a core part of that.

Basically, it was time.

We Need You

Before we can make this one official, though, we need to have it tested out. It's working for Bonfire, but it is intended to be a nearly invisible replacement of the Loader and Router. That's where you come in. Give the modules branch a spin and [let us know](https://github.com/ci-bonfire/Bonfire/issues?directi if you run into any errors with it.

Over at NetTuts, they've put together a series of tutorials that show how to build a simple Twitter clone, called Ribbit in a variety of different languages. Using their concept as an example, lets step through how you might build the exact same application with Bonfire acting as the admin area for us to manage users, etal.

This is the first of two or three tutorials covering the process. We'll cover the basics they cover, user login and signup, Ribbitting, and friends, etc. and might even delve into some topics they didn't, like the AJAX solution, etc.

This tutorial assumes that you already have a clean install of Bonfire up and running, with database, and with the index.php removed from the URL.

A repo of the code is being kept at Bonfire's GitHub account if you want to download a save a little time as you follow along. This code will assume it's already been installed, so you will need to edit the database config file and copy over a working table from another stock 0.7 install to use.

You've Got The Look

They did a good job of describing the benefits of LESS in their intro tutorial, so I won't touch on that here. Instead, we're going to focus on taking their code and design, and converting it to work in Bonfire.

Get Your Assets In Line

To get started, download their source files and extract them to some place safe on your hard drive. Move their basic assets over to a new theme inside the public/themes folder. We'll call the theme ribbit for simplicity.

Next, copy the base assets into place:

  • Move the files from the gfx folder to public/assets/images/.
  • Copy the styles.less file into a new folder at public/themes/ribbit/css
  • Copy the less.js file into a new folder at public/themes/ribbit/js

Now, we need to modify the less file to correctly point to the new images location. Open the style.less file in your favorite editor and do a global find/replace for gfx/ to be replaced with /assets/images/.

Base Template

Next, we need to create a new layout file for the theme. Bonfire will automatically use the index.php file as the base, so create that now at public/themes/ribbit/index.php. Copy and paste the contents of their index.html file into this new file.

    <!DOCTYPE HTML>
    <html>
    <head>
        <link rel="stylesheet/less" href="/themes/ribbit/css/style.less">
        <script src="/themes/ribbit/js/less.js"></script>
    </head>
    <body>
        <header>
            <div class="wrapper">
                <img src="/assets/images/logo.png">
                <span>Twitter Clone</span></p>

          </div>
       </header>
       <div id="content">
          <div class="wrapper">

          </div>
       </div>
       <footer>
          <div class="wrapper">
             Ribbit - A Twitter Clone Tutorial<img src="gfx/logo-nettuts.png">
          </div>
       </footer>
    </body>
    </html>

Now, to make sure that all public-facing pages are using the new theme, let's edit the Front_Controller to set the theme for us. The Front_Controller is a foundation controller that is used to put common functionality for the front pages in once place. It can be found at application/core/Front_Controller.php. Be sure to edit the tags for the less.js and styles.less paths so they point to the proper location.

It only has a single method, the constructor. Edit that method and tell the template library to use the new theme, by inserting the following line anywhere after loading the template library itself.

    Template::set_theme('ribbit', 'junk');

The first parameter is the name of the theme to set as the active theme. Since Bonfire supports parent/child theme relationships the second parameter would be the name of the parent theme, or the fallback theme. In this case, we don't want to use one, so we simply set it to something random.

If you try to reload your frontpage now, you'll see the same 'Welcome to Bonfire' page as before. That's because the default home controller does not extend from the Front_Controller. Let's fix that now by replacing the existing home controller with our own.

Erase the contents of the application/controllers/home.php file and replace it with:

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

    class Home extends Front_Controller {

        public function index()
        {
            Template::render();
        }
        //--------------------------------------------------------------------
    }

The Template::render() function tells Bonfire to display the contents of a file found at application/views/home/index.php, within the current theme. Refresh your front page again, and you'll see your new theme, with the logo, background, footer, and a broken image in the bottom right corner. Let's fix that real quick so it doesn't just nag us the entire time.

Open up the theme's index.php file again and change the location to point to the proper location.

<img src="/assets/images/logo-nettuts.png">

Aaah. Much better.

Only problem is that our content isn't showing up within the template file itself. Easy enough to fix. Again in the theme's index file, we need to add a single line between the wrapper div open and close tags.

    <?= Template::content(); ?> 

Refresh again, and you'll see your content sitting pretty in it's place. Well, maybe not too pretty, yet, but we'll fix that up next.

The Home Page

The content for the home page sits at application/views/home/index.php Open up that page now and we'll insert their code for the login boxes and registration form. Remember, during this stage, we're just bringing over the looks. None of the functionality. We'll integrate that in the next tutorial.

Insert the following placeholder login form after the in the header, but before the closing <p> tag.

    <form>
        <input type="email">
        <input type="password">
    </form>

Now, on to the registration form and frog image. Erase the contents of the home/index file and insert the following code.

    <img src="/assets/images/frog.jpg">
    <div class="panel right">
        <h1>New to Ribbit?</h1>
        <form>
            <input name="email" type="text">
            <input name="password" type="text">
            <input name="password2" type="password">
            <input type="submit" value="Create Account">
        </form>
    </div>

The Buddies Page

In order for a new page to display, we'll need to create a new method to show it. We have a few options here. We could create a new Buddies controller to hold the page. We could create a new module, which might be useful if we thought we could re-use the code on another project, or simply wanted to take advantage of some of the context capabilities in the admin area. For this simple demonstration, though, we'll keep things simple and collect most of our functionality into the home controller.

So let's make a new method so that we can navigate to the page. This goes in the home controller we were just in.

    public function buddies()
    {
        Template::render();
    }

That will try to display a view file based on the controller name (as the folder) and the method name (as the file), so lets give it one. Create a new file at application/views/home/buddies.php buddies. Add the "Ribbit" box and the User Info area.

    <div id="createRibbit" class="panel right">
        <h1>Create a Ribbit</h1>
        <p>
            <form>
                <textarea name="text" class="ribbitText"></textarea>
                <input type="submit" value="Ribbit!">
            </form>
        </p>
    </div>


    <div id="ribbits" class="panel left">
        <h1>Your Ribbit Profile</h1>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user1.png">
            <span class="name">Frogger</span> @username
            <p>
                567 Ribbits<span class="spacing">45 Followers</span><span class="spacing">32 Following</span><br>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
    </div>


    <div class="panel left">
        <h1>Your Ribbit Buddies</h1>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user2.png">
            <span class="name">Kermit</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user1.png">
            <span class="name">Frogger</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user2.png">
            <span class="name">Kermit</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user3.png">
            <span class="name">Hypnotoad</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user2.png">
            <span class="name">Kermit</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user3.png">
            <span class="name">Hypnotoad</span> @username <span class="time">15m</span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
    </div>

Navigate to /home/buddies and you should see your new page. We'll fix the URL to something nicer later.

Public Ribbits Page

This page shows the public information and doesn't require a user to be logged in. Again, we need to create a new method to hold the page, so create the ribbits method in our home controller.

public function ribbits()
{
    Template::render();
}

Then create a copy of the buddies.php view file, and name it ribbits.php. Strip out the div with an id of ribbits from the new file and your new page is ready. You can find it at /home/ribbits. Again, we'll clean up the URLs in a bit.

Public Profiles Page

This page presents a list of public profiles that users can search through. One last time, create a new method called profiles in the home controller.

    public function profiles()
    {
        Template::render();
     }

Then a new view at home/profiles.php.

        <div class="panel right">
        <h1>Search for profiles</h1>
        <p>
            <form>
                <input name="query" type="text">
                <input type="submit" value="Ribbit!">
            </form>
        </p>
    </div>



    <div id="ribbits" class="panel left">
        <h1>Public Profiles</h1>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user2.png">
            <span class="name">Kermit</span> @username <span class="time">625 followers <a href="#">follow</a></span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user1.png">
            <span class="name">Frogger</span> @username <span class="time">329 followers <a href="#">follow</a></span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
        <div class="ribbitWrapper">
            <img class="avatar" src="/assets/images/user3.png">
            <span class="name">Hypnotoad</span> @username <span class="time">129 followers <a href="#">follow</a></span>
            <p>
                Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. <a href="#">http://net.tutsplus.com/tutorials/php/ ...</a>
            </p>
        </div>
    </div>

Your new page is now ready at /home/profiles.

Cleaning up the URLs

Before we're done for today, lets make our site structure a little nicer by editing the routes. Open up application/config/routes.php file and we will setup a few aliases so that the site is nicer to get around in.

$route['buddies']   = 'home/buddies';
$route['ribbits']   = 'home/ribbits';
$route['profiles']  = 'home/profiles';

There we go. Now we can access the pages without having the home portion showing in the URL.

I should point out here that the URLs can still be accessed at /home/buddies, etc. In this case, that's not a problem, but there might be occassions that you would not want users to access the page at that location. In that case, you would simply provide an empty string on the right side of the statemen and it would block access.

Conclusion

That's a wrap for this part of the tutorial. We have all of the assets in place and the site is showing us the basic pages. Next time, we'll hook in our existing users' system, restrict access to a few pages, setup our models, and more.

The cries happen every year or so. CodeIgniter is dead. They've been saying this for quite a while, but I don't believe them. Granted, I'm fond of the framework and have been using it since 2006. It's extremely stable. Fast. Quite flexible. It can do everything I've ever needed it to. Sure there are a few annoyances, but that's the same with every other framework I've used, including Rails, Laravel, and Cake. Here at Bonfire, though, we believe in CodeIgniter.

However, we also believe it needs to be able to grow and morph a bit to keep up with the demands of modern developers. So I've decided that Bonfire will no longer be a pure CodeIgniter application. What does this mean? Simply that we won't be afraid to tweak core files anymore where we need to.

Yeah, I hear the screams of "Blasphemy!" but hear me out.

We will strive to keep the changes minimal but there are a few places where some additional tweaks are needed in order to provide a more powerful, flexibile experience. Starting with version 0.7.1 we are overriding a couple of core files. I think you'll be happy with the changes coming down the pike.

Code Separation

We made huge strides in 0.7 in getting Bonfire's code away from your application's code as much as possible. However, there were a few things that we couldn't separate out and had to be left in the application folder. So we're making a couple tweaks to the Common and CodeIgniter files that allow us to store ALL of Bonfire's specific, do not touch, code in the bonfire folder. This allows us you to upgrade as easily as possible.

The only exception here will be the stock controllers that we build on top of. They'll still reside in the application folder, but only because there are likely changes that you'll need to make for most any application within those files so we don't want to overwrite in core upgrades.

Routing

One of the places that feels the weakest to me, compared to more recent PHP frameworks, is the routing system. So we've made some big additions here.

The first is a new Route library class, patterned after Jamie Rumbelow's excellent Pigeon library and Laravel's Router. This new library is already written and provides great new features like:

  • HTTP Verb-based routing, so you can assign routes only to respond if certain HTTP verb is in use. Like specifying a route just for GET request and another (at the same URL) for POST request. This makes building RESTfull routes easy.
  • Resourceful Routes make REST even easier by providing a single method to create all standard REST routes for you, though you can definitely customize the way it works.
  • Prefixing Routes groups routes together under a single URI segment heading, like 'api' or 'banking' or whatever.
  • Context Routes replace the current context system and makes it easy to add new context areas that map from one segment to any controller in your modules. Yes, it still requires modules, but is a little less magic and much more flexible.
  • Named Routes give names to routes so that you can reference the names throughout your application instead of the route. That way you can change the URL in the routes config file and not have to worry about your application breaking.

You can grab this library for any of your CI based applications today over at my GitHub account. It's fully tested and has an in-depth readme over there.

Modules

We've overridden the Loader and Router classes with our own custom versions. These contain the new module code that we'll be using from here on out. It replaces WireDesignz excellent HMVC code that we've been using since day one and will provide all of the same functionality. This is based on Jens Segers HMVC code with some modifications along the way.

So, why did we switch if it has the same functionality? We needed a solution that would help us load files from Bonfire directly, and from Bonfire's modules. So it had to be something easy to integrate. Jen's code is built on top of, and takes great advantage of, CodeIgniter's built-in packages. This creates cleaner, more elegant code than WireDesignz'.

The other reason I wanted to integrate and replace the core was so that we have the potential for even more advanced routing tricks, like filters, etc. Don't expect those items for 0.7.1, but the possibility is always there.

Saying Farewell. And Hello

In some ways it feels like this break is us saying "Good bye" to CodeIgniter and starting to fork it ourselves. Please understand, though, that this is not my intention. Instead, it's simply tweaking the core to give your code room, provide easier upgradability, and bring a little more fun back into your coding.

Instead, think of this as saying "Hello" to a slightly more mature version of your favorite framework.

Coming soon in version 0.7.1.

At long last - 0.7!

After way too long, we're thrilled to bring you the 0.7 version of Bonfire. This one contains some of the largest changes that we've done to date and might prove challenging to upgrade 0.6 sites (and will definitely require some time on your part, so be warned). Among the many changes are:

  • New Bootstrap 2.x based theme in the admin area
  • Passwords secured with phppass now for better security
  • Site restructuring for even better security for web apps.
  • Much more flexible and powerful MY_Model, adding Observer methods for easier customization, and moving data validation to the Model, where it belongs.
  • Splitting of the MY_Controller into Base_Controller, Front_Controller and Admin_Controller that area autoloaded, leaving MY_Controller alone for you to customize for your site.
  • Simpler, cleaner, front-end theme based on Bootstrap 2
  • New docs system in place to help you distribute docs within your application and modules. It's a bit basic at the moment, but that does mean that every download of 0.7 comes with all of the docs that we have and the docs are always up to date in the repo.
  • Lots and lots bugfixes.

We apologize that it took so long to get this point. I know that, for a number of you, we've probably caused you to lose a little faith in the project. For that, we are truly sorry. We are here, though, and there are some grand plans for the future that are already in the works. More information on that will be coming soon.

Now Collecting Stats

Just to make sure this is clear from the start - all installs of Bonfire 0.7 and later will report back some anonymous statistics about the environment you're installing in. We don't collect anything personal and are just collecting stats that help us to know what types of environments it's been installed in so that we can better support it and develop with those targets in mind.

Also, there's times when the forums are quiet and you wonder if anyone is actually using this thing anymore. Then you hear about a developer who has built over 80 sites on it over the last 3 years. Or a hosting provider that built their user are on Bonfire. Things like that and you realize that we are making a difference in developer's lives here. And that's the whole reason that we do this anyway. So throw me a line at lonnieje@gmail.com and let me know how you're using Bonfire. I'd love to be able to add to the (single) testimonial that I currently have on the site and hear how it's impacted your lives and careers.

What's Next for Bonfire?

Now that 0.7 is in the wild, we can take some time to streamline the code and move portions of it that don't really need to be in every install into separate modules that can be easily dropped in through Composer. The goal here is to make Bonfire a simple, streamlined package that can be used for all of your development needs.

Tentatively, here's the plans for the next few point releases:

  • 0.7.1 - New, lighter, menu system and driver-based auth library. Work on both of these is already underway. Both will also be easily used in straight CodeIgniter projects.
  • 0.7.2 - Better localization/language support and timezones
  • 0.7.3 - still in the air... :)

At some point during these releases we'll likely see Bonfire adopting a new modular code library that provides much enhanced routing support and treats module like the "packages" they are. Work has also begun on that, but it is still too early to say how long that will take.

Oh, yeah! A New Website!

Since 0.7 was such a huge change, and included the docs system, I had to rebuild the site from the ground up. This seemed like a great time to refresh the look of the site a touch also. There's still more work to be done, but we're getting there.

This also gets us ready for some of the more exciting ideas I have in store for the community. Not just the Bonfire community, though definitely that, but the CodeIgniter community at large. And that's all I'm saying on that front for now.

Enjoy the new release and, as always, please let us know if you run into any issues by reporting an issue or submitting a pull request with new changes.

Thanks for sticking with us, everyone.

Happy coding!

We just pushed a completely revised version of the installer to a new branch over at GitHub. We'd love to have you test the new installer just to help us verify if it works like we hope. Docs still need to be updated, but here's a quick overview:

  • From a fresh Bonfire install, you need to manually setup your Database config file (application/config/database.php).
  • Once this is done, simply go to your site root. This brings up the file and folder write check, and compares PHP versions, etc.
  • Click Next.
  • Wait a few seconds while your database is populated.
  • You're done.

At this point, Bonfire installs a default admin user and will show you the email and password needed to login. You should change that before you go live. :)

So please, download the latest code and give it an install in your typical system. If you run into problems, please let us know.