CodeIgniter Forums
I need good design ideas for my controllers? - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forum-20.html)
+--- Forum: Archived General Discussion (https://forum.codeigniter.com/forum-21.html)
+--- Thread: I need good design ideas for my controllers? (/thread-29756.html)



I need good design ideas for my controllers? - El Forum - 04-20-2010

[eluser]Gabriel Labrecque[/eluser]
Hello,

I've been developing a project for 3 months with CI and I enjoyed most of it so far. I'm generally happy of my design although my folder 'controllers' is getting crowded.

Some of my controller files have more than a thousand lines and I don't really want to break them into in two classes because they do share some logic.

So far, what I did is add private controller functions using the underscore prefix but they remain in the same file.

Also, some of my controllers accept form POSTs, others parse the segments of the URL. Some return views, some return jSON, some return plain/text and some return templates.

I am now considering extending the CI core Controller library to have a subclasses like Json_controller, Template_controller, etc. but before I go further and spend some time refactoring everything, I'd really like some feedback about those ideas.

Has anybody out there found a smart way of...

A) ...splitting a controller file into several? (preferably without splitting it in several controllers and manually adding items to $route[])

B) ...having Controller subclasses depending on the type of information we want the controllers to accept or return?


I need good design ideas for my controllers? - El Forum - 04-20-2010

[eluser]mddd[/eluser]
If you have that many controllers and they are that long, my guess is you should try to move more of your functionality towards models / libraries.
You should think of the controller as the 'general manager' who looks at the big picture but doensn't handle too much of the details.
Functions that are more general, and do tasks that might occur in other sites, put them in libraries.
Functions that are specific to the project, put them in models.

Also, if you have the same information in different output formats, I would combine those controllers. So if you have some kind of list that is shown in your website but also available as an rss xml document, you could make 1 controller "list" and call that with an argument telling it what to output.

An abstract example;
Code:
class List extends Controller
{

function  __construct()
{
  // do things that always need to be done for the list
}

function index()
{
  // if no method is called, output the info as html
  $this->html();
}

function rss()
{
  // get the information you want
  $info = _get_some_info();
  // output it as rss
  $this->load->view('list-rss', $info);
}

function html()
{
  // get the information
  $info = _get_some_info();
  // output is as html
  $this->load->view('list', $info);
}

}



I need good design ideas for my controllers? - El Forum - 04-20-2010

[eluser]danmontgomery[/eluser]
Just want to point out that 'list' is a reserved keyword in PHP, and you can't name a class 'list' (or 'List').

http://www.php.net/manual/en/reserved.keywords.php


I need good design ideas for my controllers? - El Forum - 04-20-2010

[eluser]mddd[/eluser]
Well thanks. Why do you think I wrote 'an abstract example'...
It is not meant to be working code. It is meant to illustrate the concept.


I need good design ideas for my controllers? - El Forum - 04-22-2010

[eluser]Gabriel Labrecque[/eluser]
Thanks for the reply mddd. I'll try to move some more project-specific stuff to the models folder and reusable stuff into the libraries folder.

One thing bothers me in the solution you suggested though is that you'd need to add those functions to all your controllers. I was considering extending the Controller class in such a way:

Code:
class MY_Controller extends Controller
{
  function _json($info)
  {
    $this->output->set_header('Content-type: application/x-json');
    echo json_encode($info);
  }

  function _png(????)
  {
    // some image magic done here
  }

  function _pdf(????)
  {
    // some pdf lib called here
  }

  function _html($view, $info)
  {
    $this->load->view($view, $info);
  }
}

Maybe that's what you had in mind in the first place but I guess it's good to make it all clear for whoever else read this thread.

That doesn't solve my problem for dealing with the inputs (i.e. POSTs and segments) though. In order to deal with segments, what I was considering to do is to pass uri segments as parameters to the controllers.

Code:
class Foo_controller extends MY_Controller
{
  function Foo_function($foo, $bar)
  {
    // if I call http://mywebsite.com/foo_controller/foo_function/segment3/segment4
    // ...then I get $foo == 'segment3' and $bar == 'segment4'
  }
}

For POSTs, we could have this:
Code:
class Bar_controller extends MY_Controller
{
  function Bar_function_post($POST)
  {
    // bar_function_post() gets called if something was posted
  }

  function Bar_function()
  {
    // bar_function() gets called if nothing was posted
  }
}

Any thought about this design?


I need good design ideas for my controllers? - El Forum - 04-22-2010

[eluser]mddd[/eluser]
I think that in reality you will always need to do things to your data before you can output information. If your controller is going to output Json, you probably have to do some other stuff to that data then when you were outputting Html.

So my guess is that the generic methods (_png, _html, _json etc) that you would put in your MY_Controller class would not have much use. Like the '_html' method: what more can that method do than load a view, with the information it gets from some other function in your controller? You still need to load information, and maybe process that information before you can send it to the _html function. If that's all done, then why not put the 'this->load->view' in the Controller too?

Pretty much the same goes for the handling of post information or segment information (note: you'll probably need both in every controller so this is not a real choice between the two). Why make these generic 'input handling functions'? What can they do? They can take all the parts from a request and give them to another method in your Controller. That is completely unneccessary because there are already functions in CodeIgniter to get those POST variables and segment values.

So, I get the feeling that you want to build a 'framework in a framework' by making all these methods that, in the end, won't really help to DO anything. The real 'doing' is still going to be in the regular controller methods, supported by calls to libraries and models.

I hope this makes sense.


I need good design ideas for my controllers? - El Forum - 04-22-2010

[eluser]Gabriel Labrecque[/eluser]
Quote:I think that in reality you will always need to do things to your data before you can output information. If your controller is going to output Json, you probably have to do some other stuff to that data then when you were outputting Html.

Ok, let me clarify. When my controller outputs json data, it's always because there was an Ajax call. And when there's an Ajax call, I always return an associative array of the form:
Code:
array('code' => 'ok', 'data' => $data)
or
Code:
array('code' => 'error', 'errors' => array(array('message' => 'some message here'), array('message' => 'another message here')))

My controller functions are filled with little bits of array definitions like those. If I just had this extended controller, I would save 4 lines * ~20 times.

Quote:So my guess is that the generic methods (_png, _html, _json etc) that you would put in your MY_Controller class would not have much use. Like the ‘_html’ method: what more can that method do than load a view, with the information it gets from some other function in your controller? You still need to load information, and maybe process that information before you can send it to the _html function. If that’s all done, then why not put the ‘this->load->view’ in the Controller too?

Well, right now, I'm using Smarty for a template engine. This would be a smart place to load the library. Also, there are a couple of global variables that need everywhere in the views. This would again be a smart place to load them as well.

Quote:Pretty much the same goes for the handling of post information or segment information (note: you’ll probably need both in every controller so this is not a real choice between the two). Why make these generic ‘input handling functions’? What can they do? They can take all the parts from a request and give them to another method in your Controller. That is completely unneccessary because there are already functions in CodeIgniter to get those POST variables and segment values.

Well, I personally think that writing "$this->input->post('')" for every variable looks overly verbose.

Quote:So, I get the feeling that you want to build a ‘framework in a framework’ by making all these methods that, in the end, won’t really help to DO anything. The real ‘doing’ is still going to be in the regular controller methods, supported by calls to libraries and models.

I'll sure have to evaluate the pros and cons but I don't think it's such a bad idea to build a framework within a framework.

Quote:I hope this makes sense.