• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Open Source CI Framework That Builds Pages From Reusable Components

#1
[eluser]solvo[/eluser]
Hey All,

I’ve developed an open source framework on CodeIgniter that builds pages from components, allowing developers to create more modular sites that are easier to update and maintain.

The basic idea is that instead of writing large methods in your controllers, your controllers will be lean - they’ll merely define what components to load on the page and where. You then write components that are reusable across your site making updates and bug fixes a lot easier since there’s much less redundant code. If you have the same login form on every page, for example, no need to rewrite that code in each controller method - just create a component for it.

A more thorough discussion of concepts can be found in the documentation link below.

If you’re at all interested, you can find the open source project on github: https://github.com/xjstratedgebx/CodeByrner

I’m still working on the complete documentation, but what’s currently done is available here: https://github.com/xjstratedgebx/CodeByrner/wiki

If what I set out to do has been done and accomplished a 1000 times before, forgive me for throwing another project on the pile - that certainly wasn’t my intent. I merely use this framework for my own projects, and thought someone else might find it useful, or use some ideas on their own.

Please let me know if you have any questions or suggestions that I can incorporate.

Take care,
- JB

#2
[eluser]dnc[/eluser]
This looks very promising. I'll be watching this one.

#3
[eluser]solvo[/eluser]
Thank you much, hope it proves useful. I found myself writing this library with each new project I did, figured it was time to put it into source control somewhere so I could update it as necessary and all my projects would benefit. I hope that other developers find that it makes their lives easier as well.

Let me know if you have any questions/suggestions.

- JB

#4
[eluser]boltsabre[/eluser]
Hey, just had a quick glance at it, but what's the difference between this and using libraries (and helper), and for the repeated view code just using an include->view('..').

For example, my "login/logout/register" (located up the top RHS of every front end page of the site), I use the above mentioned - it's all very isolated on modular, if I want to make a change, I do it and it's site wide.

For the site I will have upwards of 30 different forums, I've just finished isolating this into it's own library and helpers, now when I want a new forum, inside my controller sub folder I make a new controller called "forum" which is just a copy and paste of "forum" template, which is 50 lines in total (including line breaks and comments). I set up a parameter array in that forums constructor which has stuff such as that forums id for the DB, what is the base uri segment it's located at so I can have pagination working whatever level the forum is located at, what bread crumb helper to load, etc. Less than 50 lines, change a few parameters, and bang, a whole new forum.

I'm not saying your method doesn't have advantages, but I'd be very interested in your thoughts about what will make this better than using libraries and helpers in a smart way?

#5
[eluser]solvo[/eluser]
Hey there boltsabre, thanks for the question.

Before I answer, let me just say that I'm a big believer in finding what works for you and going with that. So while I hope that my little framework is useful for you, if you have a way of doing things that works well for you, I completely support your doing it the way that you want/feel most comfortable with.

To answer your question, it sounds like your setting up individual forums to have their own controllers, which is why you have parameters inside of your controller to identify which forum that controller is for (please do correct me if I am wrong). My guess is that your URI segments are somewhat similar to "http://base_url/forum_name1" (or http://base_url/index.php/forum_name1" if you haven't done the whole modrewrite thing).

If I understand you correctly, if anything ever needs to change in that forum template you have, now you have 30 files that need to be updated appropriately.

I think on a theoretical level that's the biggest difference between what my framework does and the framework you've built does. I would have a single "Forum" controller with methods like "index", "view_forum", "view_topic", "post", and the parameters passed to those methods in the URI would take the place of the parameters you are hard-coding into each individual forum controller. Here's what the setup might look like:

Code:
class Forum extends Page {

    function __construct() {
        parent::__construct();
    }

    function index() {
        $this->addComponent('ForumBreadcrumb');
        $this->addComponent('LoginForm');
        $this->addComponent('ListForums');
        $this->addComponent('ForumStats');
    }

    function view_forum($forum_id) {
        $this->addComponent('ForumBreadcrumb');
        $this->addComponent('LoginForm');
        $this->addComponent('ListTopics', 'content', array($forum_id)); //Can also get the forum_id from $this->uri->segment(x) in the component method
        $this->addComponent('ForumStats');
    }

    function view_topic($topic_id) {
        $this->addComponent('ForumBreadcrumb');
        $this->addComponent('LoginForm');
        $this->addComponent('ListPosts', 'content', array($topic_id)); //Can also get the topic_id from $this->uri->segment(x) in the component method
        $this->addComponent('ForumStats');
    }

    function post($topic_id) {
        $this->addComponent('ForumBreadcrumb');
        $this->addComponent('LoginForm');
        $this->addComponent('AddPost', 'content', array($topic_id)); //Can also get the topic_id from $this->uri->segment(x) in the component method
        $this->addComponent('ForumStats');
    }

    function submit_post() {
        //You could process this right here if you want to since you're processing POST data, and then redirect the user, or you can throw it to a component to handle. For me, personally, I try to keep my controllers clean, so I might write a component to do the processing, or just use that AddPost component from above and call a processing method inside of that. It doesn't make that much of a difference though.
        $this->addComponent('AddPost', 'content', array(), 'processPost');
    }

Obviously that's an overly simplified forum system right there, but it would work. The idea behind my framework is that it automatically handles the building of the page from your various components, allowing you to get straight into programming the functionality you want to program. Here that would be the breadcrumb, login form, stats info, and then the content specific to each page.

Also, the component class I wrote that you would extend for each of your components allows you to write your methods just like if you were working inside a controller, and not a library. Controllers have complete access to the CodeIgniter object on each page load view $this->, and your components will as well. This way you don't have to keep doing the whole $CI = &get;_instance(); deal.

If you wanted to do AJAX stuff and call specific pieces of a component, like re-rendering a component on the page, or doing a "more news" kind of thing, I've built functionality for that into the platform as well. There's a component that comes bundled called Cmpt that allows you to call a specific, public methods in a component through the URL. In the above code example, we could AJAX the post submission stuff by POSTing to http://base_url/cmpt/AddPost/topic_id_number. Then you can handle the response on the page without a reload. The platform will throw an error if someone tries to access a private method, so security is built right, you don't need to worry about that.

Also, I try to avoid helpers as a point of personal preference. I like classes with defined methods instead of freely callable functions, but that's not to say they don't have their place (again, this is solely my personal preference). I have however included a utilities helper in CodeByrner that has a function called dump() which will stop output on the page and give you diagnostic information on the variable you pass it. I find this really useful for debugging.

Think I've also begun to throw in support for a service layer, which I think is a major idea lacking in CI. Controllers are gate keepers, they call services which define business logic, and services go to models to get the information they need. Of course, if you don't want to do that, CodeByrner will work just fine without using services (and the service class comes bundled but turned off by default anyway).

So there's actually a whole lot of stuff going on in this little framework.

...all that being said, did I come even remotely close to answering your question? Please let me know.

Take care,
- JB

#6
[eluser]boltsabre[/eluser]
Hey, sorry about the late and short reply, it's getting late here.

It does sound interesting, that's for sure. I hope you keep posting back here on the forum as it develops.

You were correct with my forum setup.
Code:
www.mydomainDOTcom/one_of_many_cities(folder)/forum(controller)/vp(method)
www.mydomainDOTcom/one_of_many_states/forum/post-new-thread
www.mydomainDOTcom/visas/business/forum, etc
And each forum controller is 50 lines of codes, basically just a constructor with my parameters, and methods (calling various library functions).

And you are correct, if something MAJOR needs changing (ie, a new method), they all need updating. But a combination of switch statements and default values mean that if I just need something little for one forum I can pass an extra parameter and use it the library constructor (or method) to define some behavior that will only apply to that forum.

I'm a little curious about your setup, you mentioned that all your parameters are based in the url. If you then need to change something, wont you have to go and hunt down every internal instance of that link in the views and update the url, update the xml sitemap, the html sitemap? What about SEO, and inbound links/404 pages? Now we're getting into the realm of messy .htaccess 301 redirectss/mod rewrite rules flying around everywhere. Or have I missed something here?

#7
[eluser]solvo[/eluser]
Hey there boltsabre,

I should have discussed the parameters better (or at all). In my example, the only parameters you're passing via URL would be ID's, like the ID for a forum, an ID for a topic, an ID for a post, etc.

Any of the parameters for the forum are better placed in the database, so in the case of my example you might have a structure that looks like this:

Code:
CREATE TABLE forums (
    forum_id INT(2) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    allow_new_topics TINYINT(1) DEFAULT 1,
    color_scheme ENUM ('Red', 'Blue', 'Green') DEFAULT 'Red',
    guests_can_post TINYIT(1) DEFAULT 0
);

Code:
CREATE TABLE topics (
    topic_id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    forum_id INT(2) NOT NULL,
    title VARCHAR(255) NOT NULL,
    user_id INT(10) NOT_NULL,
    closed TINYINT(1) DEFAULT 0,
    created TIMESTAMP
);

Code:
CREATE TABLE posts (
    post_id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    topic_id INT(10) NOT NULL,
    user_id INT(10) NOT NULL,
    post_text TEXT,
    created TIMESTAMP
);

So then if you look back at the example code from my previous post, you'll see we're only passing through the URL either a $forum_id or a $topic_id. We'll use those to go to the database and grab our parameters.

Since everything is related, of course you can always get the forum information if all you had is, say, the $post_id. This example is in SQL, but each DB type has its own ways of doing the following:

Code:
SELECT forums.*
FROM forums
JOIN topics USING (forum_id)
JOIN posts USING (topic_id)
WHERE posts.post_id = $post_id /* Of course you'd sanitize $post_id before putting it in a query */
LIMIT 1

By taking this information out of being hard-coded in your files, and placing it within the database, you're creating an environment that is easier to manage. You could then build a tool that allows you to dynamically build out new forums by providing a front-end interface to adding entries to your database.

Ultimately, this is how all major forum and bulletin board systems work, including the CodeIgniter forums here. Again, find what works for you and do it, don't let me get in the way, but I think from a manageability and sustainability standpoint, this would be the best way to go.

As for SEO concerns, there's nothing a Googlebot loves more than a link that looks like http://base_url.com/forums/view_post/7. That link shouldn't ever have to change, and if it does, it's likely part of a wholesale refactoring of your platform and/or data scheme, in which case SEO is probably the least of your worries.

If you're doing a small project you want to manage yourself, really any way of getting the job done should be fine. I developed CodeByrner with the idea of using it as the basis of platform that is being worked on by several people at the same time (although it works just fine for single developer projects), and also with the idea that a solid, client-facing, production environment should be easy to isolate problems within and be unit-testable. This means cutting down as much as possible on code redundancies.

I hope that is helpful or instructive. Please let me know if you have any further questions!

Take care,
- JB

#8
[eluser]boltsabre[/eluser]
Hey JB,

Thanks for the clarification, makes more sense now with your url parameters, as mentioned I thought you were passing them all - nice to have them isolated in a db table!

Thanks for all the info, it's good for me, I'm a recent newbie to web dev (finished my course, and have been working for a company now for almost 2 years, but the website is a bit monolithic and not build on any framework or in a pure OOP way, guess you'd call it a procedural php based website using the smarty template system). I've been working on my own project PT for almost a year now, hoping to launch in a few months, and I'm always looking for good ways to make my own code/project smarter and more modular. For now it doesn't make much sense for me to rewrite my site into something like this (after 1 yr, if I don't get it online soon I'll go insane); however, if it's a success and allows me to quit my day job I'd like to do an overhaul - this could be an option.

Thanks again for your replies, good luck with it all, keep us updated okay!

#9
[eluser]solvo[/eluser]
Hey boltsabre,

Happy to help. Good luck with your site, hope it all works out for you.

Take care,
- JB

#10
[eluser]dnc[/eluser]
Ok, I've been lazy and haven't had time to test this class. Can anyone confirm for me that is works with Mod rewrite?


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.