Part of the EllisLab Network
   
2 of 3
2
How to call functions of another controller
Posted: 28 July 2007 11:15 PM   [ Ignore ]   [ # 16 ]  
Summer Student
Total Posts:  2
Joined  07-28-2007

In my relatively short time here, this is my interpretation of the CI way of doing things.

Models:
Interact with data source/s, and return the data ready to be used.

Views:
Define the content and structure of the output.

Controller:
Arrange for the content to be prepared, using controller specific ‘internal’ logic, models, libraries, helpers, plugins etc, and pass it along to the view.

Custom Libraries:
Categorised set of functions to use in the application. Complex Logic used more than once in an application.

Custom Helpers:
Simple functionality to be reused throughout the application. An example might be converting unix timestamps to excel friendly date formats.

Custom Plugins:
A set on functions that are required together more than once in an application, using data sources defined outside of the plugin.


Appreciate your thoughts and comments.

Cheers,
Henry

Profile
 
 
Posted: 29 July 2007 12:20 AM   [ Ignore ]   [ # 17 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  770
Joined  02-06-2007

Of course you don’t have to follow the conventions, but:

Henry CI - 29 July 2007 03:15 AM

Custom Libraries:
Categorised set of functions to use in the application. Complex Logic used more than once in an application.

Actually, CI libraries aren’t a set of functions. Libraries are classes. Classes have methods as opposed to functions.

Henry CI - 29 July 2007 03:15 AM

Custom Helpers:
Simple functionality to be reused throughout the application. An example might be converting unix timestamps to excel friendly date formats.

CI defines a helper as a collection of functions of a particular category.

Henry CI - 29 July 2007 03:15 AM

Custom Plugins:
A set on functions that are required together more than once in an application, using data sources defined outside of the plugin.

Plugins work almost identically to Helpers. The main difference is that a plugin usually provides a single function, whereas a Helper is usually a collection of functions. IMO plugins are redundant.

 Signature 

“I am the terror that flaps in the night”

Profile
 
 
Posted: 29 July 2007 02:33 AM   [ Ignore ]   [ # 18 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  2774
Joined  07-27-2006

Yeah, I don’t really know where to place plugins either. I’m usually developing custom solutions as libraries, and putting one-off helper function in helpers.

 Signature 

Check out the Template Library
Oh yeah, I tweet, too (regarding CodeIgniter on occassion).

Profile
 
 
Posted: 29 July 2007 06:21 AM   [ Ignore ]   [ # 19 ]  
Summer Student
Total Posts:  2
Joined  07-28-2007

Thanks Rick.

It’s a little precarious of course because there isn’t any hard and fast this is for this, this is for that, type documents (that i’ve found at least), and have come across plenty of plugins/helpers that seem to operate outside of what you’ve described.

I would have (still would..) loved a short introduction that covers the little bits like this when I first got here. Praps I’ll start a new thread called ‘best of the CI forums’ and see if I can’t mill through and maybe make a little top nuggets of information for the beginners manual…

thoughts, comments?

Cheers,
Henry

Profile
 
 
Posted: 29 July 2007 01:30 PM   [ Ignore ]   [ # 20 ]  
Research Assistant
RankRankRank
Total Posts:  530
Joined  07-10-2006
yongkhun - 09 July 2007 08:09 AM

Thanks Colin, for your fast advice.

I did consider to put the function as library. But I found that my function will be more efficient to remain in the external controller due to some class member variables. If I put it as library function, then I will have to perform some extra initialization of variables.

So, there is really no proper way of calling function in another controller?

You need to take advantage of object inheiritance. Build a base controller and extend all other controllers from that base controller. Any methods in your base controller will be shared among your subclassed controllers. If you placed the method in question in the base controller, it would be inheirited by all subclassed controllers regardless of whether they needed that method or not. Thus, you could call that method from any controller subclassed from the base controller. You could also overload a method inheirited from the base controller by including the same method in a subclassed controller and changing the method code to whatever you need.

The base controller could also load a library, helper or plugin containing the method in question and it would be inheirited by your subclassed controllers.

If you have a lot of methods stored in multiple libraries that need to be shared by some or all of your subclassed controllers, you can create a factory and load the factory class as a library (a single class). A factory is based on the factory design pattern. You can learn about factories on the web. The factory does not load libraries until they are actually needed, so the concept fits in with CI’s use of the lazy initialization design pattern in the Loader library. The factory includes get and set methods which delegate resposibilities to other libraries. This is a very elegant way of keeping your controller code simple.

Profile
 
 
Posted: 01 August 2007 04:36 PM   [ Ignore ]   [ # 21 ]  
Grad Student
Rank
Total Posts:  41
Joined  06-25-2007

Here’s a nifty helper function to accomplish what you need:

<?php

/**
 * Import another controller by first finding it then returning
 * an instanciated version of it.
 * @param string $path The path to the controller from the base of the controllers dir.
 * @author Peter Goodman
 * @copyright Copyright 2007 Peter Goodman, all rights reserved.
 */
function import_controller($path{
    
    
static $controllers = array();
    
    if(!isset(
$controllers[$path])) {
    
        $parts 
preg_split("~/~"$path, -1PREG_SPLIT_NO_EMPTY);
        
$c ucfirst(array_pop($parts));
        
$file APPPATH .'/controllers/'implode('/'$parts) .'/'strtolower($c) . EXT;
        
$error "Could not load controller [{$controller}]";
    
        if(
file_exists($file)) {
            
require_once $file;
        
            if(!
class_exists($cFALSE)) {
                
throw new Exception($error);
            
}
        
            $controllers[$path] 
= new $c;
        
        
else {
            
throw new Exception($error);
        
}
    }
    
    
return $controllers[$path];

Just pass it the path + file name without file extension to the controller you want to import and let it do its thing.

PS. I don’t suggest you use this, but if you feel that calling another controller’s method(s) is the only solution, then go for it. As long as I don’t ever have to see your code, it’s fine with me.

PPS. This also works with controllers in multiple sub folders, as is a library I use. This is also php5, so if you want to make it php4, just change all the throw Exception.. to trigger_error.

 Signature 

I/O Reader

Profile
 
 
Posted: 27 September 2007 04:14 AM   [ Ignore ]   [ # 22 ]  
Summer Student
Total Posts:  14
Joined  06-25-2007

Thanks a lot, Peter. I finally dropped the idea of calling another external controller from within a controller, and put those functionality in a library instead.

So, just stick to the MVC concept…..

Profile
 
 
Posted: 16 October 2009 03:28 PM   [ Ignore ]   [ # 23 ]  
Summer Student
Total Posts:  1
Joined  10-16-2009

although its not MVC convention i actually wanted to use it to create a sandbox area for my website. so after reading the previous code i quickly worked it out for myself, its very basic and you can amend the code to suit your needs. Just change the first two lines and it works. Insert this code into any controller.

Note:
Controller - is the controller (examples:  controller or folder/controller)
Method   - is the controller method/action (examples: index or timetables)

/*Load External Controller*/
$controller = “controller_name_here!!”;
$method   = “method_name_here!!”;
     
include($controller.’.php’);     
$get = new $controller();
$get->$method();

Profile
 
 
Posted: 06 February 2010 09:14 AM   [ Ignore ]   [ # 24 ]  
Summer Student
Avatar
Total Posts:  20
Joined  08-25-2008

I don’t think that using controller from another one is breaking mvc concept. Controlling is still in controllers, so there is nothing to be talking

I have a trouble with this importing, that Peter Goodman gave, it imports controler, and I can call some methods, but if that method uses other models or libraries, they are not working, saying that they are calling on an not an object.

Anyone knows how to really import or call another controller as it needed to be.


I use this coz i have page controller, and ther are pages like
/pages/about
/pages/portfolio

I want error controller to call pages->about or pages->portfolio if url is mysite.com/about or mysite.com/portfolio
Yes, i know about routing, but i need it to me more flexible and editable for normal gui user wink

Thanks for reading my post, hope for helping.

Profile
 
 
Posted: 03 March 2010 04:09 PM   [ Ignore ]   [ # 25 ]  
Summer Student
Total Posts:  1
Joined  03-03-2010

There’s this library called Wick :http://codeigniter.com/wiki/Wick/.

All you have to do is to load the library :

$this->load->library('Wick'); 

Then, you need to call :

$this->wick->light('pages/about');
$this->wick->light('pages/portfolio'); 

That’s all.

There’s some errors due to references, you just have to remove them and it will be working fine.

Profile
 
 
Posted: 11 May 2010 09:56 AM   [ Ignore ]   [ # 26 ]  
Grad Student
Rank
Total Posts:  42
Joined  11-05-2007

Actually you can call a function from another controller, just use call_user_func()[1]:

call_user_func(array($Anothercontroller'your_function'), $config); 

where $config can be an array of vars to pass to your_function():

$config = array('try','this','way'); 

Cheers smile


[1] http://php.net/manual/en/function.call-user-func.php

Profile
 
 
Posted: 12 August 2010 06:19 PM   [ Ignore ]   [ # 27 ]  
Summer Student
Total Posts:  19
Joined  06-03-2010

I’d like to continue this discussion, if I may. While I know it may be frustrating for those of you experienced in CI to answer the newbie questions, I appreciate it because this is how I learn - making mistakes and getting advice.

I stumbled upon this thread because I wanted to have certain pages only accessible if you’re logged in.

So if a session variable is set, it displays the view—if it’s not set, it sends you back to the login page. For me, right now this is in another controller.

Is the solution to this to put the log in methods in an intermediate controller?

class Logins extends Controller
{
  functions 
for logging in and outsetting the session variablesetc
}
...

class 
AllOtherControllers extends Logins 

or is there another way to do this? What about using the

redirect('different_controller/function'); 

function?

Thanks-Rahul

Profile
 
 
Posted: 13 August 2010 02:51 AM   [ Ignore ]   [ # 28 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  963
Joined  09-11-2008
oldblueday - 12 August 2010 10:19 PM

or is there another way to do this? What about using the

redirect('different_controller/function'); 

function?
Thanks-Rahul

Without getting into a large conversation about Web design, SEO best practices, etc., let’s just say, you probably want to use redirects in this case. A URL is a path to a resource. If authentication fails for that resource, you should redirect to a page that can provide a way to properly authenticate. It should not be the same path as the legitimate resource. Just makes sense to me (besides many practical technical reasons.)

Okay, I have to chime in on this controller-from-another-controller issue. Someone wrote that models should be database-centric. The CodeIgniter folks intended this, it’s true (see the manual), but it’s not necessarily the purpose of a model in the MVC architecture. According to the wiki:

Many applications use a persistent storage mechanism such as a database to store data. MVC does not specifically mention the data access layer because it is understood to be underneath or encapsulated by the model. Models are not data access objects; however, in very simple apps that have little domain logic there is no real distinction to be made.

Further wiki explanation of a model:

The model is used to manage information and notify observers when that information changes. The model is the domain-specific representation of the data upon which the application operates. Domain logic adds meaning to raw data (for example, calculating whether today is the user’s birthday, or the totals, taxes, and shipping charges for shopping cart items).

So a model, in essence, is meant to manage the information in an application. Not a controller. A controller is meant to simply retrieve data and hand it off to views to present it. A popular phrase for this notion of pure controllers is, “Fat Models and Skinny Controllers.” It means that your models should concern themselves with manipulating all the information of an application, and controllers concern themselves with simply grabbing data from models and passing it to views for displaying the information (now I’m getting redundant.)

I agree with the statement someone in this thread made that if you have to depend on calling controller methods from another controller, you have implemented bad MVC design. Why? Because if you stick to this notion of thin controllers, fat models, all of your information logic is modular. And we all know that, in programming, modularity is a good thing. smile

Now, this is all theory and best practices. So let me finally get to my point. The constructor for the core Model class in CodeIgniter calls one lonely method: _assign_libraries. When we look at the documentation for _assign_libraries, we get a little revelation about the power of using fat models:

* Creates local references to all currently instantiated objects
* so that any syntax that can be legally used in a controller
* can be used within models.

Did you see that? ...any syntax that can be legally used in a controller can be used within models (you can call $this->db in your controllers. Models have no special “model sauce.”) Why is this better, than say, a library? Well, an application library in codeigniter is a pure class. That is, more often, it inherits from nothing. Sure, we can extend core classes, but you do not have to extend anything typically. In fact, the manual page for libraries shows an example of the ‘ole get_instance() call for getting framework resources:

$CI =& get_instance(); 

In a model, you have the same scope as you do in a controller. This makes it a good place for much of the logic that tends to bloat controllers (Heaven knows I’m guilty of bloating my controllers too.) Incorporating your information logic in models has the added benefit of making your “rough” procedural code absolutely modular. That translates to: No need to call controller methods from other controllers! Yeah!

Don’t get my wrong. For black-box functionality, libraries are very useful and proper. Anytime you need to use the loader class to get a “thing” that is independent and separate from the procedural nature of the application, use a library. Because models have the same access as controllers to framework resources, you can even call your libraries in your models to be used as aides to help you assemble your application information. smile

 Signature 

Google Analytics HOWTO | Enable GET | Netbeans PHP Integration

Profile
 
 
Posted: 13 August 2010 03:15 AM   [ Ignore ]   [ # 29 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  963
Joined  09-11-2008

I’d like to continue this discussion, if I may. While I know it may be frustrating for those of you experienced in CI to answer the newbie questions, I appreciate it because this is how I learn - making mistakes and getting advice.

I guess I should have gotten a hint from that statement that this was a very old thread. I mean before I decided to write an epistle on the beneficence resulting in using fat models.

cheese

I suppose that was a lot of writing effort for little exposure and usefulness to the community.

 Signature 

Google Analytics HOWTO | Enable GET | Netbeans PHP Integration

Profile
 
 
Posted: 13 August 2010 03:18 AM   [ Ignore ]   [ # 30 ]  
Summer Student
Total Posts:  19
Joined  06-03-2010

Still, very helpful advice. So you’d advocate putting most of the logic and data manipulation in the models instead of the controllers? I had initially done that, then read somewhere it should be the opposite - leaving models simply for database access. Seems like it’d make for cleaner code if the models could do more than just return a query result. Are there others who advocate the opposite? Fat controllers, skinny models. (I’ll skip the obvious joke). Thanks for your help.

Profile
 
 
   
2 of 3
2