HTTP-Anfrage vom Admin-Plugin (.js) an den Controller

Hallo zusammen,

ich habe ein Sub-Modul via myPlugin zum Bestellmodul in der Administration hinzugefügt. Was ich jetzt versuche, ist, einen HTTP-Request über mein Plugin zu senden, um die Bestellungen zu holen und dann diese Informationen in meiner Admin-Komponente für das Modul zu verwenden.

Ich erhalte den folgenden Fehler, wenn ich versuche, die Anfrage zu senden:
‚code‘: „0“
‚status‘: „404“
‚title‘: „Not Found“

Ich wäre sehr dankbar, wenn mir jemand bei diesem Problem helfen könnte.

Hier ist, was ich bis jetzt gemacht habe.

File: // <plugin root>/src/Resources/app/administration/src/main.js
import './module/counter-order'

const { Component } = Shopware;

Component.register(
    'counter-list',
    () => import('./module/counter-order/page/counter-list')
);
File: // <plugin root>/src/Resources/app/administration/src/module/counter-order/index.js
import deDE from '../snippet/de-DE/de-DE.json'
import enGB from '../snippet/en-GB/en-GB.json'
import './page/counter-list';

Shopware.Module.register('counter-order', {

    type: 'plugin',
    name: 'counter-order',
    color: '#ff3d58',
    icon: 'default-shopping-paper-bag-product',
    title: 'counter-order.general.mainMenuItemGeneral',
    description: 'counter-order.general.descriptionTextModule',

    snippets: {
        'de-DE': deDE,
        'en-GB': enGB
    },

    routes: {
        index: {
            component: 'counter-list',
            path: 'index'
        }
    },

    navigation: [{
        id: 'counter-order',
        label: 'counter-order.general.mainMenuItemGeneral',
        color: '#ff3d58',
        path: 'counter.order.index',
        icon: 'default-shopping-paper-bag-product',
        parent: 'sw-order',
        position: 100
    }],

})

File: // <plugin root>/src/Resources/app/administration/src/module/counter-order/page/counter-list/index.js

import template from './product-list.html.twig'

export default Shopware.Component.register('counter-list', {
    template: template,

    data() {
        return {
            isLoading: false,
        };
    },

    created() {
        this.createdComponent();
        this.fetchOrders()
    },

    methods: {
        createdComponent ()  {
            console.log('Counter List page loaded');
        },

        fetchOrders () {
            this.isLoading = true;

            Shopware.Service('syncService').httpClient.get(
                '/counter-order/orders',
                {
                    headers: {
                        Authorization: `Bearer ${Shopware.Context.api.authToken.access}`,
                        'Content-Type': 'application/json'
                    }
                }
            ).then((response) => {
                console.log('📦 Orders:', response.data.orders);
            }).catch((error) => {
                console.error('❌ Error loading orders', error);
            }).finally(() => {
                this.isLoading = false;
            });
        }
    }
})
File: // <plugin root>/src/Resources/app/administration/src/module/counter-order/page/counter-list/product-list.html.twig
<sw-page class="counter-order">
    <template #smart-bar-header>
        <h2>Counter Orders</h2>
    </template>

    <sw-card title="Product List">
        <div>
            Content goes here...
        </div>
    </sw-card>
</sw-page>
File: // <plugin root>/src/Controller/Api/CounterOrderController

<?php declare(strict_types=1);

namespace myPlugin\Controller\Api;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Shopware\Core\Framework\Context;
use Symfony\Component\HttpFoundation\JsonResponse;
use Shopware\Core\Checkout\Order\OrderEntity;
use Symfony\Component\Routing\Annotation\Route;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;

#[RouteScope(defaults: ['_routeScope' => ['api']])]
class CounterOrderController extends AbstractController
{
    private EntityRepository $orderRepository;

    public function __construct(EntityRepository $orderRepository)
    {
        $this->orderRepository = $orderRepository;
    }

    #[Route(path:'/api/counter-order/orders', name: 'api.counter_order.orders', defaults: ['auth_required' => false, 'XmlHttpRequest' => true], methods: ['GET'])]
    public function orders(Context $context): JsonResponse
    {
        $criteria = new \Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria();
        $criteria->setLimit(10);

        $orders = $this->orderRepository->search($criteria, $context);

        return new JsonResponse([
            'orders' => $orders->getEntities()->fmap(fn(OrderEntity $order) => [
                'id' => $order->getId(),
                'orderNumber' => $order->getOrderNumber(),
                'totalPrice' => $order->getAmountTotal(),
                'createdAt' => $order->getCreatedAt()?->format('Y-m-d H:i:s'),
            ])
        ]);
    }
}
File: services.xml

        <service id="myPlugin\Controller\Api\CounterOrderController" public="true">
            <argument type="service" id="order.repository" />
            <tag name="controller.service_arguments" />
        </service>

Interessanter Ansatz.

So kommst du an die Daten… Using the data handling | Shopware Documentation

Wenn du unbedingt einen eigenen request bauen möchtest, dann orientiere dich an den Beispielen der vorhandenen Shopware services. Beispiel: shopware/src/Administration/Resources/app/administration/src/core/service/api/calculate-price.api.service.js at trunk · shopware/shopware · GitHub
Du hast insbesondere getBasicHeaders() und handleResponse() übersehen.

Viele Grüße

@EikeBrandtWarneke Danke für das Beispiel. Ich habe es auf 2 verschiedene Arten versucht, aber leider verstehe ich nicht ganz, wie ich den ApiService tatsächlich in meine .js-Datei importieren kann. Welchen Pfad sollte ich verwenden? Oder ist es möglich, dieses Service über das Shopware-Objekt zu erhalten?

Daher habe ich einfach den Vorschlag von @Max_Shop übernommen. Bis jetzt bekomme ich die Bestellungen.