Can not access request data from ajax post request in symfony 3 - php

I am using symfony 3.4 and I would like to send some data to controller but I do not know why I can not access it like it is show in symfony documentation:
This is my js function:
function sendQuantitiesToController() {
// Validate data
var validation = validateQuestionnaireReviewFormData();
if (validation === false) {
return false;
}
// Get form data
var data = getReviewFormComponentsData();
var id = document.getElementById('questionnaire-id').innerText;
// Send data
$.post("http://localhost:8000/questionnaire/"+id+"/review", {
components: data.components,
optional_components: data.optional_components
},
function(response, status) {
if (status == 'success') {
return true;
} else {
return false;
}
});
}
And this is my Controller function:
/**
* Questionnaire result review
*
* #Route("/questionnaire/{id}/review", name="_questionnaire_review", requirements={"id" = "\d+"})
* #Template()
*/
public function questionnaireReviewAction(Request $request, $id)
{
$form = $this->createForm(ResultOverviewType::class, $result);
$contactForm = $this->createForm(ContactType::class, $contact);
if ($request->isMethod('POST')) {
// Get data from request
$components = $request->request->get('components');
$optionalComponents = $request->request->get('optional_components');
...
}
}
return [
'form' => $form->createView(),
'contactForm' => $contactForm->createView(),
'questionnaire' => $questionnaire
];
}
Twig Template:
{{ form_start(contactForm, {'attr': {'onsubmit': 'return sendQuantitiesToController();'}}) }}
{{ form_widget(form) }}
{{ form_widget(contactForm) }}
{{ form_end(form) }}
The problem is that the $request->request->get('components') in controller is always null, but I checked getReviewFormComponentsData() with console.log and there is data there so the problem is probably with ajax post request. What I am doing wrong? Can anyone help me?
Thanks for help!

To get request data from ajax request in Symfony Controller you should simply do that:
public function questionnaireReviewAction(Request $request, $id)
{
$form = $this->createForm(ResultOverviewType::class, $result);
$contactForm = $this->createForm(ContactType::class, $contact);
if ($request->isMethod('POST')) {
// Get data from request
$data = $request->getContent();
$data = json_decode($data, true);
$components = $data['components'];
$optionalComponents = $data['optional_components'];
...
}
...
}

Related

How can I update a post in laravel using formData?

so I am working in a social network, and I want once a post is done to be able to edit it, but I am having the error:
message: "This action is unauthorized."
is seems something simple to me, I get the info in the component send it throuhg an axios call that goes through a route I have defined and it just goes to the controller and from there to the service, but I must be missing something which I do not know what it is. Any hint is much appreciated as I am getting a bit mad...
this would be the function in the component:
editPost() {
let formData = new FormData();
let headers = { headers: { "Content-Type": "multipart/form-data" } };
let updatedPost = this.post_to_update;
formData.append("post", updatedPost.description);
formData.append("file", this.file);
formData.append("video_link", updatedPost.video_link);
axios
.post("/posts/update/" + updatedPost.id, formData, headers)
.then(response => {
updatedPost.attach_file = response.data.attach_file;
updatedPost.id = response.data.id;
serverBus.$emit("post_edited", updatedPost);
});
this.file = "";
this.post_to_update = {
id: "",
index: null,
description: "",
attach_file: "",
video_link: "",
name: this.profile_info.name,
surname_1: this.profile_info.surname_1,
surname_2: this.profile_info.surname_2,
nick: this.profile_info.nick,
picture: this.profile_info.picture,
id_rol: this.profile_info.id_rol,
time_ago: "0 minutes",
code: this.profile_info.code
};
$("#EditModal").modal("hide");
},
this is the web.php:
########################################################################################################################
# Post Routes
########################################################################################################################
Route::post('/posts/recommend', 'PostController#recommend')
->name('recommendPost');
Route::post('/posts/update/{id}', 'PostController#update');
Route::post('/posts/report', 'PostController#report')
->name('reportPost');
Route::get('/posts/{post}/comments', 'PostController#retrieveComments')
->where('post', '[0-9]+')
->name('commentsByPost');
Route::resource('/posts', 'PostController')
->only(['index', 'store', 'update', 'destroy']);
Route::get('/reportedPosts', 'PostController#reportedPosts');
The controller:
public function update(StorePostRequest $request, $post_id)
{
return $this->postService->updatePost($request, $post_id);
}
and the service:
public function updatePost(StorePostRequest $request, $post_id)
{
$post_to_update = Post::where('id', $post_id)->first();
$post_to_update->description = $request->post;
$post_to_update->attach_file = $request->file ? $filename = sha1(time()) : null;
$post_to_update->file_name = $request->file ? $request->file->getClientOriginalName() : null;
$post_to_update->file_type = $request->file ? $request->file->getClientOriginalExtension() : null;
$post_to_update->save();
if ($request->file) {
Storage::disk('s3')->putFileAs('storage/user_uploads/post_files/' . $post_to_update->id, $request->file, $filename, 'public');
Storage::disk('local')->putFileAs('public/user_uploads/post_files/' . $post_to_update->id, $request->file, $filename, 'public');
}
return $post_to_update;
}
I think StorePostRequest class cause the block of user authorization.
Try add following lines at StorePostRequest to pass the authorization check.
public function authorize()
{
return true; //Default false;
}

POST 500 (Internal Server Error) - Laravel and Ajax

I want to send post request with ajax to controller in laravel. The ajax request send two input arguments and I want controller to find the column in the database with the first argument and then to set the name attribute with the second input argument. But I have this error message Creating default object from empty value
Ajax function:
$('#saveUserProfile').on('click', function () {
var $finduser = $('input[name=findUser]').val();
var $name = $('input[name=userprofilename]').val();
$.ajax({
type:"POST",
url:'/code/task1/public/updateUser',
data: {
'name' : $name,
'finduser' : $finduser,
// 'email' : $email,
},
success:function(data){
$("#input1").val(data[0].name);
}
});
});
and the function in my controller
public function updateUser(Request $request){
$return_array = array();
$findUserInput = $request->get('finduser');
$user = User::where('name',$findUserInput) -> first();
$user->name = $request->get('name');
$user->save();
$data = DB::select("SELECT * FROM users where name='$findUserInput'");
if(count($data) > 0){
foreach($data as $da){
$return_array[] = $da;
}
}
return $return_array;
}
Update: I also make ajax function and controller for finding user which is working good.
ajax function:
$('#buttonFindUser').on('click', function () {
var $name = $('input[name=findUser]').val();
$.ajax({
type:"GET",
url:'/code/task1/public/findUser',
data: {
'name' : $name,
},
success:function(data){
$("#input1").val(data[0].name);
$("#input2").val(data[0].email);
$("#input3").val(data[0].created_at);
}
});
});
Function in my controller:
public function findUser(Request $request){
$return_array = array();
$findUserInput = $request->get('name');
$data = DB::select("SELECT * FROM users where name='$findUserInput'");
if(count($data) > 0){
foreach($data as $da){
$return_array[] = $da;
}
}
return $return_array;
}
Any ideas?
But I have this error message Creating default object from empty value
What's happening is that you are trying to save a user that doesn't exist. You need to check if the $user is null or not in your controller. Right now, the user couldn't be found with the provided name so $user becomes null.
So, you can modify your code to do a null check on $user like so:
public function updateUser(Request $request){
$return_array = array();
$findUserInput = $request->get('finduser');
$user = User::where('name',$findUserInput) -> first();
if(!$user)
return response()->json(['status'=>false,'Description' => 'User could not be found.']);
$user->name = $request->get('name');
$user->save();
$data = DB::select("SELECT * FROM users where name='$findUserInput'");
if(count($data) > 0){
foreach($data as $da){
$return_array[] = $da;
}
}
return $return_array;
}
Here's the null check:
if(!$user)
return response()->json(['status'=>false,'Description' => 'User could not be found.']);
When we don't have a valid user, we just reply back with a json response stating that it couldn't be found.
Update:
Seeing as your input is not being retrieved in the controller, you need to make some changes in JS:
First, you are doing a post request and I cannot see a CSRF token. To add it, follow this answer: https://stackoverflow.com/a/37582060/6270112
So, your data will now become:
data: '_token=' + $('#token').val() + '&name=' + $name + '&finduser=' + $finduser
Also, as aleksejjj mentioned, you need to fix your jquery selectors as well. So, your existing selectors:
var $finduser = $('input[name=findUser]').val();
var $name = $('input[name=userprofilename]').val();
will become:
var $finduser = $('input[name^="findUser"]').val();
var $name = $('input[name^="userprofilename"]').val();
Next, in your controller you need to replace $request->get(...) with $request->input(...).
$findUserInput = $request->get('finduser');
will become
$findUserInput = $request->input('finduser');
and repeat the same with the name field as well.
You need to check your user exist
$user = User::where('name', $findUserInput)->first();
if($user)
{
$user->name = $request->get('name');
$user->save();
}
change this code
$user = User::where('name',$findUserInput) -> first();
to
$user = User::where('name','=',$findUserInput) -> first();
I hope this will work. :)

Symfony 3 - How to insert data from Ajax Response to Database

I am just starting to use Symfony and I just ran in to this problem and even after houers of research online I can not figure it out.
I am trying to insert data from a ajax request into my database. The ajax request works so far an send the following string
{"description":"","location":"","subject":"asdfasdfdsf","allDay":false,"endTime":"2016-11-22T07:00:00.000Z","startTime":"2016-11-22T06:30:00.000Z","user":"6","calendar":"1","offer":"1","status":"open"}
Here is my ajax request
$.ajax({
type: 'POST',
url: '{{ path('calendar_new') }}',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(newAppointment),
dataType: 'json',
success: function(response) {
console.log(response);
}
});
My controller looks like this
/**
* #Route("/calendar/new", name="calendar_new")
* #Method({"GET", "POST"})
*/
public function calenderNewAction(Request $request)
{
if ($request->isXMLHttpRequest()) {
$content = $request->getContent();
if (!empty($content)) {
$params = json_decode($content, true);
$new = new timeEntry;
$new->setDescription($params->get('description'));
$new->setLocation($params->get('location'));
$new->setSubject($params->get('subject'));
$new->setAllDay($params->get('allDay'));
$new->setEndTime($params->get('endTime'));
$new->setStartTime($params->get('startTime'));
$em = $this->getDoctrine()->getManager();
$calendar = $em->getRepository('AppBundle:calendar')
->findOneBy(['id' => 1]);
$offers = $em->getRepository('AppBundle:offer')
->findOneBy(['id' => 1]);
$new->setCalendar($calendar);
$new->setOffer($offers);
$new->setUser($this->getUser());
$em->persist($new);
$em->flush();
}
return new JsonResponse(array('data' => $params));
}
return new Response('Error!', 400);
}
After i try it i get the following error
Call to a member function get() on array
So the $params varible actually returns a object with all the data inside but I don't know how to set my Database variables with these values.
I figured it out.
As mentioned by Cerad I called a method on an array which was the mistake.
Here is my now working controller.
/**
* #Route("/calendar/new", name="calendar_new")
* #Method({"GET", "POST"})
*/
public function calenderNewAction(Request $request)
{
if ($request->isXMLHttpRequest()) {
$content = $request->getContent();
if (!empty($content)) {
$params = json_decode($content, true);
$new = new timeEntry;
$new->setDescription($params['description']);
$new->setLocation($params['location']);
$new->setSubject($params['subject']);
$new->setAllDay($params['allDay']);
$new->setEndTime(new \DateTime($params['endTime']));
$new->setStartTime(new \DateTime($params['startTime']));
$em = $this->getDoctrine()->getManager();
$calendar = $em->getRepository('AppBundle:calendar')
->findOneBy(['id' => 1]);
$offers = $em->getRepository('AppBundle:offer')
->findOneBy(['id' => 1]);
$new->setCalendar($calendar);
$new->setOffer($offers);
$new->setStatus('Open');
$new->setUser($this->getUser());
$em->persist($new);
$em->flush();
}
return new JsonResponse(array('data' => $params));
}
return new Response('Error!', 400);
}

How tu use recaptcha google with phalcon framework

I'm still trying to add a recaptcha to my website, I want try the recaptcha from Google but I can't use it properly. Checked or not, my email is still sent.
I tried to understand the code of How to validate Google reCaptcha v2 using phalcon/volt forms?.
But i don't understand where are my problems and more over how can you create an element like
$recaptcha = new Check('recaptcha');
My controller implementation :
<?php
/**
* ContactController
*
* Allows to contact the staff using a contact form
*/
class ContactController extends ControllerBase
{
public function initialize()
{
$this->tag->setTitle('Contact');
parent::initialize();
}
public function indexAction()
{
$this->view->form = new ContactForm;
}
/**
* Saves the contact information in the database
*/
public function sendAction()
{
if ($this->request->isPost() != true) {
return $this->forward('contact/index');
}
$form = new ContactForm;
$contact = new Contact();
// Validate the form
$data = $this->request->getPost();
if (!$form->isValid($data, $contact)) {
foreach ($form->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
if ($contact->save() == false) {
foreach ($contact->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
$this->flash->success('Merci, nous vous contacterons très rapidement');
return $this->forward('index/index');
}
}
In my view i added :
<div class="g-recaptcha" data-sitekey="mypublickey0123456789"></div>
{{ form.messages('recaptcha') }}
But my problem is after : i create a new validator for the recaptcha like in How to validate Google reCaptcha v2 using phalcon/volt forms? :
use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
if (!$this->isValid($validation)) {
$message = $this->getOption('message');
if ($message) {
$validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
}
return false;
}
return true;
}
public function isValid($validation)
{
try {
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
$url = $config->'https://www.google.com/recaptcha/api/siteverify'
$data = ['secret' => $config->mysecretkey123456789
'response' => $value,
'remoteip' => $ip,
];
// Prepare POST request
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
],
];
// Make POST request and evaluate the response
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
}
So i don't know if tjis code is correct anyway, i have a problem too after that : how to create an object "recaptcha" in my form add
$recaptcha = new ?????('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'Please confirm that you are human'
]));
$this->add($recaptcha);
PS: I apologize because i'm a noob here and my mother tongue is not english, so if you don't understand me or want give me some advices to create a proper question, don't hesitate ^^
I've made a custom form element for recaptcha. Used it for many projects so far.
The form element class:
class Recaptcha extends \Phalcon\Forms\Element
{
public function render($attributes = null)
{
$html = '<script src="https://www.google.com/recaptcha/api.js?hl=en"></script>';
$html.= '<div class="g-recaptcha" data-sitekey="YOUR_PUBLIC_KEY"></div>';
return $html;
}
}
The recaptcha validator class:
use Phalcon\Validation\Validator;
use Phalcon\Validation\ValidatorInterface;
use Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
if (!$this->verify($value, $ip)) {
$validation->appendMessage(new Message($this->getOption('message'), $attribute, 'Recaptcha'));
return false;
}
return true;
}
protected function verify($value, $ip)
{
$params = [
'secret' => 'YOUR_PRIVATE_KEY',
'response' => $value,
'remoteip' => $ip
];
$response = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?' . http_build_query($params)));
return (bool)$response->success;
}
}
Using in your form class:
$recaptcha = new Recaptcha($name);
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'YOUR_RECAPTCHA_ERROR_MESSAGE'
]));
Note 1: You were almost there, you just missed to create custom form element (the first and last code piece from my example);
Note 2: Also there is a library in Github: https://github.com/fizzka/phalcon-recaptcha I have not used it, but few peeps at phalcon forum recommended it.

OctoberCMS Post Form

My form:
<form id="main-contact-form" name="contact-form" ata-request="onSend" data-request-success="alert('Message Sent')">
I cant seem to get a form to post; where do I place this file? Which file do I edit to make it send the form data fields to my email? I have already setup the backend mail settings:
function onSend()
{
// Collect input
$name = post('name');
$email = post('email');
$message = post('message');
// Submit form
$to = System\Models\MailSettings::get('sender_email');
$params = compact('name','email');
Mail::sendTo($to, 'temp.website::mail.newrequest', $params);
return true;
}
Please refer to the documentation: Plugin Components.
You can create a component (SomeForm.php)
<?php namespace My\Plugin\Components;
use Cms\Classes\ComponentBase;
class SomeForm extends ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Form',
'description' => 'Some form'
];
}
public function onSend()
{
// Collect input
$name = post('name');
$email = post('email');
$message = post('message');
// Submit form
$to = System\Models\MailSettings::get('sender_email');
$params = compact('name','email');
Mail::sendTo($to, 'temp.website::mail.newrequest', $params);
return true;
}
}
And then create a view for it (e.g. default.htm)
<form id="main-contact-form" name="contact-form" data-request="{{ __SELF__ }}::onSend" data-request-success="alert('Message Sent')">
...
</form>
Usage in pages/layouts:
[someForm]
==
{% component "someForm" %}
You goto the CMS section in your backend and paste that into the Code section of the default.htm layout. I already answered this question in the OctoberCMS.com forum. You can read about it here. Make sure that whatever form you use this on has a data-request="onSend" else it will not work. This is how it would ultimately look like...
You can add the Form's HTML either in your component partials directory, Theme's partial directory or just add it directly to any page / layout. It does not really matter.
Read more about including Partials
{% partial "contact-form.htm" %}
Or
{% partial __SELF__ ~ "::contact-form.htm" %} // reference to component's partial
October's AJAX framework requires the use of the JavaScript API or data attributes. It is fine how you are doing it in the example but forgot to add the Component's Name before the onSend Handler
data-request="SendEmails::onSend"
Where SendEmails = Component Name or Alias given in the page, if the form is in the component's partial just use {{ __SELF__ }}::onSend
or with the JavaScript API, just do :
$.request('onSend', {
data:{email:email, message:message, name:name},
success: function (data) {
//
},
error:function(e){
//
}
});
then in the component handling the request create a function onSend:
<?php namespace AuthorName\PluginName\Components;
use Cms\Classes\ComponentBase;
use Mail;
use Url;
use Input;
use Request;
use Response;
use ApplicationException;
use Validator;
use ValidationException;
class SendEmails extends ComponentBase
{
public function onSend()
{
if (Request::ajax()) {
try {
$data = post();
// Quick Validation rules for E-mail, Name & Message
if (!array_key_exists('email', $data)) {
$data['email'] = post('email');
}
if (!array_key_exists('norad', $data)) {
$data['message'] = post('message');
}
if (!array_key_exists('name', $data)) {
$data['name'] = post('name');
}
$rules = [
'email' => 'required|email|between:6,255',
'name' => 'required|between:4,255'
//..
];
$validation = Validator::make($data, $rules);
if ($validation->fails()) {
throw new ValidationException($validation);
}
// Check if E-mail Template Exists # "author.plugin::mail.templatename"
if (View::exists("author.plugin::mail.templatename")) {
Mail::send("author.plugin::mail.templatename", $data, function ($message) {
$message->from('noreply#yourdomain.com', 'Site Name');
$message->to($data['email'], $data['name']);
$message->subject('Subject here..');
});
// Handle Erros
if (count(Mail::failures()) > 0) {
echo "Failed to send Mail "; // Handle Failure
} else {
// Mail sent
echo "Mail Sent!"; // Handle Success
}
}
} catch (Exception $ex) {
throw $ex;
}
}
}
}

Categories