Я пытаюсь отправить форму с помощью 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.info(id);
form = $('#task_form').serialize();
console.info(form);
$.ajax({
url:'{{ path('submit_task') }}',
type: "POST",
dataType: "json",
data: {
"task": form
},
async: true,
success: function (return_data)
{
console.info(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);
}
Форма создается в действии index:
/**
* @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()
));
}
Я хотел бы знать, как обрабатывать данные формы без объекта «форма» в функции. Может ли кто-нибудь помочь мне с этой проблемой!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ваша проблема - это то, на что я наткнулся еще в Symfony3, и с тех пор я пробовал различные методы обработки контента, отправленного через AJAX.
Эта часть проста, в контроллере просто вызовите $data = $request->getContent();
Создайте сервис, который поможет обрабатывать такие данные. Он использует валидатор Symfony (см. Конструктор: ValidatorInterface) и имеет метод под названием validateAndCreate, который принимает в качестве параметра $data (который является содержимым тела запроса AJAX) и $entityClassName (который является объектом для создания и заполнения данными, например: User::class сгенерирует строку имени класса)
Эти три будут важны при обработке вашего AJAX-контента. $data можно десериализовать и внедрить непосредственно в экземпляр объекта (созданный из параметра ClassName).
Если данные отправляются как JSON, используйте JsonEncoder, после создания объекта сериализатора он сможет десериализовать данные JSON непосредственно во вновь созданный объект (параметр className in используется для создания объекта).
После создания объекта используйте валидатор, чтобы проверить, является ли он действительным объектом. Я рекомендую использовать @Assert во всех объектах Entity, чтобы валидатор работал соответствующим образом.
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);
}
$("#form").on("submit", function(e){
e.preventDefault();
let data = {};
$(this).serializeArray().forEach((object)=>{
data[object.name] = object.value;
});
console.info(data);
//TODO: ajax call here with data
//If ajax call fails because server can't decode
//Think of doing : data = JSON.stringify(data);
console.info(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 = "[email protected]" 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% 26ta sk_form% 255Bdescript ion% 255D% 3DTest% 26ta sk_form% 255Bstatus% 2 55D% 3DTo-do% 26task_f orm% 255B_token% 255D% 3DEvrXAl-zRja0oZM60a jFoG9KcdIu7zj7i8WOF1 RH2eE & assignment_id = 1 ',' json ', array (' json_decode_associative '=> true,' json_decode_recursion_depth '), как это могло произойти> 512 ?
@SanderBakker да, потому что вы не отправляете JSON, вы отправляете данные формы, а не данные JSON. Я посмотрю, не смогу ли я предоставить пример клиентской части.
@SanderBakker там проверьте код javascript, console.info - это формат, в котором вы хотите его отправить. Возможно, вам придется выполнить JSON.stringify, прежде чем отправлять его.
Какой метод вы имеете в виду, говоря «метод»?