Начиная с успешной проверки подлинности по электронной почте (в версии 4.2.4), попытка следовать Документы поставщика пользователей для добавления проверки подлинности по имени пользователя завершается с ошибкой.
DBAL Exception:... Undefined offset: 1
Любопытно, что если я запускаю оператор SQL, как показано в профилировщике отладки, View runnable query, запрос выполняется правильно и возвращает ненулевой результат. Так что, по крайней мере, репозиторий может вернуть имя пользователя.
Я попытался переписать оператор построителя запросов, используя entityManager; предоставление оператора setParameters() с двумя параметрами; все безрезультатно.
Редактировать № 2:
Тыкая в код Doctrine, указанный в трассировке (см. ниже), возникает исключение в строке
[$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types);
$query и $params (как показано с dd(...)) имеют смысл для меня. Однако переменная $types непрозрачна: это массив [0 => 102, 1 => 102]. Исключение возникает с утверждением SQLParserUtils....
конец Редактировать #2
Редактировать № 3:
Вот что происходит в Doctrine, но я понятия не имею о назначении кода. В Doctrine\DBAL\SQLParserUtils строки 129–133 содержатся в цикле foreach (), который запускается один раз для каждого элемента в $paramsPos массиве [0 => 496, 1 => 513], где значениями являются расположение заменяемых параметров в операторе SQL. Массив $params изначально содержит
array:2 [▼
0 => array:1 [▼
"username" => "gbrooks"
]
1 => array:1 [▼
"username" => "gbrooks"
]
]
После выполнения кода в 125 - 133 (как показано ниже)
$needle += $paramOffset;
$needlePos += $queryOffset;
$count = count($params[$needle]);
$params = array_merge(
array_slice($params, 0, $needle),
$params[$needle],
array_slice($params, $needle + 1)
);
массив $params содержит
array:2 [▼
"username" => "gbrooks"
0 => array:1 [▼
"username" => "gbrooks"
]
]
Обратите внимание, что ключа 1 больше не существует, поэтому, когда оператор count($params[$needle]) в строке 127 встречается при следующем проходе цикла (и $needle теперь равен 1, выдается DBAL Exception Undefined offset: 1.
конец Редактировать #3
Пользовательский репозиторий:
namespace App\Repository;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository implements UserLoaderInterface
{
public function loadUserByUsername($usernameOrEmail)
{
$user = $this->createQueryBuilder('u')
->where('u.username = :query OR u.email = :query')
->setParameter('query', $usernameOrEmail)
->getQuery()
->getOneOrNullResult();
}
}
LoginFormAuthenticator содержит:
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $this->entityManager->getRepository(User::class)->loadUserByUsername(['username' => $credentials['username']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
След:
G:\Documents\workspace\mana\vendor\doctrine\dbal\lib\Doctrine\DBAL\DBALException.php:172 {▶}
G:\Documents\workspace\mana\vendor\doctrine\dbal\lib\Doctrine\DBAL\DBALException.php:145 {▶}
G:\Documents\workspace\mana\vendor\doctrine\dbal\lib\Doctrine\DBAL\Connection.php:911 {▶}
G:\Documents\workspace\mana\vendor\doctrine\orm\lib\Doctrine\ORM\Query\Exec\SingleSelectExecutor.php:50 {▶}
G:\Documents\workspace\mana\vendor\doctrine\orm\lib\Doctrine\ORM\Query.php:334 {▶}
G:\Documents\workspace\mana\vendor\doctrine\orm\lib\Doctrine\ORM\AbstractQuery.php:967 {▶}
G:\Documents\workspace\mana\vendor\doctrine\orm\lib\Doctrine\ORM\AbstractQuery.php:922 {▶}
G:\Documents\workspace\mana\vendor\doctrine\orm\lib\Doctrine\ORM\AbstractQuery.php:765 {▶}
G:\Documents\workspace\mana\src\Repository\UserRepository.php:24 {▶}
G:\Documents\workspace\mana\src\Security\LoginFormAuthenticator.php:74 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-guard\Provider\GuardAuthenticationProvider.php:102 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-guard\Provider\GuardAuthenticationProvider.php:96 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-core\Authentication\AuthenticationProviderManager.php:76 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-guard\Firewall\GuardAuthenticationListener.php:130 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-guard\Firewall\GuardAuthenticationListener.php:82 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-bundle\Debug\WrappedListener.php:46 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-bundle\Debug\TraceableFirewallListener.php:35 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-http\Firewall.php:90 {▶}
G:\Documents\workspace\mana\vendor\symfony\security-bundle\EventListener\FirewallListener.php:48 {▶}
G:\Documents\workspace\mana\vendor\symfony\event-dispatcher\Debug\WrappedListener.php:115 {▶}
G:\Documents\workspace\mana\vendor\symfony\event-dispatcher\EventDispatcher.php:212 {▶}
G:\Documents\workspace\mana\vendor\symfony\event-dispatcher\EventDispatcher.php:44 {▶}
G:\Documents\workspace\mana\vendor\symfony\event-dispatcher\Debug\TraceableEventDispatcher.php:145 {▶}
G:\Documents\workspace\mana\vendor\symfony\http-kernel\HttpKernel.php:126 {▶}
G:\Documents\workspace\mana\vendor\symfony\http-kernel\HttpKernel.php:67 {▶}
G:\Documents\workspace\mana\vendor\symfony\http-kernel\Kernel.php:198 {▶}
G:\Documents\workspace\mana/public\index.php:25 {▶}
Для улучшения вашего кода. В Symfony 4 рекомендуется внедрять то, что вам нужно, в репозиторий, а не в entityManager. Таким образом, вы можете ввести UserRepository с помощью конструктора и выполнить $this->userRepository->loadUserByUsername
Трассировка прилагается. Я недостаточно умен, чтобы разобраться в коде Doctrine. Спасибо за подсказку dd(). Кстати, я всегда стараюсь сначала следовать документам, а потом приводить в порядок.
Какую версию доктрины вы используете?
Предполагая, что вас интересует доктрина/dbal: 2.9.2
Я добавил правку №3, в которой подробно описывается код Doctrine\DBAL, вызывающий исключение. Как обойти этот код, для меня остается загадкой.






Обновите свой репозиторий до этого:
namespace App\Repository;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository implements UserLoaderInterface
{
public function loadUserByUsername($usernameOrEmail)
{
return $this->createQueryBuilder('u')
->where('u.username = :query')
->orWhere('u.email = :query')
->setParameter('query', $usernameOrEmail)
->getQuery()
->getOneOrNullResult();
}
}
Неудивительно, что это не имеет значения.
Вся проблема заключалась в том, что аргумент this->entityManager->getRepository(User::class)->loadUserByUsername(...) должен быть НЕ массивом, а скаляром.
Возможно, я смогу заработать на создании кроличьих нор в стиле Алисы, чтобы в них можно было попасть.
Вы действительно должны добавить полную трассировку ошибки, которую вы получаете, а не только ее обрезанную версию (поскольку она укажет, какая строка/файл вызывает ее). Также для информации есть ярлык
dump('test');die;в SF4:dd('test');;)