Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

How to generate controller code with distinct method names in case of prefix in paths #84

Open
SOHELAHMED7 opened this issue Nov 2, 2021 · 12 comments

Comments

@SOHELAHMED7
Copy link
Contributor

I have use-case like below

  • GET /calendar/domains - get all domains. Domain here is model and DB table. calendar is just the prefix
  • GET /calendar/domains/{id} - get a domain by ID.

Here the base controller generates:

    abstract public function actionDomains();

    abstract public function actionDomains($id);

Two method with same name leads to errors.

How can code generation for above end-points can be achieved?

@Insolita
Copy link
Collaborator

Insolita commented Nov 2, 2021

Seems there is no way. This route is out of json-api resource conception.

GET /domains
GET /domains/{id} will return different actions

Also

GET /calendar/{calendarId}/domains
GET /calendar/{calendarId}/domains/{id}
will works correct

@Insolita
Copy link
Collaborator

Insolita commented Nov 2, 2021

Or do you assume REST usage, without JsonApi?
That part probably should be checked better, as well as last time jsonApi was most focused

But anyway - we need to detect and support CRUD operations (list/view/create/update/delete) and non-crud operations like /password/recovery/{token} /confirm/email/{email} /avatar/upload/{id}

@SOHELAHMED7
Copy link
Contributor Author

As of now I need to use with JSON:API.

I am using your package. It is very helpful. Generic actions fulfil my most use-cases. I am using it most to avoid custom actions.


regarding above end-points:

Calendar in not model or a DB table in my use-case as of now.

It is just a prefix.

@Insolita
Copy link
Collaborator

Insolita commented Nov 2, 2021

It is just a prefix.

So, prefixes are not supported. We expects that a resource name is a single world You can use

GET /domains
GET /domains/{id}

or

GET /calendar-domains
GET /calendar-domains/{id}

or

GET /calendar/domains/list
GET /calendar/domains/{id} (But generated templates may be different for this way)

@Insolita
Copy link
Collaborator

Insolita commented Nov 2, 2021

If we will start supporting prefixed resource routes,
GET /calendar/domains - should be pointed to DomainController or CalendarDomainController -> actionList
POST /calendar/domains - -> actionCreate
GET /calendar/domains/{id} - actionView($id)
PATCH /calendar/domains/{id} - actionUpdate($id)
DELETE /calendar/domains/{id} - actionDelete($id)

But now
POST /auth/confirm/{email} points to AuthController actionConfirm
POST /password/recovery points to PasswordController actionRecovery
GET /metric/visits points to MetricController actionVisists
if we will start supporting prefixed resources - we can't detect differences between crud resources and standalone actions.

@cebe what you think?

@cebe
Copy link
Owner

cebe commented Nov 4, 2021

JSON-API itself does not really say anything about URL design in this case. https://jsonapi.org/recommendations/#urls

if we will start supporting prefixed resources - we can't detect differences between crud resources and standalone actions.

it should probably be a configuration option to allow specifying grouping prefixes. If the API contains these prefixes a configuration could decide what to do with it. In some cases it might also make sense to generate Modules from URL prefixes.

So for example:

$urlPrefixes = [
    'calendar' => '', // drop prefix, create controller in main app
    'order' => 'order', // create controller in the order module
    'base/auth' => 'auth', // create controller in the auth module
    'auth' => 'auth/base', // create controller in the base/auth module - not sure if this case is needed (never used submodules in any application)
]

@Insolita
Copy link
Collaborator

Insolita commented Nov 4, 2021

'auth' => 'auth/base', // create controller in the base/auth module

It is not clear about the "base/auth module"

We can define
'prefix' => 'moduleName',
or prefix => 'moduleName/subModuleName'

Namespace and path should be resolved from Yii::$app->getModule('moduleName')->controllerNamespace etc/

or we need explicit
'prefix' =>['path' => '@app/modules/auth/controllers/base', 'namespace' => '/app/modules/auth/base']

@cebe
Copy link
Owner

cebe commented Nov 5, 2021

good point, we might need to generate the module if it does not exist so we have no idea about namespaces and paths.
Need to allow making these configurable.

We could allow both, string for module name and use default assumptions about naming and path. and allow array configuration for more detailed config.

@SOHELAHMED7
Copy link
Contributor Author

I suggest to make module creation for every prefix optional.

Example:

Lets take my above calendar example.

I need calendar prefix in my path but don't want calendar Yii module in my code. Also I don't have calendar DB table. Also there is no huge feature or functionalities around calendar

I just need it as prefix.

Path /calendar/* should be handled by controller defined in main app and not in any Yii module.

Current code generation Yii2-app-api for

GET /calendar/entry/{name} will create CalendarController and actionEntry()

this is fine

CalendarController file will be present in main app and not in any module

Now coming to main question that is present in issue description.

How to generate distinct function name for case like:

GET /calendar/domains - get all domains. Domain here is model and DB table. calendar is just the prefix
GET /calendar/domains/{id} - get a domain by ID.

This should be taken care of by code generator. A thought of mine:

GET /calendar/domains => CalendarController/actionDomains
GET /calendar/domains/{id} => CalendarController/actionDomainById (actionGetDomain or so...)

To achieve this I think we can use

yii\web\GroupUrlRule::$prefix

yii\web\GroupUrlRule::$routePrefix

 new GroupUrlRule([
     'prefix' => 'calendar',
     'routePrefix' => '',
     'rules' => [
         'GET domains' => 'calendar/domains',
         'GET domains/<id:\d+>' => 'calendar/domain-by-id',
         ...
     ],
 ]);

@Insolita
Copy link
Collaborator

Insolita commented Nov 5, 2021

I suggest to make module creation for every prefix optional.

Yes, module definition will be optional.
You will be able to define
'urlPrefixes' => [
'calendar' => ''
] in yii2-openapi and 'calendar' part will be handled by main app, without modules, but about next part...

This should be taken care of by code generator. A thought of mine:

GET /calendar/domains => CalendarController/actionDomains
GET /calendar/domains/{id} => CalendarController/actionDomainById (actionGetDomain or so...)

But what by you mind should be for
POST /calendar/domains,
PATCH /calendar/domains/{id} ,
DELETE /calendar/domains/{id}

@SOHELAHMED7
Copy link
Contributor Author

But what by you mind should be for

You mean to ask what are my thoughts about controller and action for below paths? If yes, then I think we can name it like:

POST /calendar/domains, => CalendarController -> actionAddDomain
PATCH /calendar/domains/{id}  => CalendarController -> actionUpdateDomain($id),
DELETE /calendar/domains/{id} => CalendarController -> actionDeleteDomain($id),

@Insolita Insolita mentioned this issue Nov 20, 2021
@cebe
Copy link
Owner

cebe commented Nov 20, 2021

I don't get why these routes should not generate DomainControlller with actionList(), actionCreate(), actionUpdate()...

do you suggest do provide GroupUrlRule in config to determine generated routes, controller and action from it?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: 📋 Backlog
Development

No branches or pull requests

3 participants