PHP Symfony 4 AJAX формы отправки - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь отправить форму с использованием 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);
    }

Форма создается в действии 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()
        ));
    }

Я хотел бы знать, какобрабатывать данные формы без объекта «form» в функции.Может ли кто-нибудь помочь мне с этой проблемой!

1 Ответ

0 голосов
/ 20 мая 2018

Ваша проблема связана с тем, что я наткнулся на Symfony3, и с тех пор я пробовал различные методы обработки содержимого, отправляемого через AJAX.

Получение данных 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);

    }

На стороне клиентапример обработки формы для 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...