通过用户名或电子邮件进行身份验证失败并出现 DBAL 异常:未定义的偏移量:1
Authenticate by username or email fails with DBAL Exception: Undefined offset: 1
从通过电子邮件成功验证(在 4.2.4 中)开始,尝试按照 User Provider docs 添加用户名验证失败
DBAL Exception:... Undefined offset: 1
奇怪的是,如果我 运行 SQL 语句如调试分析器 View runnable query
所示,查询 运行s 正确并且 returns a非空结果。所以至少存储库可以 return 一个用户名。
我尝试使用 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
,所以当在下一次循环中遇到第127行的count($params[$needle])
语句时(并且$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 {▶}
将您的存储库更新为:
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(...)
的参数不应该是一个数组,而是一个标量。
也许我可以通过创造像爱丽丝一样的兔子洞来做生意。
从通过电子邮件成功验证(在 4.2.4 中)开始,尝试按照 User Provider docs 添加用户名验证失败
DBAL Exception:... Undefined offset: 1
奇怪的是,如果我 运行 SQL 语句如调试分析器 View runnable query
所示,查询 运行s 正确并且 returns a非空结果。所以至少存储库可以 return 一个用户名。
我尝试使用 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
,所以当在下一次循环中遇到第127行的count($params[$needle])
语句时(并且$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 {▶}
将您的存储库更新为:
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(...)
的参数不应该是一个数组,而是一个标量。
也许我可以通过创造像爱丽丝一样的兔子洞来做生意。