模板在 Symfony 中不起作用 - 如何连接新功能?

Template doesn't work in Symfony - how to connect a new function?

我正在创建一个应用程序,我想让用户能够更改他们的数据和密码。我已经创建了一个电子邮件更改表单并且可以正常工作,但我遇到了密码问题。 我有一个页面 localhost:8000/user/{id} 和这里的按钮:编辑电子邮件和编辑密码。编辑电子邮件有效,当我点击编辑密码时 - 我在 localhost:8000/user/{id}/change_password 上看到一个空白页面 (enter image description here enter image description here)。那里没有显示 PassType。

localhost:8000/user/{id} 和 localhost:8000/user/{id}/change_password 没有语法错误。

我已经向 UserController 添加了一个函数 edit_pass,创建了 PassType(更改密码的表单在哪里)并制作了一个模板 edit_password.html.twig。

不知道哪里出了问题。我对其他有效的表格做了同样的事情。我试图清除 edit_password 模板(我只是把 base_html 留在那里并放了一些文本)因为我认为它有问题,但它仍然是空白localhost:8000/user/{id}/change_password.

页面

密码类型:

<?php
/*
 * Password type.
 */

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class PassType.
 */
class PassType extends AbstractType
{
    /**
     * Builds the form.
     *
     * This method is called for each type in the hierarchy starting from the
     * top most type. Type extensions can further modify the form.
     *
     * @see FormTypeExtensionInterface::buildForm()
     *
     * @param FormBuilderInterface $builder The form builder
     * @param array                $options The options
     */
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add(
            'password',
            RepeatedType::class,
            [
                'type' => PassType::class,
                'required' => true,
                'attr' => ['max_length' => 40],
                'first_options' => ['label' => 'label.password'],
                'second_options' => ['label' => 'label.repeat_password'],
            ]
        );
    }

    /**
     * Configures the options for this type.
     *
     * @param OptionsResolver $resolver The resolver for the options
     */
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(['data_class' => User::class]);
    }

    /**
     * Returns the prefix of the template block name for this type.
     *
     * The block prefix defaults to the underscored short class name with
     * the "Type" suffix removed (e.g. "UserProfileType" => "user_profile").
     *
     * @return string The prefix of the template block name
     */
    public function getBlockPrefix(): string
    {
        return 'user';
    }
}

edit_password.html.twig

{% extends 'base.html.twig' %}

{% block title %}
    {{ 'title_password_edit'|trans({'%id%': user.id|default('')}) }}
{% endblock %}

{% block body %}
    <h1 class="display-4 d-flex justify-content-center">{{ 'title_password_edit'|trans({'%id%': user.id|default('')}) }}</h1>
    {{ form_start(form, { method: 'PUT', action: url('password_edit', {id: user.id}) }) }}
    {{ form_widget(form) }}
    <div class="form-group row float-sm-right">
        <input type="submit" value="{{ 'action_save'|trans }}" class="btn btn-primary" />
    </div>
    <div class="form-group row float-sm-left">
        <a href="{{ url('user_index') }}" class="btn btn-link">
            {{ 'action_back_to_list'|trans }}
        </a>
    </div>
    {{ form_end(form) }}

{% endblock %}

和具有 edit_pass 功能的 UserController 的一部分

 /**
     * Edit Password.
     *
     * @param \Symfony\Component\HttpFoundation\Request $request    HTTP request
     * @param \App\Entity\User                          $user       User entity
     * @param \App\Repository\UserRepository            $repository User repository
     *
     * @return \Symfony\Component\HttpFoundation\Response HTTP response
     *
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     *
     * @Route(
     *     "/{id}/change_password",
     *     methods={"GET", "PUT"},
     *     requirements={"id": "[1-9]\d*"},
     *     name="password_edit",
     * )
     */
    public function edit_pass(Request $request, User $user, UserPasswordEncoderInterface $passwordEncoder, UserRepository $repository): Response
    {
        $form = $this->createForm(PassType::class, $user, ['method' => 'PUT']);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $user->setPassword(
                $passwordEncoder->encodePassword(
                    $user,
                    $form->get('password')->getData()
                )
            );
            $repository->save($user);

            $this->addFlash('success', 'message.updated_successfully');

            return $this->redirectToRoute('user_show', array('id' => $this->getUser()->getId()));
        }

        return $this->render(
            'user/edit_password.html.twig',
            [
                'form' => $form->createView(),
                'user' => $user,
            ]
        );
    }

我还要添加 user/show。html.twig

{% extends 'base.html.twig' %}

{% block title %}
    {{ 'label_detail_users'|trans({'%id%': user.id|default('')}) }}
{% endblock %}

{% block body %}
    <h1 class="display-4 d-flex justify-content-center">{{ 'label_detail_users'|trans({'%id%': user.id|default('')}) }}</h1>
    {% if users is defined and users|length %}
        <table class="table table-striped">
            <thead>
            <tr>
                <th>{{ 'label_user_id'|trans }}</th>
                <th>{{ 'label_email'|trans }}</th>
            </tr>
            </thead>
            <tbody>
                <tr>
                    <td>{{ users.id }}</td>
                    <td>{{ users.email }}</td>
                </tr>
            </tbody>
        </table>
        <p>
            <a class="btn btn-info" href="{{ url('user_edit', {id: users.id}) }}" title="{{ 'edit_email'|trans }}">
                {{ 'edit_email'|trans }}
            </a>
        </p>
        <p>
            <a class="btn btn-info" href="{{ url('password_edit', {id: users.id}) }}" title="{{ 'edit_password'|trans }}">
                {{ 'edit_password'|trans }}
            </a>
        </p>
        <p>
            <a class="btn btn-info" href="{{ url('user_index') }}" title="{{ 'action_back_to_list'|trans }}">
                {{ 'action_back_to_list'|trans }}
            </a>
        </p>

    {% else %}
        <p>
            {{ 'message_item_not_found'|trans }}
        </p>
    {% endif %}
{% endblock %}

您产生了一个无限循环 - 它在您的 RepeatedTypePasswordTypePassType 是您整个表单的名称 - 您看到问题了吗?

public function buildForm(FormBuilderInterface $builder, array $options): void
{
    $builder->add(
        'password',
        RepeatedType::class,
        [
            'type' => PasswordType::class,
            'required' => true,
            'attr' => ['max_length' => 40],
            'first_options' => ['label' => 'label.password'],
            'second_options' => ['label' => 'label.repeat_password'],
        ]
    );
}

请问你们为什么限制密码的长度?