How to add and use multiple actions into Apigilities RPC Generated Controller

1k views Asked by At

i need your advice. I need to create multiple Actions in RPC style API Controller generated by Apigility. How do I need to make routing, to make it work like it is in normal zend application.

'application' => array(
                'type'    => 'Literal',
                'options' => array(
                    'route'    => '/application',
                    'defaults' => array(
                        '__NAMESPACE__' => 'Application\Controller',
                        'controller'    => 'Index',
                        'action'        => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Segment',
                        'options' => array(
                            'route'    => '/[:controller[/:action]]',/*I need flexible route like this one*/
                            'constraints' => array(
                                'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                                'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                            ),
                            'defaults' => array(
                            ),
                        ),
                    ),
                ),
            ),

Code generated by Apigility is:

<?php
namespace TestAPI\V1\Rpc\Test;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\JsonModel;

class TestController extends AbstractActionController
{
    public function TestAction()
    {
        /*Added by myself*/
        return new JsonModel(array(
            'id' => 'test',
        ));
    }

}

and routing is generated this way:

'controllers' => array(
    'factories' => array(
        'TestAPI\\V1\\Rpc\\Test\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\TestControllerFactory',
    ),
),
'zf-rpc' => array(
    'TestAPI\\V1\\Rpc\\Test\\Controller' => array(
        'service_name' => 'test',
        'http_methods' => array(
            0 => 'GET',
        ),
        'route_name' => 'test-api.rpc.test',
    ),
),

Thank You for your help!

3

There are 3 answers

0
Édipo Costa Rebouças On

Solution 1

Try register aliases on controllers key to your controller and register each alias on zf-rpc config.

Something like that:

'controllers' => array(
    'factories' => array(
        'TestAPI\\V1\\Rpc\\Test\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\TestControllerFactory',
    ),
    'aliases' => array(
        'TestAPI\\V1\\Rpc\\Test2\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\Controller',
        'TestAPI\\V1\\Rpc\\Test3\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\Controller',
    ),
),


'zf-rpc' => array(
    'TestAPI\\V1\\Rpc\\Test\\Controller' => array(
        'service_name' => 'test',
        'http_methods' => array(
            0 => 'GET',
        ),
        'route_name' => 'test-api.rpc.test',
    ),
    'TestAPI\\V1\\Rpc\\Test2\\Controller' => array(
        'service_name' => 'test2',
        'http_methods' => array(
            0 => 'GET',
        ),
        'route_name' => 'test-api.rpc.test2',
    ),
    'TestAPI\\V1\\Rpc\\Test3\\Controller' => array(
        'service_name' => 'test3',
        'http_methods' => array(
            0 => 'GET',
        ),
        'route_name' => 'test-api.rpc.test3',
    ),
),

Probably you have to copy and change de route config and another configs.

Solution 2

You can try generate another rpc service and change the factory to a alias, all configs will generate to you.

after you generate the service, you will get something like this:

'controllers' => array(
        'factories' => array(
            'TestAPI\\V1\\Rpc\\Test\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\TestControllerFactory',
            'TestAPI\\V1\\Rpc\\Test2\\Controller' => 'TestAPI\\V1\\Rpc\\Test2\\TestControllerFactory',
        ),
    ),

You have to change to something like this:

'controllers' => array(
        'factories' => array(
            'TestAPI\\V1\\Rpc\\Test\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\TestControllerFactory',
        ),
        'aliases' => array(
            'TestAPI\\V1\\Rpc\\Test2\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\Controller',
        ),
    ),
0
Hasina On

You can try this for routing :

'controllers' => array(
    'factories' => array(
        'TestAPI\\V1\\Rpc\\Test\\Controller' => 'TestAPI\\V1\\Rpc\\Test\\TestControllerFactory',
    ),
),
'zf-rpc' => array(
    'TestAPI\\V1\\Rpc\\Test\\Controller' => array(
        'service_name' => 'test',
        'http_methods' => array(
            0 => 'GET',
        ),
        'route_name' => 'test-api.rpc.test',
    ),
),
'router' => array(
        'routes' => array(
            'test-api.rpc.test' => array(
                'type' => 'Segment',
                'options' => array(
                    'route' => '/api/test[/:action_name]',
                    'defaults' => array(
                        'controller' =>'TestAPI\\V1\\Rpc\\Test\\Controller',
                        'action' => 'test',
                ),
            ),
        ),))

` And in your controller :

<?php
namespace TestAPI\V1\Rpc\Test;

use Zend\Mvc\Controller\AbstractActionController;

class TestController extends AbstractActionController
{
    public function testAction()
    {
        $action_name = $this->getEvent()->getRouteMatch()->getParam('action_name');
        switch ($action_name) {
            case 'test1':
                return $this->test1Action();
            default:
                return array();
        }
    }

    public function test1Action(){
        //Your code here
        return ...; //preferable to be array
    }
}

the url is .../api/test/test1

I Hope this will help you.

0
PowerKiKi On

Multiple actions per controller is discouraged by Matthew Weier O'Phinney (Apigility's creator):

No.

Apigility's RPC functionality posits one route -> one controller -> one action (although we allow multiple HTTP methods to it). This is for several reasons:

  • Simplifies configuration
  • Simplifies finding the code for a given route (exactly one place to look)
  • Helps prevent large controllers

What I'd do is create a service object that can handle the various related operations, and then an RPC service per discrete operation (unless that operation could be described using different HTTP verbs on the same route, that is). Then inject each controller with that service object, and call the appropriate method.

source: https://groups.google.com/a/zend.com/d/msg/apigility-users/Or3xBLAd9Y0/RzQKIMpaV0cJ