SW 5.5.0 Beta - You have requested a non-existent service "shop"

Ich habe ein Plugin welches auf der neuen Shopware Version 5.5 nach dem Installieren einen Fehler verursacht. Es kann nicht mehr kompiliert werden.

Die Fehlermeldung lautet: You have requested a non-existent service „shop“

Der Fehler erscheint nicht, wenn im __construct die Abfrage nach der Shop-ID für den Scobe entfernt wird:

 

Aus diesem Code-Schnipsel

$shop = Shopware()->Shop();
$this->config = $configReader->getByPluginName($pluginName, $shop);

wird dann dies hier ohne Abfrage des Subshops:

$this->config = $configReader->getByPluginName($pluginName);

CODE:

Subscriber/Subscriber.php

pluginPath = $pluginPath;

		$shop = Shopware()->Shop();
		$this->config = $configReader->getByPluginName($pluginName, $shop);
	}

	public static function getSubscribedEvents()
	{
		return [
			'Theme_Inheritance_Template_Directories_Collected' => ['onTemplateDirectoriesCollect', -10],
			'Enlight_Controller_Action_PostDispatchSecure_Widgets_Emotion' => 'onFrontendPostDispatch',
			'Theme_Compiler_Collect_Plugin_Less' => 'onCollectLessFiles',
			'Theme_Compiler_Collect_Plugin_Javascript' => 'onCollectJsFiles'
		];
	}

	public function onTemplateDirectoriesCollect(EventArgs $args) {
		$dirs = $args->getReturn();

		$dirs[] = $this->pluginPath . '/Resources/views/';

		$args->setReturn( $dirs );
	}

	/**
	 * Provide the needed javascript files
	 *
	 * @return ArrayCollection
	 */
	public function onCollectJsFiles()
	{
		$jsFiles = [
			$this->pluginPath . '/Resources/views/frontend/_public/src/js/jquery.pluginname.js'
		];

		return new ArrayCollection($jsFiles);
	}

	/**
	 * @return ArrayCollection
	 */
	public function onCollectLessFiles()
	{

		$less = new LessDefinition(
			[
				'less-variable' => $this->config['lessVariable'],
			],
			[
				$this->pluginPath . '/Resources/views/frontend/_public/src/less/all.less',
			],
			$this->pluginPath
		);

		return new ArrayCollection([$less]);
	}


	public function onFrontendPostDispatch(EventArgs $args)
	{
		/** @var \Enlight_Controller_Action $controller */
		$controller = $args->get('subject');
		$view = $controller->View();

		$config = array(
			'configParameter' => $this->config['configParameter'],
		);

		$view->assign('prefixPluginName', $config)

	}
}

Ressources/services.xml

        %prefix_plugin_name.plugin_name%
        %prefix_plugin_name.plugin_dir%

 

Fehlermeldung beim Kompilieren

Während der Bearbeitung von Shop "Demoshop" ist ein Fehler aufgetreten: You have requested a non-existent service "shop". Did you mean one of these: "customer_search.dbal.condition.ordered_in_shop_handler", "customer_search.dbal.condition.registered_in_shop_handler", "shop_page_menu", [...] "shopware_storefront.vote_hydrator_dbal", "shopware_storefront.vote_service", "shop"?

 

Hallo,

vermutlich wird der Subscriber in einem Kontext aufgerufen, in dem es keine Shop Instanz gibt. Sprich Backend oder CLI.
Das Problem ist, dass du direkt im Konstruktor versuchst auf das Shop Object zuzugreifen. Das funktioniert so nicht. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

1 „Gefällt mir“

Hallo [@Michael Telgmann](http://forum.shopware.com/profile/17553/Michael Telgmann „Michael Telgmann“)‍

danke für den Hinweis. Ich rufe den __construct() ja in der Subscriber/Subscriber.php auf. Wie kann ich das ändern? Sollte ich das nicht in der Subscriber/Subscriber.php machen?

Ich würde das Holen der Plugin Konfig in die Callback Methode des einen Events verschieben, in der es nur gebraucht wird. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

1 „Gefällt mir“

Du meinst also, ich soll 

$shop = Shopware()->Shop();
$this->config = $configReader->getByPluginName($pluginName, $shop);

beispielsweise in die 

 onTemplateDirectoriesCollect oder onFrontendPostDispatch

verschieben?

Genau. In „onFrontendPostDispatch“ wird das funktionieren. In der „onCollectLessFiles“ bin ich mir gerade nicht sicher, kannst du aber mal versuchen. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

1 „Gefällt mir“

Okay, ich bin leider in den Programmierungen nicht so fit… Frontend mit SMARTY, LESS und Co ist eher mein Gebiet…

Ich habe den ganzen Kram ja jetzt im __construct drin… und leider keine Ahnung, wie ich das nun in die onFrontendPostDispatch bekommen soll… 

strg+x und dann strg+v und testen ob es geht wäre mal ein Anfang

1 „Gefällt mir“

@BestShopPossible‍

ich verstehs glaube nicht ganz… 

$shop = Shopware()->Shop();
$this->config = $configReader->getByPluginName($pluginName, $shop);

kann ich nicht einfach verschieben… ich referenziere da ja auf Variablen usw. die im __construct geholt werden. Den ganzen __construct kann ich doch auch nicht einfach verschieben… ich peils nicht…  Undecided

    /**
	 * @var
	 */
	private $pluginPath;

	/**
	 * @var
	 */
	private $config;

	public function __construct($pluginName, $pluginPath, CachedConfigReader $configReader)
	{
		$this->pluginPath = $pluginPath;

		$shop = Shopware()->Shop();
		$this->config = $configReader->getByPluginName($pluginName, $shop);
	}

 

Dein subscriber (und damit der constructor) wird -immer- geladen - egal ob du dich im frontend, backend oder cronjob Kontext befindest. Da es im backend keinen Shop gibt, wird dieser Fehler geworfen. Also solltest du das Auslesen der Konfiguration erst in der listener Methode machen.

Viele Grüße
https://www.digitvision.de

1 „Gefällt mir“

Okay. Also ist das Beispiel hier: Plugin quick Startup Guide

nicht direkt um das Auslesen von Subshop-Konfigurationen erweiterbar und müsste entsprechend komplett umgebaut werden?! Weil nach diesem Vorbild habe ich es gemacht…

Der Unterschied ist, dass du die Konfiguration mit dem aktuellen Shop als Kontext auslesen möchtest.
Bitte vergleich doch die beiden constructors mal genauer.

Viele Grüße
https://www.digitvision.de

1 „Gefällt mir“

Ja genau, ich will ja, dass ein möglicher Subshop eine andere Konfiguration haben kann und habe diese Vorlage entsprechend um den weiteren Paramter in getByPluginName() erweitert und versuche dann Shopware()->Shop(); auszulesen, was aber wohl nicht passieren darf.

Das meinst Du doch, oder?

Wie müsste denn das Beispiel aus Plugin quick Startup Guide aussehen, damit man dort auch subshop-spezifisch die Konfiguration auslesen kann?

 

Und warum die Config im Constructor auslesen und als Var zwischenspeichern?
Ich würde einfach bei Bedarf zur Laufzeit aus dem Event heraus die Config auslesen - und nicht IMMER im Constructor - unnötiger Overhead.

1 „Gefällt mir“

 

  • Die services.xml habe ich nun um

und

%prefix_plugin_name.plugin_name%

gekürzt.

;


    
        
        %prefix_plugin_name.plugin_dir%
  • Den Constructor habe ich nun radikal gekürzt…

    /**

    • @var
      */
      private $pluginPath;

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

 

 **onCollectLessFiles (**Theme_Compiler_Collect_Plugin_Less) habe ich um $this->config = Shopware()->Container()->get(‚shopware.plugin.cached_config_reader‘)->getByPluginName(‚pluginName‘); erweitert.

/**
 * @return ArrayCollection
 */
public function onCollectLessFiles()
{

	$this->config = Shopware()->Container()->get('shopware.plugin.cached_config_reader')->getByPluginName('pluginName');

	$less = new LessDefinition(
		[
			'less-variable' => $this->config['lessVariable'],
		],
		[
			$this->pluginPath . '/Resources/views/frontend/_public/src/less/all.less',
		],
		$this->pluginPath
	);

	return new ArrayCollection([$less]);
}

 

onFrontendPostDispatch (Enlight_Controller_Action_PostDispatchSecure_Widgets_Emotion) habe ich um $shop = Shopware()->Shop();
    $this->config = Shopware()->Container()->get(‚shopware.plugin.cached_config_reader‘)->getByPluginName(‚pluginName‘, $shop );
erweitert

public function onFrontendPostDispatch(EventArgs $args)
{
	/** @var \Enlight_Controller_Action $controller */
	$controller = $args->get('subject');
	$view = $controller->View();

	$shop = Shopware()->Shop();
	$this->config = Shopware()->Container()->get('shopware.plugin.cached_config_reader')->getByPluginName('pluginName', $shop );

	$config = array(
		'smartyVariable' => $this->config['configParameter'],
	);

	$view->assign('pluginName', $config);

}

 

 

FRAGEN: Benötige ich bei den LESS-Variablen keinen Shop-Kontext? Wenn ich hier Shopware()->Shop() abfrage erscheint wieder der Fehler…

@sonic schrieb:

Und warum die Config im Constructor auslesen und als Var zwischenspeichern?
Ich würde einfach bei Bedarf zur Laufzeit aus dem Event heraus die Config auslesen - und nicht IMMER im Constructor - unnötiger Overhead.

Also ist die Doku nicht „best-practice“? ( https://developers.shopware.com/developers-guide/plugin-quick-start/?&_ga=2.37836650.817698121.1527489250-1386687580.1527146725#subscriber-classes )

Im Beispiel wird aber die allgemeine Config gelesen, und eben nicht die aus einem Shop-Context.
Sobald etwas ausserhalb vom Shopcontext läuft - also z.B. Backend - gibt es eben auch keinen Shop-Context. Wo soll der denn herkommen???
“onCollectLessFiles()” (kenn ich grad nicht) dürfte ja wohl nur in Frage kommen, wenn ein Theme compiliert wird. Da dürfte es aber gar keinen Shop-Context geben, eher wird es wohl ein Argument geben, welches Verweise auf das zu kompilierende Theme und den dazu gehörigen Shop hat. Aber das ist bestimmt kein klassicher “Shopcontext” - weil es ja dort nicht in einem “Shop” abläuft.

Guck mal hier:
shopware/LessCollector.php at 5.4 · shopware/shopware · GitHub
Wenn ich jetzt auf die Schnelle richtig bin, bekommt “onCollectLessFiles” den Shop als Parameter übergeben.

1 „Gefällt mir“

Okay, also muss ich es da nicht explizit selbst übergeben ?!

 

Ich sehe es immer wieder in anderen Plugins, dass in der onCollectLessFiles der Shop mit Shopware()->Shop() übergeben wird. Das knallt auch bei anderen… das ist wohl neu in der 5.5

Du kannst dir aus dem EventParameter das Shop Objekt holen und dieses dann für das Holen der Konfig nutzen. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

1 „Gefällt mir“

Ich weiß nicht, ob Du meinen Nachtrag schon gelesen hattest :wink:
Also:
Wenn ich richtig liege, wird onCollectLessFiles() zwei "Array"s übergeben - die müsstest Du also dann in der Function ergänzen.
Das erste „Array“ - genauer ArrayCollection - wäre für die Rückgabe aus dem Plugin und im zweiten Array müsste dann ein index „shop“ sein, der eben auf den Shop verweist.
Denn könntest Du dann testweise an den Config-Reader übergeben.

1 „Gefällt mir“