PHP symfony 4 ajax 表单提交
Posted
技术标签:
【中文标题】PHP symfony 4 ajax 表单提交【英文标题】:PHP symfony 4 ajax form submission 【发布时间】:2018-10-30 04:12:13 【问题描述】:我正在尝试使用 ajax 提交表单并将其数据发送到数据库,但我不明白如何处理从 ajax 调用接收到的数据。
我写了以下代码:
% extends 'base.html.twig' %
% block title %Assignments | CRM Fabriek% endblock %
% block body %
<div class="container">
<div class="columns">
<div class="column is-full">
<div class="level">
<h1 class="level-left title title-no-margin is-vcentered">Assignments</h1>
<div class="level-right">
% include 'search.html.twig' %
<a href=" path("newAssignment") " class="level-item button is-success">Add new</a>
</div>
</div>
<table class="table is-fullwidth">
<tr>
<th>Name</th>
<th>Description</th>
<th>Status</th>
<th>Actions</th>
</tr>
% if assignments != null %
% for assignment in assignments %
<tr>
<td> assignment.name </td>
<td> assignment.description </td>
<td> assignment.status </td>
<td>
<a class="button is-info is-small" href=" path('overviewAssignment', 'id': assignment.id) "><i class="fa fa-eye"></i></a>
<a class="button is-warning is-small" href=" path('editAssignment', 'id': assignment.id) "><i class="fa fa-pencil"></i></a>
<button class="button is-success is-small" onclick="openModal( assignment.id )"><i class="fa fa-plus"></i></button>
</td>
</tr>
% endfor %
% else %
<tr>
<td colspan="4">No entries</td>
</tr>
% endif %
</table>
<div class="pagerfanta">
pagerfanta(pager)
</div>
<div>
<div class="modal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Modal title</p>
</header>
<section class="modal-card-body">
form_start(form, 'attr': 'id': 'task_form')
form_row(form.name, 'attr': 'class': 'input')
form_row(form.description, 'attr': 'class': 'textarea')
form_label(form.status)
<div class="control">
<div class="select">
form_widget(form.status)
</div>
</div>
form_end(form)
</section>
<footer class="modal-card-foot">
<button id="submit_task" class="button is-success">Save changes</button>
<button class="button" onclick="closeModal()">Cancel</button>
</footer>
</div>
</div>
</div>
</div>
</div>
</div>
% endblock %
% block javascripts %
<script>
function openModal(id)
$('.modal').addClass('is-active');
$('#submit_task').attr('onClick', 'submitTask('+ id +');');
function closeModal()
$('.modal').removeClass('is-active');
function submitTask(id)
console.log(id);
form = $('#task_form').serialize();
console.log(form);
$.ajax(
url:' path('submit_task') ',
type: "POST",
dataType: "json",
data:
"task": form
,
async: true,
success: function (return_data)
console.log(return_data);
,
error: function (xhr, ajaxOptions, thrownError)
);
closeModal();
</script>
% endblock %
在控制器中使用以下方法:
/**
* @Route("/", name="submit_task")
*/
public function add_task(Request $request)
$form_data = $request->get('task');
return new JsonResponse($form_data);
在索引动作中创建表单:
/**
* @Security("is_authenticated()")
* @Route("/assignments", name="assignments")
*/
public function index(Request $request)
$assignment_rep = $this->getDoctrine()->getRepository(Assignment::class);
if($request->get('search') == null)
if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN'))
$assignments = $assignment_rep->findAll();
else
/* @var User $user */
$user = $this->getUser();
$assignments = array();
foreach($user->getAssignments() as $assignment)
array_push($assignments, $assignment);
else
if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN'))
$assignments = $assignment_rep->search($request->get('search'));
else
/* @var User $user */
$assignments = $assignment_rep->searchUser($request->get('search'), $this->getUser()->getId());
$page = $request->query->get('page', 1);
$adapter = new ArrayAdapter($assignments);
$pagerfanta = new Pagerfanta($adapter);
$pagerfanta->setMaxPerPage(25);
$pagerfanta->setCurrentPage($page);
$task = new Task();
$form = $this->createForm(TaskFormType::class, $task);
$form->remove('assignment');
$assignments = $pagerfanta->getCurrentPageResults();
return $this->render('assignment/index.html.twig', array(
'assignments' => $assignments,
'pager' => $pagerfanta,
'form' => $form->createView()
));
我想知道如何在函数中没有“表单”对象的情况下处理表单数据。谁能帮我解决这个问题!
【问题讨论】:
你说的“方法”是什么方法? 【参考方案1】:你的问题是我在 Symfony3 中偶然发现的,从那以后我一直在尝试各种方法来处理通过 AJAX 发送的内容。
获取 AJAX 数据
这部分很简单,在控制器中直接调用$data = $request->getContent();
创建服务
创建一个服务来帮助处理此类数据。它使用 Symfony 的验证器(参见构造函数:ValidatorInterface
),并有一个名为 validateAndCreate
的方法,该方法将 $data
(这是 AJAX 请求正文内容)和 $entityClassName
(这是要创建的实体)作为参数并填充数据,例如:User::class
将生成类名字符串)
规范化器、编码器和序列化器
这三个对于处理 AJAX 内容很重要。 $data
可以反序列化并直接注入到实体实例中(通过 ClassName 参数创建)
如果数据以JSON
发送,则使用JsonEncoder
,一旦创建了序列化器对象,它将能够将JSON数据直接反序列化为新实例化的对象(参数中的className用于生成对象)。
生成对象后,使用验证器检查它是否为有效对象。我建议在所有 Entity 对象中使用 @Assert
以使验证器相应地工作。
class ApiService
private $validator;
public function __construct(ValidatorInterface $validator)
$this->validator = $validator;
public function validateAndCreate($data, $entityClassName)
$objectNormalizer = new ObjectNormalizer();
$normalizers = [$objectNormalizer];
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$result = $serializer->deserialize($data, $entityClassName, 'json');
$errors = $this->validator->validate($result);
if(count($errors) > 0)
throw new CustomApiException(Response::HTTP_BAD_REQUEST, (string) $errors);
return $result;
在控制器中用于创建新会议的示例
public function newMeeting(Request $request, ApiService $apiService, FractalService $fractalService)
/** @var Admin $admin */
$admin = $this->getUser();
/** @var UserRepository $rep */
$em = $this->getDoctrine()->getManager();
$data = $request->getContent();
if(empty($data)) throw new CustomApiException(Response::HTTP_BAD_REQUEST, "Data sent null.");
/** @var Meeting $test */
$meeting = $apiService->validateAndCreate($data, Meeting::class);
$meeting->setAdmin($admin);
$admin->addMeeting($meeting);
$em->persist($test);
$em->flush();
//Return data however you wish, I use a FractalService
$data = $fractalService->generateData($meeting, MeetingTransformer::class, 'meeting');
return $fractalService->generateResponse($data);
AJAX 表单处理的客户端示例
$("#form").on("submit", function(e)
e.preventDefault();
let data = ;
$(this).serializeArray().forEach((object)=>
data[object.name] = object.value;
);
console.log(data);
//TODO: ajax call here with data
//If ajax call fails because server can't decode
//Think of doing : data = JSON.stringify(data);
console.log(JSON.stringify(data));
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form">
<input type="text" value="john" name="firstname"/>
<input type="text" value="smith" name="lastname"/>
<input type="text" value="florida" name="address"/>
<input type="text" value="1234512345" name="phonenumber"/>
<input type="text" value="john.smith@gmail.com" name="email"/>
<input type="submit" value="submit this"/>
</form>
【讨论】:
我要试试这个,一个问题;分形服务与所有这些有什么关系? @SanderBakker 因为我有一个 API 系统,所以我需要按照 JSONApi 规范将数据转换为特定的常规格式。在此处查看有关分形的更多信息github.com/samjarrett/FractalBundle(我不建议在您的情况下使用它) @SanderBakker 请记住,CustomApiException 只是我创建的自定义异常。我有一个侦听器来侦听该特定异常以返回 HTTP 400 错误请求响应。你必须相应地改变它。 不知何故,它似乎无法使用 de json 编码器进行解码; JsonDecode->decode('task=task_form%255Bname%255D%3DTest%26task_form%255Bdescription%255D%3DTest%26task_form%255Bstatus%255D%3DTo-do%26task_form%255B_token%255D%3DEvrXAl-zRja0oZM60ajFoG9KcdIu7zj7i8'1KcdIu7zj7i8KcdIu7zj7i8 , array('json_decode_associative' => true, 'json_decode_recursion_depth' => 512, 'json_decode_options' => 0)) 关于这怎么可能发生的任何线索? @SanderBakker 是的,因为您不是在发送 JSON,而是在发送表单数据而不是真正的 JSON 数据。我会看看我是否不能提供一个示例客户端。以上是关于PHP symfony 4 ajax 表单提交的主要内容,如果未能解决你的问题,请参考以下文章
symfony2 中的 Ajax 表单提交,为没有 javascript 的用户提供优雅的降级