Search code examples
symfonyshopwareshopware6

Shopware 6 backend controller path


In Shopware 6, I want to call a backend (/admin) API controller from a backend / admin page using JavaScript. What is the correct way to use a relative path, probably with a built-in getter function?

Fetching /api/v1 only works if the shop is on /, but not when it is in a sub-folder.

fetch('/api/v1/my-plugin/my-custom-action', ...)

Solution

  • The best practice would be to write your own JS service that handles communication with your api endpoint.

    We have an abstract ApiService class, you can inherit from. You can take a look at the CalculatePriceApiService for an example in the platform. For you an implementation might look like this:

    class MyPluginApiService extends ApiService {
        constructor(httpClient, loginService, apiEndpoint = 'my-plugin') {
            super(httpClient, loginService, apiEndpoint);
            this.name = 'myPluginService';
        }
    
        myCustomAction() {
            return this.httpClient
                .get('my-custom-action', {
                    headers: this.getBasicHeaders()
                })
                .then((response) => {
                    return ApiService.handleResponse(response);
                });
        }
    }
    

    Notice that your api service is preconfigured to talk to your my-plugin endpoint, in the first line of the constructor, which means in all the following request you make you can use the relative route path.

    Keep also in mind that the abstract ApiService will take care of resolving the configuratuion used for the Requests. Especially this means the ApiService will use the right BaseDomain including subfolders and it will automatically use an apiVersion that is supported by your shopware version. This means the apiVersion the ApiService uses in the route will increase every time a new api version is available, that means you need to work with wildcards in your backend route annotations for the api version.

    Lastly keep in mind you need to register that service. That is documented here. For you this might look like this:

    Shopware.Application.addServiceProvider('myPluginService', container => {
        const initContainer = Shopware.Application.getContainer('init');
        return new MyPluginApiService(initContainer.httpClient, Shopware.Service('loginService'));
    });