我们是否迁移错误?从 Symfony 2.7 迁移到 4.0 的表单中未发生验证

问题描述 投票:0回答:1

在从 Symfony 2.7 迁移到 4.0 的代码中,我的表单上不再进行验证,从而允许错误数据通过并导致违反 Doctrine 约束

我是 Symfony 新手,被要求将 2.7 应用程序迁移到 4.0。我按照步骤(2.7->2.8->3.x->4.0)执行此操作并解决了出现的问题,但在此过程中遇到的一件事是自动表单验证。在原始版本中,如果我尝试创建新用户并将字段留空,它会正确标记这些用户并在 UI 中弹出“不得为空”消息。现在,它让这些过去,直到它尝试写入数据库,此时 Doctrine barfs 因为违反了数据库非空约束。

我试图找出我做错了什么,但我并没有牢牢掌握表单创建过程和语法是如何改变的。有关表单验证的所有示例文档都假定使用 createFormBuilder() 方法,并且我所有现有的代码都使用 createForm()。我错过了什么?

这是与表单关联的用户对象的一部分,显示了我希望触发验证警告的 @Assert 语句:

/**
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="Domain\CoreBundle\Repository\UserRepository")
 * @ORM\HasLifecycleCallbacks()
 * @UniqueEntity(fields="email", message="This email address is already in usage")
 * @UniqueEntity(fields="username", message="This username is already in usage")
 */
class User extends BaseUser implements JsonSerializable
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @Assert\NotBlank(message="Email should not be empty")
     * @Assert\Email(strict=true)
     * @Assert\Length(max=150, maxMessage="Email should be less than {{ limit }} characters")
     */
    protected $email;

    /**
     * @Assert\NotBlank(message="Username should not be empty")
     * @Assert\Regex(
     *     pattern = "/^\d*[a-zA-Z][ a-zA-Z0-9\!\@\#\$\%\^\&\-\_\=\+\~\?\.]*$/i",
     *     message = "Username should include at least one letter"
     * )
     */
    protected $username;

    /**
     * @var string
     *
     * @Assert\NotBlank(message="First name should not be empty")
     * @ORM\Column(name="first_name", type="string", length=255)
     */
    protected $firstName;

    /**
     * @var string
     *
     * @Assert\NotBlank(message="Last name should not be empty")
     * @ORM\Column(name="last_name", type="string", length=255)
     */
    protected $lastName;

    (rest of code omitted for conciseness)

这是来自控制器的 addNew 操作(AdministratorController 扩展了 UserController):

    /**
     * Add new administrator
     *
     * @param Request $request
     *
     * @return Response
     */
    public function addNewAction(Request $request)
    {
        $company = $this->getCurrentCompany();
        $form = $this->createForm(AddAdministratorType::class, null,
          array('current_user'=> $this->user, 'restricted_admin'=>$this->getRestrictedAdmin(), 'company'=>$company));

        if ($request->getMethod() == Request::METHOD_POST) {
            $form->handleRequest($request);

            // check if the user already exists
            $userManager = $this->get('fos_user.user_manager');
            $user = $form->getData();

            $oldUser = $userManager->findUserByUsername($user['email']);
            if ($oldUser)
            {
                $alreadyExists = false;
                if ($user["isSuperAdmin"] &&$oldUser->isGrantedSuperAdmin())
                    $alreadyExists = true;
                if ($user["isCompanyAdmin"] && $oldUser->isGranted(UserRepository::ROLE_COMPANY_ADMIN, $company))
                    $alreadyExists = true;
                if (!$user["isCompanyAdmin"] && !$user["isSuperAdmin"] && $oldUser->isGranted(UserRepository::ROLE_ADMIN,$company))
                    $alreadyExists = true;

                if ($alreadyExists)
                    $form->get('email')->addError(new FormError('This email address is already in use'));
            }


            if ($form->isValid()) {
                $user = $form->getData();


                if ($oldUser) // if the user already exists, we just need to add the role
                {
                    if (!$this->getUser()->isGrantedSuperAdmin() && 
                                !in_array($company->getId(), array_map(function($x){return $x->getId();}, $oldUser->getCompaniesWithRole())))
                    {
                        // the user isn't currently in this company and the user adding the role
                        // isn't a super admin, so we have to create a shadow user entry to hide 
                        // the real user info from other in the company until the user logs into
                        // the company
                        $oldShadow=$this->em->getRepository(ShadowUser::class)->findOneBy(array("user" => $oldUser, "company"=>$company));
                        if (!$oldShadow)
                        {
                            $shadow = new ShadowUser();
                            $shadow->setUser($oldUser);
                            $shadow->setFirstName($user["firstName"]);
                            $shadow->setLastName($user["lastName"]);
                            $shadow->setCompany($company);
                            $shadow->setIsVydioUsed($user["isVydioUsed"]);
                            $shadow->setVydioRoomLink($user["vydioRoomLink"]);
                            $shadow->setCreatedDate(new \DateTime());
                            $this->em->persist($shadow);
                        }
                    }

                    if ($user["isSuperAdmin"])
                    {
                        $oldUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_SUPER_ADMIN, $company );
                    }
                    if ($user["isCompanyAdmin"])
                    {
                        $oldUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
                    }
                    if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
                    {
                        $oldUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_ADMIN, $company );
                    }

                    $programRepo = $this->em->getRepository(ProgramUser::class);
                    foreach($user["programs"] as $program)
                    {
                        $oldRelation = $programRepo->findOneBy(array("user"=> $oldUser, "program"=>$program));
                        if (!$oldRelation)
                        {
                            $relation = new ProgramUser();
                            $relation->setUser($oldUser);
                            $relation->setProgram($program);
                            $relation->setCompany($company);
                            $this->em->merge($relation);
                        }
                    }
                    $this->em->persist($oldUser);
                    $this->em->flush();

                }
                else
                {
                    $newUser = new User();
                    $newUser->setPassword($this->get('domain_core_service')->generatePassword());
                    $newUser->setDefaultCompany($company);
                    $newUser->setFirstName($user["firstName"]);
                    $newUser->setLastName($user["lastName"]);
                    $newUser->setEmail($user["email"]);
                    $newUser->setUsername($user["email"]);
                    $newUser->setEnabled($user["enabled"]);
                    $newUser = $this->em->getRepository('DomainCoreBundle:User')->addUserInSystem($userManager, $newUser);

                    $token = $this->get('domain_core_service')->generateToken();
                    $newUser->setConfirmationToken($token);
                    if ($user["isSuperAdmin"])
                    {
                        $newUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_SUPER_ADMIN, $company );
                    }
                    if ($user["isCompanyAdmin"])
                    {
                        $newUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
                    }
                    if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
                    {
                        $newUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
                        $this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_ADMIN, $company );
                    }

                    foreach($user["programs"] as $program)
                    {
                        $relation = new ProgramUser();
                        $relation->setUser($newUser);
                        $relation->setProgram($program);
                        $relation->setCompany($company);
                        $this->em->merge($relation);
                    }

                    $this->em->persist($newUser);
                    $this->em->flush();

                }
                return $this->redirect($this->generateUrl('domain_admin_show_all_administrators_page'));
            }
        }

        return $this->render(
            'DomainAdminBundle:Administrators:add-new.html.twig',
            array(
                 'form'                => $form->createView(),
                 'page_title'          => 'Add New Administrator',
                 'currentSidebar'      => $this->currentSideBar,
                 'currentSidebarItem'  => $this->currentSidebarItem,
            )
        );
    }

以及表单的树枝文件:

{% extends 'DomainAdminBundle::base-admin-layout.html.twig' %}
{% import '::widgets/form_errors.html.twig' as form_custom_errors %}
{% import '::widgets/label.html.twig' as form_custom_labels %}
{% block title %} My Application| {{ page_title }} {% endblock %}

{% block javascripts %}
    {{ parent() }}

    <script type="text/javascript" src="{{ asset('assets/scripts/admin-add-new.js') }}"></script>
{% endblock %}

{% block stylesheets %}
    {{ parent() }}

    <link rel="stylesheet" type="text/css" href="{{ asset('assets/styles/admin-add-new.css') }}">
{% endblock %}

{% block admin_main_content %}
    <div class="content-block administrator-controller" ng-controller="AdministratorController">
        <div class="content-title-bar">
            <div class="pull-left">
                <h2>{{ page_title }}</h2>
            </div>
        </div>

        <div class="content-block" ng-controller="AdminController">
            {{ form_start(form, {"attr": { "action":"{{ path('domain_admin_add_new_administrator_page') }}", 'enctype': 'multipart/form-data', "method":"POST", "novalidate":"novalidate", "autocomplete":"off", "class":"form-horizontal add-user", "ng-submit":"disableAddButton()" }}) }}
                <div class="base-box info-block">
                    <div class="control-group">
                        <div class="controls">
                            {{ form_widget(form.enabled) }}
                            {{ form_label(form.enabled, 'Active') }}
                        </div>
                    </div>
                    {% if app.user.isGrantedSuperAdmin() %}
                        <div class="control-group">
                            <div class="controls">
                                {% set companyAdminValue = form.isCompanyAdmin.vars.checked ? 'true' : 'false' %}
                                {{ form_widget(form.isCompanyAdmin, { 'attr':{ 'ng-model':'adminForm.isCompanyAdmin', 'ng-init': 'adminForm.isCompanyAdmin=' ~ companyAdminValue } }) }}
                                {{ form_label(form.isCompanyAdmin, 'Company Admin') }}
                                {% set superAdminValue = form.isSuperAdmin.vars.checked ? 'true' : 'false' %}
                                {{ form_widget(form.isSuperAdmin, { 'attr':{ 'ng-model':'adminForm.isSuperAdmin', 'ng-init': 'adminForm.isSuperAdmin=' ~ superAdminValue } }) }}
                                {{ form_label(form.isSuperAdmin, 'Super Admin') }}
                            </div>
                        </div>
                    {% endif %}
                    <div class="control-group" ng-init="initMultiSelect(true)">
                        {{ form_custom_labels.widget(form.programs) }}
                        <div class="controls">
                            {{ form_widget(form.programs) }}
                            {{ form_custom_errors.widget(form.programs) }}
                        </div>
                    </div>
                    <div class="control-group">
                        {{ form_custom_labels.widget(form.firstName) }}
                        <div class="controls">
                            {{ form_widget(form.firstName) }}
                            {{ form_custom_errors.widget(form.firstName) }}
                        </div>
                    </div>
                    <div class="control-group">
                        {{ form_custom_labels.widget(form.lastName) }}
                        <div class="controls">
                            {{ form_widget(form.lastName) }}
                            {{ form_custom_errors.widget(form.lastName) }}
                        </div>
                    </div>
                    <div class="control-group">
                        {{ form_custom_labels.widget(form.email) }}
                        <div class="controls">
                            {{ form_widget(form.email) }}
                            {{ form_custom_errors.widget(form.email) }}
                        </div>
                    </div>
                    <div class="control-group">
                        {{ form_custom_labels.widget(form.timezone) }}
                        <div class="controls">
                            {{ form_widget(form.timezone) }}
                            {{ form_custom_errors.widget(form.timezone) }}
                        </div>
                    </div>
                </div>
                <div class="text-right">
                    <button id="add-admin-submit" type="submit" class="btn btn-do" ng-disabled="isDisabled">Add new administrator</button>
                    <a href="{{ path('domain_admin_show_all_administrators_page') }}" class="btn btn-redo" ng-disabled="isDisabled">Cancel</a>
                </div>
                {{ form_rest(form) }}
            {{ form_end(form) }}
        </div>
    </div>
{% endblock %}

如果我将所有字段留空并单击“添加新管理员”,它不会将它们标记为空白,而是将它们传递给 Doctrine。预期的行为是它在 UI 上标记它们,并且不会尝试将它们写入数据库。

我确信我已经对 Symfony 造成了多次犯罪,因为我已经加快了学习曲线,所以放轻松。现在我只是想解决这个狭隘的问题;重构以更优雅地适应 Symfony 4 将不得不等待另一天。

谢谢!

php symfony symfony4 symfony-forms
1个回答
0
投票

看起来您想根据请求中的数据验证 User 类。

您是否在表单类型类中设置了 data_class 选项?

如果您想使用另一个类的验证规则(因为您使用一些 @Assert* 注释标记您的属性),则这是必需的。

https://symfony.com/doc/current/forms.html#creating-form-classes

进行验证的另一种方法是在 FormType 中直接选择验证规则。

© www.soinside.com 2019 - 2024. All rights reserved.