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()
));
}
関数内の「フォーム」オブジェクトなしでフォームデータを処理する方法を教えてください。誰かがこの問題を助けてくれますか?
あなたの問題はSymfony3で偶然見つけたもので、それ以来、AJAX経由で送信されたコンテンツを処理するためにさまざまな方法を試してきました。
この部分は単純です。コントローラでは、単に$data = $request->getContent();
を呼び出します。
この種のデータの処理に役立つサービスを作成します。 Symfonyのバリデーター(コンストラクター:ValidatorInterface
を参照)を使用し、_validateAndCreate
と呼ばれるメソッドをパラメーター_$data
_(AJAXリクエスト)として受け取りますbody content)と_$entityClassName
_(データを作成してデータを入力するエンティティです。例:_User::class
_はクラス名文字列を生成します)
これら3つは、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);
}
_
_$("#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="[email protected]" name="email"/>
<input type="submit" value="submit this"/>
</form>
_