calling methods from another controller

hello.

how can i use or call a method from another controller class?

thanks <_<

I’m not sure that you can but if someone knows how then please post here.

In the meantime if you want to access a function(AKA method) from numerous controllers why not just make a component. You are probably already auto loading all of the contents of the components directory.

Here is an example of a component called MyUtils (could be any name)

Create a file in components called ‘MyUtils.php’ example contents of the file below


<?php

class MyUtils {


	public function hasAbstract()

	{

		$count=EventAbstract::model()->contributer(Yii::app()->user->id)->count();

    return ($count > 0 ? true : false);

		

	}


}

?>

Now you can call the functions from anywhere (multiple controllers anyway) for example the code below is in my /views/layouts/main.php and is used to provide conditional dropdown menu options.


if(MyUtils::hasAbstract()){

        $items= array(

                    array('label' => 'Edit',

                            'url' =>array('/eventAbstract/AbstractUpdate')

                            ),

                         );

				} else {		 

		 $items = array(

                    array('label' => 'Create',

                            'url' =>array('/eventAbstract/create')

                            ),

                         );

						 }

Hope this helps,

doodle ;)

One possible approach is to use redirect:




public function actionMyAction()

    {

        $this->redirect(array('myothercontroller/myotheraction'));

    }



Check also:

http://www.yiiframework.com/doc/api/1.1/CController#forward-detail

Try with public static method

If you must do this (it’s probably not recommended or it would be easier).

Add this line to /config/main.php (or whatever config file you are using)


'import'=>array(

		'application.models.*',

		'application.controllers.*', <-- add this line

        'application.components.*',

...

example I used in siteController




	public function hello()

	{	

	return 'Hello World';

        }



proof that another controller can access the method

In another controller




	public function actionIndex()

	{

   echo  SiteController::hello();

	die;

...



Hope this helps, FWIW I would use components for a shared method.

doodle ;)

Why is not recomended?

I would be interested to know why this solution deserves a negative score?

Sorry I didn’t have email notification set.

I think it’s a bad idea because each controller should really be discreet and only hold the code that the controller needs. Once code is shared between different controllers it’s best to put it elsewhere, example is a component.

Next time you come across this situation why not create a php file call it whatever you want. Example call it MyUtils.php then in controller(s) you can access the same code.








// isCoolDude returns true or false depending on coolness factor

echo (MyUtils::isCoolDude($buddy) ? "This dude is cool" : "Na, he's not cool!");



Each time you come across a similar global requirement add another method to your MyUtils.php file after a while, even on a simple application you will probably have half a dozen methods to call.

@abajja

Negative score was not from me but probably given because your suggestion only redirects it doesn’t allow access to a method. The original question was

FWIW I think it is pointless to give negative feedback without a reason, nobody learns from this.

doodle

Think to, many controllers rely on the same loadModel method referencing $_GET[‘id’]. If you’re not very careful with what methods you’re using and how, you could end up with unexpected (and undesired) results.

Making it difficult to achieve this type of behavior is one way of protecting us from ourselves so that if you’re doing it you know exactly what you’re doing and why. ;)

I agree that calling methods from another controller is a bad practice.

If a method is such important that more than one controller requires it, it means that is business logic, and business logic is better to put in model.

If the method doesn’t deserve to be put in a model, it also doesn’t deserve to be shared among controller.

If is, for example, loadModel, it absolutely doesn’t deserve to be shared among controller, as in practice it just call a method of the model (findByPk). Simply use this method.

PHP also supports inheritance. If you have a function that multiple controllers need to have you can make an abstract class extend CController, and make your other controllers extend that one:


abstract class ControllerParent extends CController

{

   // This is the method you want your Controllers to share/overload

   public function echoClassname()

   {

      echo get_class($this);

   }

}


class ChildA extends ControllerParent

{

   public function echoClassname()

   {

      parent::echoClassname();

      echo '<br />Yep!';

   }

}


class ChildB extends ControllerParent

{

   public function echoClassname()

   {

      parent::echoClassname();

      echo '<br />Totally!';

   }

}

In this case you can also just leave your child classes empty and then they’d be able to call ChildA->echoClassname() and it would just use the version defined in the parent.

@doodle

In no time I thought that the score is from you. And agree with you that it "is pointless to give negative feedback without a reason".

That said, the question we try to answer is too vague.

It is a disjunction of two sentences: How can I use a method… OR how can I call a method…

While my suggestion seems not to be a transparent call** (what is a call?) to a method (action), it is clearly a reply to How can I use a method which is in this case an action… thus a (not the) reply to the question.

The verb use is defined in Merriam Webster as:

Now, I can understand that this may not be what one expects as solution to his problem, in this case he can precise the question.


** redirect is implemented by mean of the php function header.

if you test :

mytest.php


<?php 

header("Location:http://testdrive/index.php?site/index");

?>

In Yii environment the application instantiate the controller site and actionIndex() is excuted.

@abajja Yes, I agree, but sometimes I think people have difficulty explaining their situation or exact needs.

I think the main thing is we should all be trying to help each other.

If we are all helpful and not criticizing each other this can become a very strong community. There is much to learn here, the level of programming skill of many of the board members is excellent. I hope one day to be an excellent programmer and I am still on a steep learning curve.

This is an excellent point you have raised, but this will only work with a method prefixed with ‘action’ ; correct?

take care,

doodle

Yes correct. In the general case where the method is an action or not the short reply to the question is Refactor. How ? it depends:

  • write the method in Controller. Note that by default our customized controllers (yiic and gii) derive form Controller…

  • if it is an action one can derive it from CAction, see: CViewAction, CCaptchaAction…

  • or redesign the application because we are wrong.

This is an older post, but I thought I’d respond to it, as I think it’s helpful to consider these kinds of academic questions, from time to time. I’ve been working on something similar to this, myself, and it’s forced me to think carefully about why some things belong in certain places and others need to be accessible from elsewhere. I disagree with the post above that anything that is shared by more than one controller is therefore to be considered business logic and belongs in a model. Remember, models represent business rules/logic (which usually means interfacing with some kind of persistence layer, too) and controllers handle requests (usually) from some kind of HTTP client (often a browser) and, subsequently, responses to the request (by rendering the view). Your models should not “know” about requests/responses: they should just be themselves, agnostic to the fact that there are HTTP clients buzzing around. There could, in fact, be a need for logic in more than one place to handle an HTTP request/response that has little or nothing to do with the persistence layer or the business rules. This would be a controller’s job. Putting such logic in a model muddies the separation of concerns we’re aiming for when we use an MVC framework.

That being said, the proper thing to do, in such a case, seems to be to include the functionality you need in a behavior or other place that is accessible to more than one controller. This way, you can let the individual controllers deal with the specific logic that distinguishes them from each other while still benefiting from the availability of this shared code. (A good example is the utility class Doodle mentions above.) I also kind of like the idea of extending an abstract controller which is then placed in "components" so that it can be extended as needed. For me, the choice comes down to whether or not the controllers are truly similar/related things (like siblings) or whether they simply do similar things, at times, almost by coincidence. The former suggests that they need to descend from a common parent (abstract class in the "components" directory), while the latter suggests that you could set up a utility class (behavior, perhaps) to parse whatever needs parsing for anybody who needs that kind of work done.

One of the wonderful things about OOP is that you really can think holistically about your design and not just getting from point A to point B. But I probably spend too much time sitting in front of the computer and have gotten a little wacky about things like that. :P

hi friends you can call a controller method from your model

by

$controller=Yii::app()->getController();

$controller->mail($param);

You should create the action alone extending CAction, use the actions() method inside your controllers. And then you can use the action in what ever controller you want.

That only if you want it to be an action (accesible from browser).

Otherway you should use a Component / helper.

If the method is related to others controller methods then you could do what rajesh said above.