模板在 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 %}
您产生了一个无限循环 - 它在您的 RepeatedType
中 PasswordType
。 PassType
是您整个表单的名称 - 您看到问题了吗?
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'],
]
);
}
请问你们为什么限制密码的长度?
我正在创建一个应用程序,我想让用户能够更改他们的数据和密码。我已经创建了一个电子邮件更改表单并且可以正常工作,但我遇到了密码问题。 我有一个页面 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 %}
您产生了一个无限循环 - 它在您的 RepeatedType
中 PasswordType
。 PassType
是您整个表单的名称 - 您看到问题了吗?
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'],
]
);
}
请问你们为什么限制密码的长度?