You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()调用

将代码中直接获取服务的部分替换为注入的属性:

  1. 替换密码表单工厂的获取:

    // 原代码
    $formFactory = $this->get('fos_user.change_password.form.factory');
    // 修改后
    $formFactory = $this->changePasswordFormFactory;
    
  2. 替换编码器工厂的获取:

    // 原代码
    $factory = $this->get('security.encoder_factory');
    // 修改后
    $factory = $this->encoderFactory;
    
  3. 替换验证器的获取:

    // 原代码
    $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 01:02:33