CakePHP 3.x how do I include the params in the map

2019-09-06 10:31发布

问题:

this is what I have in my routes:

Router::scope('/', function ($routes) {
    $routes->extensions(['json']);
    $routes->resources('CustomerCompanies', [
        'map' => [
            'get_by_account' => [
                'action' => 'get_by_account',
                'method' => 'GET',
            ]
        ]
    ]);  

This is my method get_by_account inside CustomerCompaniesController.php:

/**
 * Pagination method by Customer Account id
 *
 * @param string|null $id Customer Account id.
 * @return void Redirects to index.
 * @throws \Cake\Network\Exception\NotFoundException When record not found.
 */
public function get_by_account($customer_account_id = null)
{

}

Relations:

  1. CustomerAccounts hasMany CustomerCompanies
  2. CustomerCompanies belongsTo CustomerAccounts

I want to return a list of CustomerCompanies that belong to a particular CustomerAccount by supplying the CustomerAccount id and I get back in json results.

Do I need to change something in the get_by_account to indicate the param? and if so, how?

UPDATE

This is what I saw in the documents:

回答1:

You have to define the :id route element, which is being passed by default (there is currently no way to pass further custom route elements). You can do that either in the array key of your map entry

'map' => [
    'get_by_account/:id' => [
        'action' => 'get_by_account',
        'method' => 'GET',
    ]
]

or via the path option (by default, the key is set as the value for the path option)

'map' => [
    'get_by_account' => [
        'action' => 'get_by_account',
        'method' => 'GET',
        'path' => 'get_by_account/:id'
    ]
]

See also

  • Cookbook > Routing > Mapping Additional Resource Routes
  • Source > \Cake\Routing\RouteBuilder::$_resourceMap


回答2:

I realized that business logic wise, I was trying to create a nested resource.

Hence I will include my answer to another one of my own question about creating nested resource here.

------- ANSWER -----------

Do this in your routes.php

$routes->resources('Parents', function ($routes) {
    $routes->resources('Children');
});

$routes->resources('Children');

In ChildrenController.php,

protected function _prepareConditions() {
    $parentId = isset($this->request->params['parent_id']) ? $this->request->params['parent_id'] : null;

    if ($parentId == null) {
        return [];
    }

    return [
        'Children.parent_id' => $parentId
    ];
}

public function index()
{
    $conditions = $this->_prepareConditions();

    $this->paginate = [
        'contain' => ['Parents'],
        'conditions' => $conditions
    ];
  // ... and so on

You will be able to do the following:

  1. /parents/1/children
  2. /parents/1/children.json
  3. /children
  4. /children.json

Why this works?

http://book.cakephp.org/3.0/en/development/routing.html#creating-nested-resource-routes

tells us that basically to basically retrieve the parent id from the request params.

What it does not say explicitly is that, the routes will then reuse the basic 5 functions: index, add, view, delete, edit even when you nest them under a parent url.

Why do you still have a separate resources route for the Children?

This allows the /children and /children.json to work if you need them as well.

What about add?

I haven't tried that but I do not foresee any issues with using that as

  1. /parents/1/children/add
  2. /parents/1/children/add.json
  3. /children/add
  4. /children/add.json