Yii 1.1: How to use a Widget as an Action Provider

40 followers

What is an Action Provider Widget?

As written on the API docs: An Action Provider Widget is a widget that has declared several actions by using its 'public static function actions()'. After, a Controller can easily import all its declared actions on its 'public function actions()'.

Step 1: Create the Action Class

For the sake of the article we need to create an action named getData that is supposed to be shared among the whole project and saved with the name getData.php on our protected/components/actions folder.

class getData extends CAction{
    public function run(){
        echo 'HELLO WORLD';
    }
}

Step 2: Configure the Widget

To transform a Widget into an action provider is quite easy (once you know of course). The only thing we need to do is to set the static function actions(). As you will see on the following code, we name the action as GetData and that is the action that will be called in our route. We are going to save the following widget in our protected/components/ folder with the name testProvider.php.

class testProvider extends CWidget{
    public static function actions(){
        return array(
           // naming the action and pointing to the location
           // where the external action class is
           'GetData'=>'application.components.actions.getData',
        );
    }
}

Step 3: Configure the Controller

Finally we set our controller’s actions() function to point to our actions provider.

// This function is in this example
// on SiteController
public function actions()
{
   return array(
      // test. is the prefix we are going to use on our URL
      // for all actions within the actionProvider class
      // we point to the location where the provider
      // is.
      'test.'=>'application.components.testProvider',
    );
}

All done, now we can call all the actionProvider actions as controllerID/actionPrefix.actionID. Here is the example:

index.php?r=site/test.GetData

Passing Parameters to Actions

As you all know, and already explained in the wiki Actions Code Reuse with CAction, Actions are classes that extend from CAction, that is, a CComponent. If we wish to pass parameters to the actions that are within the provider, we have to do it this way when configuring your controller (step 3) (Thanks to Attilio for pointing this out):

// This function is in this example
// on SiteController
public function actions()
{
   return array(
      // test. is the prefix we are going to use on our URL
      // for all actions within the actionProvider class
      // we point to the location where the provider
      // is.
      'test.'=>array(
         'class'=>'application.components.testProvider',
         'getData'=>array(
            // property1 must be a public variable
            // on getData CAction class
            'property1'=>'value1',
           ),
        ),
    );
}

Total 14 comments

#15724 report it
KonApaz at 2013/12/10 08:00am
Pass a parameter runtime

Hi

How to pass parameter on runtime ?

For example

'getData'=>array(
            'property1'=>(Yii::app()->user->isGuest ? $_GET['property1'] : 'default'),
),
 
Is it corrected ? , I think it isn't...
#13955 report it
KonApaz at 2013/07/09 07:22am
re: Different approach

I agree with you Boaz

Actually my widget is an extension of a module!

So the schema is

modules:
  mymodule:
    extensions:
        mywidget:
          mywidget.php
          action:
              theactionRelatedWithMyWidget.php

I want the widget reusable for other uses, thats why this schema! I could use it as a module inside to another module but is to complicated!

#13954 report it
KonApaz at 2013/07/09 07:16am
Re: about render

Thanks CeBe for your response

1) I supposed, since it is posible use static actions there was a way to do that directly, but as I understand there is no way because in this case widget works as action provider!

2) The anwser is related with first question. If the action could be into widget we could be used $this->render('directlyviewfilename');

#13950 report it
Boaz at 2013/07/09 05:40am
Different approach

I hope this is considered too blunt :-) :

During my time with Yii I came to prefer not using the suggested design scheme at all. Rather, whenever I have a widget that is required to 'do something', meaning process something on server side as a response to user action on client side, I prefer packing the widget in a module and adding there controller classes, even AJAX only controller action methods.

I find this scheme cleaner and thus easier to maintain. Under this view, a widget is not a swiss army knife but rather used to show stuff to users, and that's it.

#13949 report it
CeBe at 2013/07/09 05:34am
Re: about render

1) but how create action directly in widget ?

you can only create Action classes and refer to them in actions() method in the widget. Inline actions are only supported by controllers.

2) how render a view without set entire path ?

I'm afraid there is no better way to do it currently. You have to use controller render().

#13947 report it
KonApaz at 2013/07/09 05:03am
about render

Very good wiki!

1) but how create action directly in widget ?

2) how render a view without set entire path ? for example I create a widget for a module and the only way that works is $this->controller->render('application.modules.mymodule.views.upload'); because the $this->render does not works (CAction has not a render method) and the Controller is not the widget itself (because works as provider) How can I get the current widget to do that ?

Thanks

#11716 report it
Jmper at 2013/01/29 05:54am
Action maps are case sensitive

It is worth noting that, opposite to normal actions, actions defined through provider are case sensitive. For example you can have

public function actionGetData() {
...
}

in your controller, and have a link

index.php?r=controller/getdata

However, if you define the action through action provider, like in this article, you cannot use

index.php?r=controller/test.getdata

This will give you 404 error. You have to use

index.php?r=controller/test.GetData
#11097 report it
Cherif at 2012/12/16 04:00pm
HMVC

Is this how we can implement the HMVC in Yii? It sounds like what it is discused here HMVC

#6576 report it
Antonio Ramirez at 2012/01/19 09:15am
@charliehyii

Thanks charlie... is now fixed

#6555 report it
Charlie Hand at 2012/01/18 11:38am
Incorrect URL

In the default configuration of Yii, the url has to be index.php?r=site/...

instead of index.php?site/...

#4110 report it
Mike at 2011/06/07 05:56am
Passing additional parameters to specific actions

@Tony: Maybe you can inlcude what Attilio found out here?

#3787 report it
Antonio Ramirez at 2011/05/08 05:38am
@yiqing95

That is not bad approach. Nevertheless, the point of the article was how Yii uses a widget as an action provider which is not documented elsewhere.

The widget encapsulates all the 'shared' actions throughout our application, that means, that we do not need to 'include' one by one all the shared actions . As you can see on the article, I just need to include the Actions Provider and thats it, all its actions will be included at once. This is the actual role of the widget.

#3714 report it
yiqing95 at 2011/05/01 07:37am
widget as Action

let's say : class MyActionWidget extends CWidget { // public $actionPrefix = 'act_'; /no use/

 public static function actions(){
            return array(
               'route1'=>'someName',
               'route2'=>'someName2',
            );
    }
public function someName(){ $this->render('someView1');}
public function someName2(){ $this->render('someView2');}

} in controller public function actions() {

            return array(
                    'test.'=>'application.components.MyActionWidget',
            );
    }

know i can access it from route: index.php/site/test.rout1 or index.php/site/test.rout2
the key point is that key in actions function of controller('test.') end with dot '.' will be treated as a widget but a CAction subcalss . above code just my imagination , please don't mislead by me.

#3713 report it
yiqing95 at 2011/05/01 07:17am
widget as Action

why do you directly config the actions function of controller like: return array(

  'getData'=>'xx.xxx.getData',
);

now we can access it from route: index.php?site/getData; above is the normally usage;
if follow your way, what's the role of widget? the question is CWidget doesn't extends the CAction , if so we can do a lot , refers to this wiki :http://www.yiiframework.com/forum/index.php?/topic/16357-how-to-use-widget-as-action-provider/page__p__81206__hl__actionPrefix#entry81206

Leave a comment

Please to leave your comment.

Write new article