Using Services in Rules

Hello

I have created a custom rule. It generally seems to work (admin part is working, I get the right config from admin, the rule is constructed and match is called). Nice!

For the evaluation of my rule (the implementation of match) I need to use some services (services from my own plugin, the config of my plugin, some repositories, …). How can I get those services?

  • Injection in __construct with „services.xml“ does not work! Yes, I receive the services as arguments to __ construct but the private $someService variables are overridden somewhere after having been set in the constructor. Maybe this happens somewhere in the core where the values from the config form in the admin are set. All these variables are null when match is executed even though I set them to a non-null value in the constructor.
  • $this-\>container is not defined.

The following snippet illustrates what I am trying to do:

class DemoRule extends Rule {

	/**
	 * @var int
	 */
	protected $myInt;
	
	private $someService;
	
	public function __construct(SomeService $someService) {
		$this->someService = $someService;
		// Here `$this->someService` is defined.
		// `$someService` really is an instance of
		// `SomeService` and not `null` (as requested in
		// "services.xml").
	}
	
	public function getName():string {
		return 'some_name';
	}
	
	public function match(RuleScope $scope):bool {
		// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		// `$this->someService` is now `null`.
		// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		
		// Did something weird happen when `$this->myInt` was
		// magically set?
		
		return false;
	}
	
	public function getConstraints():array {
		return array(
			'myInt' => array(new Type('int'))
		);
	}
}

Maybe there is some last-resort way of obtaining a service instance (something like Shopware()-\>Container())?

My questions: How can we use services in a custom rule (e.g. how do we get our plugin config, repositories and custom services)?

You don’t have access to the container nor the services. This part of the rule builder design. You can only use the already provided variables to make a decision (false/true).

@Almare schrieb:

You don’t have access to the container nor the services. This part of the rule builder design. You can only use the already provided variables to make a decision (false/true).

That is exactly the problem!

E.g. we can’t access the plugin configuration, we can’t access information from the DB because we can’t inject/fetch a repository (e.g. own associations will not have been added to the customer/address, whether some historic data is present is a pure question of luck), we have to repeat all the calculation code because we can’t access our own services, we can’t even write anything to the log, …

Only the simplest of rules could be implemented like that (it seems the Shopware authors thought of the rules they were going to implement before they decided which data to make available; of course it works then…). And all of it seems to be due to some relatively minor implementation issues in the core. I have create an issue for this: Shopware Issuetracker. It’s in the „Backlog“, maybe some day we can write serious risk management rules without resorting to dirty tricks.