Это вопрос о Symfony 4 autowiring , использующей только «массив» в качестве аргумента типа аргумента конструктора.Я привожу конкретный случай, но это может быть полезно для других, поскольку такая ситуация возникает в нескольких пакетах Symfony.
Эта команда Symfony запрашивает пароль и кодирует его:
php bin/console security:encode-password
Код этой команды находится в vendor / symfony / security-bundle / Command / UserPasswordEncoderCommand.php
В Symfony 4.2.3 это конструктор для UserPasswordEncoderCommand:
class UserPasswordEncoderCommand extends Command
{
protected static $defaultName = 'security:encode-password';
private $encoderFactory;
private $userClasses;
public function __construct(EncoderFactoryInterface $encoderFactory, array $userClasses = [])
{
$this->encoderFactory = $encoderFactory;
$this->userClasses = $userClasses;
parent::__construct();
}
Symfony использует внедрение зависимостейвызывать конструктор, передавая автоматически определенные аргументы.Вышеупомянутый первый аргумент конструктора $ encoderFactory автоматически подключается с использованием подсказки типа EncoderFactoryInterface.Мой вопрос: Как автоматически подключается второй аргумент $ userClasses? Как Symfony знает, что должен содержать массив?Отладочные операторы печати показывают, что массив содержит одно значение «App \ Entity \ User».
Вот мой config / packages / security.yaml
security:
encoders:
App\Entity\User:
algorithm: argon2i
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
guard:
authenticators:
- App\Security\LoginFormAuthenticator
# activate different ways to authenticate
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
logout:
path: app_logout
# Where to redirect after logout
target: app_login
Я думаю, что следующие три файлаважно ответить на этот вопрос.
vendor / symfony / security-bundle / Resources / config / console.xml содержит:
<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>
<defaults public="false" />
<service id="security.command.user_password_encoder" class="Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand">
<argument type="service" id="security.encoder_factory"/>
<argument type="collection" /> <!-- encoders' user classes -->
<tag name="console.command" command="security:encode-password" />
</service>
</services>
</container>
Часть vendor / symfony / security-bundle / Resources / config / security.xml содержит:
<service id="security.encoder_factory" alias="security.encoder_factory.generic" />
<service id="Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface" alias="security.encoder_factory" />
<service id="security.user_password_encoder.generic" class="Symfony\Component\Security\Core\Encoder\UserPasswordEncoder">
<argument type="service" id="security.encoder_factory"></argument>
</service>
<service id="security.password_encoder" alias="security.user_password_encoder.generic" public="true" />
<service id="Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface" alias="security.password_encoder" />
Часть поставщика / symfony / security-bundle / DependencyInjection / SecurityExtension.php содержит:
function load(array $configs, ContainerBuilder $container)
...
if (class_exists(Application::class)) {
$loader->load('console.xml');
$container->getDefinition('security.command.user_password_encoder')->replaceArgument(1, array_keys($config['encoders']));
}
Я задаю этот вопрос, потому что мне хотелось быиспользовать UserPasswordEncoderCommand.php в качестве отправной точки для команды для создания пользователя с правами администратора в моей базе данных.Это даст первому администратору разрешение на вход в систему с помощью веб-браузера для создания других пользователей.
Я попытался скопировать vendor / symfony / security-bundle / Command / UserPasswordEncoderCommand.php в src / Command / AddUserCommand.php иизменив эти строки:
< namespace Symfony\Bundle\SecurityBundle\Command;
---
> namespace App\Command;
< class UserPasswordEncoderCommand extends Command
---
> class AddUserCommand extends Command
< protected static $defaultName = 'security:encode-password';
---
> protected static $defaultName = 'app:add-user';
Когда я запустил эту команду: php bin/console app:add-user
появилась эта ошибка:
There are no configured encoders for the "security" extension.
Это произошло потому, что конструктор __construct (EncoderFactoryInterface $ encoderFactory, массив $ userClasses =[]) был вызван только с одним аргументом, поэтому вторым аргументом по умолчанию является пустой массив.
Кажется, эти файлы также необходимо скопировать из vendor / symfony / security-bundle куда-нибудь в каталог src /
DependencyInjection/SecurityExtension.php
Resources/config/console.xml
и быть как-то изменено. Какие другие файлы необходимо скопировать в src /? Документация Symfony под https://symfony.com превосходна, но я не могу найти, где описана эта ситуация.
Обратите внимание, что этокоманда работает:
php bin/console app:add-user mypassword "App\Entity\User"
но я не хочу, чтобы пользователь вводил это.И это может измениться, если меняется security.yaml.