4
votes

I am in the process of learning Yii2 more in depth, so I was wondering if it is possible for a widget to have something similar to actions in a controller?

In example:

class WTest extends Widget {

    public ...;

    public function init() {
      ...
    }

    public function run() {
        Pjax::begin();
        echo "<a href='".Yii::$app->urlManager->createAbsoluteUrl("test/add")."'>Add test</a>";
        Pjax::end();
    }

    public function addThing() {
      echo "hola"
    }
}

Then in a controller do:

class TestController extends Controller
{
  public function actionAdd() {
    $wObj = new WTest;
    return $wObj->addThing();
  }
}

The issues with this way is that I loose all the parameters set when calling the widget in the form, since I am calling "new WTest", it is a new instance. I have tried using a static method too, but similar issue, any ideas?

UPDATE In the view, I am calling the widget like this:

        WTest::widget([
            'test' => 'hi'
        ]);
2
If you want to have only one instance, you should use singleton pattern for it. - ThanhPV
Can you give me an example? I am not sure how to apply Singleton in this case - Eduardo

2 Answers

2
votes

Update: Remove private __contruct(), __clone() and use yii2 dependency injection. In class WTest, you should define some function and variables:

class WTest extends Widget
{
    /**
     * @var WTest The reference to *WTest* instance of this class
     */
    private static $instance;

    /**
     * Returns *WTest* instance of this class.
     *
     * @return WTest The *WTest* instance.
     */
    public static function getInstance()
    {
        if (null === static::$instance) {
            static::$instance = new static();
            //Add more attribute and do many stuff here
        }

        return static::$instance;
    }

    //If you want set value for variable, use yii2 DI
    /** @var string $test */
    public $test;
}

And use in your action:

public function actionAdd() {
    $wObj = WTest::getInstance();
    return $wObj->addThing();
}

Use in views:

WTest::widget([
    'test' => 'value',
]);

Hope it helpful.

More info about singleton pattern: http://www.vincehuston.org/dp/singleton.html.

Good luck and have fun!

0
votes

Answer from ThanhPV was not completely right but it guide me to the correct direction by using Dependency Injection :)