我正在尝试为我的应用程序实现自定义身份验证系统。
为此,我创建了一个名为Auth的类(库),该类扩展了我的UserRepository,因此我可以直接在auth类中使用该模型。
<?php
namespace App\Lib;
use App\Repository\UserRepository;
class Auth extends UserRepository {
在我位于Auth中的身份验证函数中,我调用findByCredentials函数,该函数应该从数据库返回一些用户数据。
$user = $this->findByCredentials($email, $password);
我在控制器内部调用它以使其运行
public function index(Request $request) {
$auth = new Auth();
$auth->authenticate(null, 'somefakemaik@example.com', '1234');
return $this->tpl();
}
这是我的UserRepository,它是自动生成的,到目前为止,我仅添加了一个功能。
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class UserRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, User::class);
}
public function findByCredentials($email, $password)
{
return $this->createQueryBuilder('user')
->andWhere('user.email = :email')
->andWhere('user.password = :password')
->setParameters([
'email' => $email,
'password' => $password
])
->getQuery()
->getResult();
}
但是我得到标题中提到的错误。
我使用cli / console生成了所有内容,并确保我的表存在于数据库中。我在Linux机器上使用MySQL v5.7。
我还配置了config / packages / doctrine.yaml
auth类的构造器
public function __construct($jwt = null, $email = null, $password = null) {
$this->jwt = $jwt;
$this->email = $email;
$this->password = $password;
}
答案 0 :(得分:1)
您显然正在消除依赖注入的优点。
从本质上讲,依赖注入是您不在类内部创建服务,而是在构造函数或函数调用中将其作为参数提供。 (在symfony框架中,通常不必在其他地方创建它,但是symfony将照顾为您提供它,除非您明确地想要调用函数/构造函数...这就是为什么通常不这样做的原因。 t。)
一个示例是控制器,其中Request $request
(类型提示)由框架提供。从技术上讲,只要框架(更具体地说是容器)知道该类以及如何生成该类/实例,您几乎可以在其中找到任何类型提示类。容器会为您生成依赖项,并连接到自动装配或自动配置,这非常方便。 (有关symfony的文档:https://symfony.com/doc/current/service_container.html)
在您的特定示例中:我建议不要扩展UserRepository
,并提出两个更好的选择:
UserRepository
如果您想扩展UserRepository,并且该UserRepository已经是特定项目并且对于您的项目而言是唯一的,为什么不将“扩展名”直接放在UserRepository中?我真的想不出一个很好的理由不这样做。但是...
Auth
服务。由于要进行一些重要的准备工作,以在学说的一边创建存储库,并且涉及一些类似单例的依赖项(注册表,连接等),并在某个地方挖掘,因此请采用自动装配/自动配置框架,并将UserRepository
设为Auth
服务的参数:
class Auth {
/** @var UserRepository */
private $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function authenticate(...) {
/* some logic that can use $this->userRepository */
}
}
重要说明:您将jwt,电子邮件,密码作为Auth的参数。这产生了语义上的差异:要么是对用户进行身份验证的服务,在这种情况下,绝对不要将jwt,电子邮件和密码作为构造函数的一部分,因为那样的话,它将是对一个用户的身份验证,即为其创建用户的身份验证。 ...几乎没有任何好处。否则,它应该在authenticate调用中接收这些参数-我认为这更有意义。
但是,如果您正在执行一些复杂的身份验证协议,在该协议中,您需要与在用户凭据顶部(用户身份验证即服务或其他任何东西)上需要一些其他凭据的外部服务器通信,那么我的论点是无效的,您应该学习如何在services.yaml中定义Auth的凭据。
但是我怀疑并非如此。暂时考虑一下状态可能是一个好主意。通常,找出构造服务的实际必要条件,并将这些内容添加到构造函数中。当服务必须执行某些操作时,它属于服务方法中的参数。
自己创建一个Auth
是很不方便的,因为您将不得不重建symfony的依赖注入+自动接线+自动配置已经提供的许多功能。干净的方法是注入所需的东西。
我将在此处重复您的索引路线,并在下面添加一些评论
public function index(Request $request) {
$auth = new Auth();
$auth->authenticate(null, 'somefakemaik@example.com', '1234');
return $this->tpl();
}
尽管不是严格要求,但通常将控制器的路由功能命名为[something]Action
,因此命名为indexAction
。其次,您显然不使用Request
,因此应将其删除。第三,将UserRepository
或Auth
添加到方法标题中(取决于您选择的替代方法):
// this goes into your controller
// or: public function indexAction(UserRepository $userRepository) {
public function indexAction(Auth $auth) {
$auth->authenticate(/** ... your parameters ... */);
return $this->tpl(); // <-- what's this? ;o)
}