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

Routing rule to get all POST data as action argument

Hi everyone, I am creating a REST API (keeping the MVC layer) and what I want to manage is to have a routing rule that give me the capability to write my action like this

public function createAction($data) 
{
    echo "<pre>" . __METHOD__ . "</pre>";
    var_dump($data);
    exit;
}

So I would like to get all the POST data as the action argument. I've tried different combination but without success, below my current code that is not working for POST calls

$router->add("/user", array(
    'module' => 'user',
    'controller' => 'rest',
    'action' => 'create',
    'data' => ':params'  // how to write correctly this?
))->via(array("POST"));

Any idea to solve this?

Thanks

Why don't you get all POST values from request object ?

$postValues = $this->request->getPost();

How will this abstraction make sense in the context of a PUT where it has to be operated on an ID? In that case would you have two parameters on updateAction?

I've built several API's and I think it might make more sense to use this as a DI service, so that way you can lazy load the body of the call when you need it

$di->setShared('body', function() {
    $body = json_decode(file_get_contents('php://input'), false);
    if ($body === null) {
        //throw an exception here because we have an invalid json format
    }
}

// Then inside a controller:

public function createAction($data) 
{
    echo "<pre>" . __METHOD__ . "</pre>";

    //body is a lazy loaded service that is only parsed when we request it
    var_dump($this->body);
    exit;
}

If you'll notice this accomplishes two things:

1) Parses the validity of our json and handles exception throwing at a global level

2) Abstracts the need for passing the variables into each every single function that will need it. Now you just access the global di service



2.2k
Accepted
answer
edited Dec '14

How about this?

    $di->set('dispatcher', function() use ($di) {
        //Create an EventsManager
        $eventsManager = new Phalcon\Events\Manager();

        $eventsManager->attach("dispatch:beforeDispatchLoop", function($event, $dispatcher) use ($di) {
            //Possible controller class name
            $controllerName = Phalcon\Text::camelize($dispatcher->getControllerName()) . 'Controller';
            //Possible method name
            $actionName = $dispatcher->getActionName() . 'Action';

            if (($controllerName === 'IndexController') && ($actionName === 'createAction')) {
                $dispatcher->setParams(array($di['request']->getPost()));
            }
        });

        $dispatcher = new Phalcon\Mvc\Dispatcher();
        $dispatcher->setEventsManager($eventsManager);

        return $dispatcher;
    });

Thanks for all your answers guys, I've very appreciated.

I managed to do it thanks to the @kenjis answer, so I'll accept his answer.

Cheers!