通过用户名或电子邮件进行身份验证失败,并显示DBAL异常:未定义的偏移量:1

时间:2019-03-13 17:30:39

标签: php symfony doctrine-orm symfony4

从通过电子邮件成功进行身份验证开始(在4.2.4中),尝试遵循User Provider docs通过用户名添加身份验证失败

  

DBAL异常:...未定义偏移量:1

奇怪的是,如果我运行如调试概要分析器View runnable query中所示的SQL语句,查询将正确运行并返回非空结果。因此,至少存储库可以返回用户名。

我尝试使用entityManager重写查询生成器语句;提供带有两个参数的setParameters()语句;全部无济于事。

编辑#2:

拨入跟踪中标识的主义代码(见下文),该行处发生异常

[$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types);

$query$params(如dd(...)所示)对我来说很有意义。 $types变量是不透明的:它是一个数组[0 => 102, 1 => 102]。语句SQLParserUtils...例外。

结束编辑#2

编辑#3:

这是《教义》中发生的事情,但是我不知道代码的意图。在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,{ {1}}被抛出。

结束编辑#3

UserRepository:

DBAL Exception Undefined offset: 1

LoginFormAuthenticator包含:

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();
    }
}

踪迹:

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;
}

2 个答案:

答案 0 :(得分:0)

将您的存储库更新为此:

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();
    }
}

答案 1 :(得分:0)

整个问题是this->entityManager->getRepository(User::class)->loadUserByUsername(...)的参数不应该是数组,而应该是标量。

也许我可以通过创建类似爱丽丝般的兔子洞来做生意。