Symfony3升级Symfony4遇私有服务获取弃用问题求助
Symfony 3.4升级到4:解决私有服务获取的弃用警告
你遇到的弃用警告源于Symfony4默认所有服务为私有,禁止直接通过$this->get()从容器获取私有服务。以下是针对两个问题服务的解决方案:
推荐方案:构造函数依赖注入
这是Symfony4官方推荐的方式,替代直接从容器获取服务,更符合依赖倒置原则。
步骤1:添加必要的use声明
在控制器顶部补充以下use语句:
use FOS\UserBundle\Form\Factory\FactoryInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Validator\Validator\ValidatorInterface;
步骤2:注入服务到控制器构造函数
修改控制器类,添加私有属性和构造函数,注入所需服务:
class ProfileAdminController extends Controller { private $changePasswordFormFactory; private $encoderFactory; private $validator; public function __construct(FactoryInterface $changePasswordFormFactory, EncoderFactoryInterface $encoderFactory, ValidatorInterface $validator) { $this->changePasswordFormFactory = $changePasswordFormFactory; $this->encoderFactory = $encoderFactory; $this->validator = $validator; } // ... 原有action方法 }
步骤3:替换原有$this->get()调用
将代码中直接获取服务的部分替换为注入的属性:
替换密码表单工厂的获取:
// 原代码 $formFactory = $this->get('fos_user.change_password.form.factory'); // 修改后 $formFactory = $this->changePasswordFormFactory;替换编码器工厂的获取:
// 原代码 $factory = $this->get('security.encoder_factory'); // 修改后 $factory = $this->encoderFactory;替换验证器的获取:
// 原代码 $validator = $this->get('validator'); // 修改后 $validator = $this->validator;
临时过渡方案(不推荐长期使用)
如果暂时不想重构代码,可以在config/services.yaml中将这两个服务设为公开:
services: security.encoder_factory: public: true fos_user.change_password.form.factory: public: true
注意:此方案仅适合临时过渡,Symfony后续版本可能彻底移除对公开私有服务的支持。
修改后的完整控制器代码片段
<?php namespace AppBundle\Controller; use AppBundle\Form\UserType; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use FOS\UserBundle\Model\UserInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use FOS\UserBundle\Form\Factory\FactoryInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; class ProfileAdminController extends Controller { private $changePasswordFormFactory; private $encoderFactory; private $validator; public function __construct(FactoryInterface $changePasswordFormFactory, EncoderFactoryInterface $encoderFactory, ValidatorInterface $validator) { $this->changePasswordFormFactory = $changePasswordFormFactory; $this->encoderFactory = $encoderFactory; $this->validator = $validator; } /** * @Route("/profile", name="editProfile") */ public function indexAction(Request $request) { $user = $this->getUser(); if (!is_object($user) || !$user instanceof UserInterface) { throw new AccessDeniedException('This user does not have access to this section.'); } $groups = $this->getDoctrine()->getRepository('AppBundle:Group')->findAll(); $formUser = $this->createForm(UserType::class, $user, array('groups' => $groups, 'type' => 'profile')); /** Passwort edit */ $formFactory = $this->changePasswordFormFactory; $formPw = $formFactory->createForm(); $formPw->setData($user); /** User edit */ $formUser->handleRequest($request); if ($formUser->isSubmitted() && $formUser->isValid()) { // 3) save the User! $em = $this->getDoctrine()->getManager(); try { $em->persist($user); $em->flush(); } catch(UniqueConstraintViolationException $e) { $this->addFlash( 'danger', 'Ein eindeutiges Attribut wurde doppelt vergeben!' ); } $this->addFlash( 'info', 'Angaben erfolgreich geändert!' ); } else if ($formUser->isSubmitted() && !$formUser->isValid()) { return $this->render('administration/profile/edit.html.twig', array( 'formPw' => $formPw->createView(), 'formUser' => $formUser->createView(), 'errors' => $this->validator->validate($user), )); } /** Passwort edit */ $formPwPostData = $request->request->get('fos_user_change_password_form'); /** Check if current password is correct */ $factory = $this->encoderFactory; $encoder = $factory->getEncoder($user); $pwCorrect = ($encoder->isPasswordValid($user->getPassword(),$formPwPostData['current_password'],$user->getSalt())) ? true : false; // ... 原代码后续逻辑 } }
内容的提问来源于stack exchange,提问作者user3296316
相关产品推荐
相关产品推荐

