Durchsuchbares Produkt Repository für Zusatzfeld Objekt Produkt

Ich versuche mich gerade an einem Plugin, dass mir ein durchsuchbares Produkt Repository für meinen aktuellen Saleschannel bereitstellt. Darüber will ich an die Produkt-Objekte herankommen.
Ich bekomme jetzt aber, egal wie ich meine Klasse nenne, einen Error.
Ich hoffe mir kann jemand sagen, was mein Fehler ist, ich bin am Verzweifeln.

Compile Error: Cannot declare class Roth\ProductRepo\Twig\RothProductRepo, because the name is already in use

Mein Plugin ist wie folgt aufgebaut

RothProductRepo
-composer.json
-src
--Resources
---config
----services.xml
--Twig
---RothProductRepository.php
--RothProductRepo.php

composer.json

{
  "name": "roth/product-repo",
  "description": "stellt ein durchsuchbares Produkt Repository bereit",
  "version": "1.0.0",
  "type": "shopware-platform-plugin",
  "license": "MIT",
  "authors": [
        {
            "name": "Konstantin Roth"
        }
    ],
  "autoload": {
    "psr-4": {
      "Roth\\ProductRepo\\": "src/"
    }
  },
  "extra": {
    "shopware-plugin-class": "Roth\\ProductRepo\\RothProductRepository",
    "label": {
      "de-DE": "durchsuchbares Produkt Repository",
      "en-GB": "searchable Product Repository"
    }
  }
}

RothProductRepo.php

<?php declare(strict_types=1);

namespace Roth\ProductRepo;

use Shopware\Core\Framework\Plugin;

class RothProductRepo extends Plugin
{
}

RothProductRepository.php

<?php declare(strict_types=1);

namespace Roth\ProductRepo\Twig;

use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\SalesChannelContext;

class RothProductRepo
{

  /**
   * @var SalesChannelRepositoryInterface
   */
  private $salesChannelProductRepository;

  /*
  *   Construct
  */
  public function __construct(SalesChannelRepositoryInterface $salesChannelProductRepository)
  {
    $this->salesChannelProductRepository = $salesChannelProductRepository;
  }

  public function searchProductByID($productID, $context)
  {
    return
      $this->salesChannelProductRepository->search(new Criteria([$productID]), $context)->first();
  }
}

services.xml

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
	<!--        SERVICES-->
		<service id="Roth\ProductRepo\Twig\RothProductRepository" public="true">
            <tag name="twig.extension"/> <!--Required-->
			<argument type="service" id="sales_channel.product.repository"/>
        </service>
    </services>
</container>

Müssen Filename und Classname nicht immer übereinstimmen?

Habs gerade probiert, es könnte stimmen, allerdings bekomme ich immer noch denselben Fehler…

Es steht doch in der Fehlermeldung - RothProductRepo wird als Klassenname mehrfach verwendet.
In der RothProductRepo.php und in der RothProductRepository.php. Die zweite Klasse müsste RothProductRepository heißen. Mit dem Klassennamen lädst du sie ja auch in der XML-Datei.

Außerdem sollte die shopware-plugin-class die Plugin-Instanz initialisieren: Roth\\ProductRepo\\RothProductRepo

Ich hab es hinbekommen.
So schaut das ganz Final aus, für alle die auch ein Produkt Repositiory bereitstellen wollen, das mit der Produkt ID durchsucht werden kann.

Übersicht

RothProductRepo
-composer.json
-src
--Resources
---config
----services.xml
--Twig
---RothProductRepository.php
--RothProductRepo.php

composer.json

{
  "name": "roth/product-repo",
  "description": "stellt ein durchsuchbares Produkt Repository bereit",
  "version": "1.0.0",
  "type": "shopware-platform-plugin",
  "license": "MIT",
  "authors": [
        {
            "name": "Konstantin Roth"
        }
    ],
  "autoload": {
    "psr-4": {
      "Roth\\ProductRepo\\": "src/"
    }
  },
  "extra": {
    "shopware-plugin-class": "Roth\\ProductRepo\\RothProductRepo",
    "label": {
      "de-DE": "durchsuchbares Produkt Repository",
      "en-GB": "searchable Product Repository"
    }
  }
}

RothProductRepo.php

<?php declare(strict_types=1);

namespace Roth\ProductRepo;

use Shopware\Core\Framework\Plugin;

class RothProductRepo extends Plugin
{
}

RothProductRepository.php

<?php declare(strict_types=1);

namespace Roth\ProductRepo\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\SalesChannelContext;

class RothProductRepository extends AbstractExtension
{

  /**
   * @var SalesChannelRepositoryInterface
   */
  private $salesChannelProductRepository;

  /*
  *   Construct
  */
  public function __construct(SalesChannelRepositoryInterface $salesChannelProductRepository)
  {
    $this->salesChannelProductRepository = $salesChannelProductRepository;
  }

  public function getFunctions()
  {
    return [
      new TwigFunction('getProductByID', [$this, 'searchProductByID']),
    ];
  }

  public function searchProductByID($productID, $context)
  {
    return
      $this->salesChannelProductRepository->search(new Criteria([$productID]), $context)->first();
  }
}

services.xml

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
	<!--        SERVICES-->
		<service id="Roth\ProductRepo\Twig\RothProductRepository" public="true">
            <tag name="twig.extension"/> <!--Required-->
			<argument type="service" id="sales_channel.product.repository"/>
        </service>
    </services>
</container>