0

How use service.yml file set public static properties of class?
Example of class

<?php

class TelegramLog
{
    protected static $logger;
    protected static $update_logger;

    public static $always_log_request_and_response = false;
    public static $remove_bot_token = true;

    public static function initialize(LoggerInterface $logger = null, LoggerInterface $update_logger = null): void
    {
        self::$logger        = $logger ?: new NullLogger();
        self::$update_logger = $update_logger ?: new NullLogger();
    }
}

Part of my services.yaml

Longman\TelegramBot\TelegramLog:
  calls:
    - initialize:
       $logger: '@logger'
       $update_logger: '@logger'

I tried to use properties keywords, but it works only for property of object.

I want to change default values $always_log_request_and_response and $remove_bot_token of properties in service.yml

Artem Chernov
  • 856
  • 2
  • 8
  • 26
  • So what exactly is the problem? I duplicated your code and it works fine when the service is injected. Do you expect the statics to be initialized without using a service? I can show you how to do that without using the container assuming you are using the Symfony framework. It is not something the container can do by itself. BTW, statics and Symfony really don't get along. Best to avoid statics without a good reason. – Cerad May 05 '23 at 15:53
  • I want to change $always_log_request_and_response property, I can't avoid using static property because this code from library. I can change static property in runtime, but I thought it can be done in service.yml file – Artem Chernov May 05 '23 at 16:08

1 Answers1

1

Okay so the problem is with using property injection on static variables. Something like:

   App\Service\TelegramLog:
        properties:
            always_log_request_and_response: true
        calls:
            - initialize:
               $logger: '@logger'
               $update_logger: '@logger'

Results in PHP complaining about Notice: Accessing static property App\Service\TelegramLog::$always_log_request_and_response as non static. Symfony property setter using the instance and not the static property itself. Somewhat inconsistently PHP is fine with calling initialize as non-static.

Since this is legacy code and cannot easily be refactored then it is probably best to initialize this sort of stuff outside of the container. You can do this in the Kernel::boot method:

class Kernel extends BaseKernel implements CompilerPassInterface
{
    use MicroKernelTrait;

    public function boot()
    {
        parent::boot();

        TelegramLog::$always_log_request_and_response = true;

        // Logger needs to be public for this to work
        $logger = $this->container->get(LoggerInterface::class);
        TelegramLog::initialize($logger,$logger);
    }
    public function process(ContainerBuilder $container)
    {
        $logger = $container->getAlias(LoggerInterface::class);
        $logger->setPublic(true);
    }
}

As mentioned above you should probably call initialize as well just to make sure the static properties are set even if the service is never used.

Cerad
  • 48,157
  • 8
  • 90
  • 92
  • Thank you for your response. I made a solution like your idea, but in specific controller, I think it may be more clear and flexible make decorator or wrapper insted of change Kernel class – Artem Chernov May 06 '23 at 11:34
  • @ArtemChernov It is your choice of course but the reason for having an App\Kernel class is to make these sorts of customizations. The Kernel is really nothing more than the bundle class for the application. – Cerad May 06 '23 at 12:06
  • And [here](https://stackoverflow.com/questions/75334485/symfony-configure-class-from-service-yaml-with-static-default-value/75421121#75421121) is a slight variation on the problem. In this case they wanted to be able to statically configure legacy code from a services file. It's a bit more involved but might be worth taking a look at. – Cerad May 06 '23 at 12:55