We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Controllers

Hi all. Phalcon have event for controllers like 'before custom action' and 'after custom action' ?

RompePC, thank you, but what if I want to point out himself controller / action ?



33.8k

I think this is the most near approach of what you want.

if ($dispatcher->getActionName() === 'something') {
    // Do stuff.
}
edited Mar '15

I think this is the most near approach of what you want.

if ($dispatcher->getActionName() === 'something') {
   // Do stuff.
}

I want set custom controller/action before/after event


class TestController
{
    public function indexAction()
    {
    }
}

//then
class Whatever 
{
    public function mySuperAction()
    {
        $data = whatever;
        $data2 = whatever;
        $this->event->fire('testcontroller.beforeIndexAction', $data);
        $this->event->fire('testcontroller.afterIndexAction', $data2);
    }
}

I think you shuld extends from controllerBase, ex:

//ControllerBase.php parent super class controllers
class ControllerBase extends \Phalcon\Mvc\Controller
{
    public function beforeExecuteRoute($dispatcher)
    {
        $post = $this->request->getPost(); //or get
        //when you access from some url: https://localhost/controller/beforeIndex
        if ($dispatcher->getActionName() == "beforeIndex") {
            $dispatcher->forward(array(
                "action" => "beforeIndexAction", //or after you decide
                "controller" => "testController",
                "params" => $post
            ));
        } 

    }
}

//Test Controller.php

use Project\Controllers\ControllerBase as Controller;

class function TextController extends Controller
{
    public function ....etc
}

I dont want set this on ControllerBase, because this solution not flexible

"action" => "beforeIndexAction", //or after you decide
"controller" => "testController",

I want do that on any controller, now i has like this

namespace Core\Controllers;

class BackendController extends \Phalcon\Mvc\Controller
{
    protected $eventsManager;

    public function initialize()
    {
        $modules = \Core\Models\Module::find("state = 1");

        //Events
        $this->eventsManager = new  \Phalcon\Events\Manager();

        foreach ($modules as $module)
        {
            $moduleNamespace = '\Modules\\'.ucfirst($module->name).'\Backend\Controllers\\'.ucfirst($module->name).'Controller';
            $this->eventsManager->attach($module->name, new $moduleNamespace);
        }
    }
}

namespace Modules\Catalog\Backend\Controllers;

class CatalogController extends \Core\Controllers\BackendController
{
    public function indexAction()
    {
        $this->eventsManager->fire("categories:IndexAction", $this);
        echo "Catalog module";
        $this->eventsManager->fire("page:afterIndexAction", $this);
    }
}

namespace Modules\Categories\Backend\Controllers;

class CategoriesController extends \Core\Controllers\BackendController
{
    public function indexAction()
    {
        $data = array('category 1', 'category 2', 'category 3', 'category 4', 'category 5');
        $this->view->partial(__DIR__.'/../views/index', array('data' => $data));
    }
}

//but i want do this on CategoriesController not on CatalogController
//like this

namespace Modules\Catalog\Backend\Controllers;

class CatalogController extends \Core\Controllers\BackendController
{
    public function indexAction()
    {
        echo "Catalog module";
    }
}

class CategoriesController extends \Core\Controllers\BackendController
{
    public function indexAction()
    {
        $data = array('category 1', 'category 2', 'category 3', 'category 4', 'category 5');
        $this->eventsManager->fire("catalog:beforeIndexAction", $data);
    }
}


22.8k
edited Mar '15

You dont need to do this

"action" => "beforeIndexAction", //or after you decide
"controller" => "testController",

If you extend from your baseController and define the before and afterExecute actions in your baseController they will always fire/execute by default. The baseController actions will fire first then your extended controller actions will fire. If you dont want to execute the before or afterExecute actions on the baseController then just dont extend from the baseController, or in your baseController identity the controllers that should not be affected by the beforeor after execute functions.

eg.

// inside the beforeExecuteRoute Action of the basecontroller
$actioName = $this->dispatcher->getActionName();
$ctrlName = $this->dispatcher->getControllerName();
$ignoreRoutes = array('user' => 'view') // key = controller, val = action
if($ignoreRoutes[$ctrlName][$actioName]) {
    return true; // ignore this
} 
// else do the rest
edited Mar '15

Thanks, but i not understand, how this help me ? An example of a pure php

I have parent class

class Parent
{

}

And extends from parent

class Child extends Parent
{
    function test()
    {

    }
}

class Child2 extends Parent
{
    function test2()
    {
        echo ' I want extends method test() on class Child here, not changing class Child !!! ';
    }
}

When i call class Child method test() like this

$child = new Child();

$child->test(); // i want get ' I want extends method test() on class Child here, not changing class Child !!! ';



22.8k
edited Mar '15

The you can just call the function from the parent class.

class Child2 extends Parent
{
    function test2()
    {
        parent::test(); // will call the parent test() function
        $child1 = new Child1(); // child1 object
        $child1->test(); // test function on child1
    }
}