Заменить / украсить `translation.reader`

Я заполнил ошибку, но похоже, что я отключился: p

Я просто хочу заменить сервис Symfony\Component\Translation\Reader\TranslationReader (translation.reader) своим классом. На самом деле я хочу знать, как заменить любую услугу SF4, если я хочу

translation.reader::addLoader() обычно вызывается фреймворком, но если я украшаю его собственным классом, addLoader не вызывается.

Можете ли вы сказать мне, как я могу просто отказаться от замены моей собственной службы?

https://github.com/symfony/symfony/issues/28843

Затронутые версии Symfony: 4.1.6

Описание
Невозможно украсить translation.reader (я хочу изменить процесс загрузки файла i18n по умолчанию)

Как воспроизвести

копировать / адаптировать Symfony\Component\Translation\Reader\TranslationReader к App\Translation\Reader\TranslationReader

Следуйте https://symfony.com/doc/current/service_container/service_decoration.html

Изменить services.yaml

Symfony\Component\Translation\Reader\TranslationReader: ~

App\Translation\Reader\TranslationReader:
    decorates: Symfony\Component\Translation\Reader\TranslationReader

#translation.reader: '@App\Translation\Reader\TranslationReader'

Без псевдонима: новая услуга игнорируется С псевдонимом: read() является триггером, но не addLoader()

Вот сгенерированный файл инъекции getTranslationReaderService.php:

<?php

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the private 'App\Translation\Reader\TranslationReader' shared autowired service.

include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReaderInterface.php';
include_once $this->targetDirs[3].'/src/Translation/Reader/TranslationReader.php';

return $this->privates['App\Translation\Reader\TranslationReader'] = new \App\Translation\Reader\TranslationReader();

По умолчанию это выглядит так:

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the private 'translation.reader' shared service.

include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReaderInterface.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/LoaderInterface.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/ArrayLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/FileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/PhpFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/YamlFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/XliffFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/PoFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/MoFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/QtFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/CsvFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IcuResFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IcuDatFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IniFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/JsonFileLoader.php';

$this->privates['translation.reader'] = $instance = new \Symfony\Component\Translation\Reader\TranslationReader();

$a = ($this->privates['translation.loader.yml'] ?? $this->privates['translation.loader.yml'] = new \Symfony\Component\Translation\Loader\YamlFileLoader());
$b = ($this->privates['translation.loader.xliff'] ?? $this->privates['translation.loader.xliff'] = new \Symfony\Component\Translation\Loader\XliffFileLoader());

$instance->addLoader('php', ($this->privates['translation.loader.php'] ?? $this->privates['translation.loader.php'] = new \Symfony\Component\Translation\Loader\PhpFileLoader()));
$instance->addLoader('yaml', $a);
$instance->addLoader('yml', $a);
$instance->addLoader('xlf', $b);
$instance->addLoader('xliff', $b);
$instance->addLoader('po', ($this->privates['translation.loader.po'] ?? $this->privates['translation.loader.po'] = new \Symfony\Component\Translation\Loader\PoFileLoader()));
$instance->addLoader('mo', ($this->privates['translation.loader.mo'] ?? $this->privates['translation.loader.mo'] = new \Symfony\Component\Translation\Loader\MoFileLoader()));
$instance->addLoader('ts', ($this->privates['translation.loader.qt'] ?? $this->privates['translation.loader.qt'] = new \Symfony\Component\Translation\Loader\QtFileLoader()));
$instance->addLoader('csv', ($this->privates['translation.loader.csv'] ?? $this->privates['translation.loader.csv'] = new \Symfony\Component\Translation\Loader\CsvFileLoader()));
$instance->addLoader('res', ($this->privates['translation.loader.res'] ?? $this->privates['translation.loader.res'] = new \Symfony\Component\Translation\Loader\IcuResFileLoader()));
$instance->addLoader('dat', ($this->privates['translation.loader.dat'] ?? $this->privates['translation.loader.dat'] = new \Symfony\Component\Translation\Loader\IcuDatFileLoader()));
$instance->addLoader('ini', ($this->privates['translation.loader.ini'] ?? $this->privates['translation.loader.ini'] = new \Symfony\Component\Translation\Loader\IniFileLoader()));
$instance->addLoader('json', ($this->privates['translation.loader.json'] ?? $this->privates['translation.loader.json'] = new \Symfony\Component\Translation\Loader\JsonFileLoader()));

return $instance;

Вы можете видеть, что загрузчики не вводятся, когда я занимаюсь декорированием ...

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
0
302
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не уверен, что именно в этом причина вашей проблемы, но вот несколько замечаний. Надеюсь, это поможет вам найти решение, хотя на самом деле я не получил полного ответа на ваш вопрос.

1) Некоторые службы перевода в Symfony называются Только во время фазы разогрева кеша. Всякий раз, когда вы меняете свою конфигурацию или делаете bin/console cache:clear, вы увидите, что эти классы запущены, и они генерируют переводы в вашей папке var/cache/<env>/translations/.

2) Вы можете попробовать убедиться, что в вашем кеше класс, загруженный var/cache/<env>/Container<...>/getTranslation_ReaderService.php, принадлежит вам, а не по умолчанию, например:

$this->privates['translation.reader'] = 
    new \Symfony\Component\Translation\Reader\TranslationReader();

3) Я также столкнулся с аналогичной проблемой в среде dev, где я пытался заменить Symfony\Component\Translation\Translator моей собственной службой, и мне не удалось сначала вызвать свои методы. Частично объяснение состояло в том, что когда включен Symfony Profiler, Symfony делает что-то вроде этого (в src<env>DebugProjectContainer.php>):

$this->services['translator'] = new \Symfony\Component\Translation\DataCollectorTranslator(
    ($this->privates['translator.default'] ?? $this->getTranslator_DefaultService())
);

а сам DataCollectorTranslator является оболочкой для любого переводчика, который он получает в качестве аргумента конструктора.

Я знаю, что это не идеальный ответ, но, надеюсь, это поможет вам найти решение.

это хороший указатель, теперь я могу "видеть" сгенерированные файлы для инъекций, но он (пока) не работает

quazardous 17.10.2018 15:03
Ответ принят как подходящий

Мне удалось заставить его работать ... но, пожалуйста, не стесняйтесь комментировать

Мне пришлось создать TranslatorPass, чтобы добавить загрузчики в файл внедрения службы украшения.

<?php

namespace App\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use App\Translation\Reader\TranslationReader;

class TranslatorPass implements CompilerPassInterface
{
    private $readerServiceId;
    private $loaderTag;

    public function __construct(string $readerServiceId = TranslationReader::class, string $loaderTag = 'translation.loader')
    {
        $this->readerServiceId = $readerServiceId;
        $this->loaderTag = $loaderTag;
    }

    public function process(ContainerBuilder $container)
    {
        $loaders = array();
        $loaderRefs = array();
        foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
            $loaderRefs[$id] = new Reference($id);
            $loaders[$id][] = $attributes[0]['alias'];
            if (isset($attributes[0]['legacy-alias'])) {
                $loaders[$id][] = $attributes[0]['legacy-alias'];
            }
        }

        if ($container->hasDefinition($this->readerServiceId)) {
            $definition = $container->getDefinition($this->readerServiceId);
            foreach ($loaders as $id => $formats) {
                foreach ($formats as $format) {
                    $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
                }
            }
        }
    }
}

Вставил в Kernel.php

protected function build(ContainerBuilder $container)
{
    parent::build($container);
    $container->addCompilerPass(new TranslatorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 1000);
}

тогда

bin/console cache:clear

и вуаля !

Я много лет играл с Silex и не привык к «структурированной» инъекции ... Не уверен, что мне нравится изощренность SF :)

quazardous 17.10.2018 21:22

Другие вопросы по теме