Here follows my problem. In a Symfony2.1 controller I receive an Ajax call. If I use the Request object I'm not able to get the sent param. If I use the PHP _REQUEST object the param is found!
I can confirm that the request is XHR, if it matters.
Here is my code:
public function savedataAction(Request $request){
if($request->isXmlHttpRequest())
echo 'Ajax Call';
$param1 = $request->request->get('myParam'); // Nothing is returned, but $request is obviosly not null
$param2 = $_REQUEST['myParam']; // The value is given
....
}
Any idea?
PS: If helps, notice that the AJAX call is sent by the file uploader jQuery plugin provided by Valums.
Normally its:
// retrieve GET and POST variables respectively
$request->query->get('foo');
$request->request->get('bar', 'default value if bar does not exist');
Look here are the fundamentels.
http://symfony.com/doc/current/book/http_fundamentals.html
Edit:
$request in your case is only filled when you send the form from the Symfony2 site. It is possible, that the CSRF protection block the request.
Try this in your controller to get the Request object:
$request = $this->get('request');
http://symfony2forum.org/threads/5-Using-Symfony2-jQuery-and-Ajax
Related
I have middleware where I am assigning http headers to the request/response.
$response = $next($request)->header('x-robots-tag', 'noindex', false);
In the middleware, I can also apply this line after executing the above, to get the value I had just set...
echo $response->headers->get('x-robots-tag');
But, I want to access this outside of middleware but I'm not sure how to get the Response object back to achieve this.
How can I get the $response object from within my controller?
$response = \WHAT\GOES\HERE?;
echo $response->headers->get('x-robots-tag');
I can't seem to figure out what to put in the \WHAT\GOES\HERE part to access the response object again.
Update #1:
Still unresolved, but part of the problem appears to be that in order to add the header tags to the Response object within middleware requires $next($request) and the $next Closure causes the response processing to be done after the controller code has executed. So even though I'm not sure how to target the Response object from within the controller, it doesn't look like it would have the header tag assigned until afterward anyway.
I could set the headers directly in PHP in the middleware with
public function handle($request, Closure $next /*, $tags */)
{
$tags = array_except(func_get_args(), [0,1]);
if( count($tags) > 0){
header('x-robots-tag: ' . implode(', ', $tags));
}
return $next($request);
}
and then access it in the controller by pulling it out of the headers_list() but that's not ideal and working outside of the laravel ways...
For context, the idea was to assign middleware to routes and with the middleware assign the x-robots-tag response header with the desired attributes. noindex, nofollow, whatever... Then I was hoping to capture this and populate the equivalent meta tags accordingly using the data provided to the x-robots-tag. A two-birds with one stone sort of approach, but it has proven more difficult than I had expected.
I have such a route in my routes/web.php
Route::resource('/api/surveys', 'SurveyController');
As documentation says, it creates all needed routes for API. This is a function, that gets executed when I go for /api/surveys route:
public function index()
{
$request = request();
if(!$request->hasHeader('token')) {
return "No auth token found.";
}
$tokenCheck = $this->userService->isTokenValid($request->header('token'));
if($tokenCheck !== true) {
return $tokenCheck;
}
return $this->surveyService->all();
}
What it does, it checks if token header parameter is set, if not, it returns an error, if yes, it checks if token is valid and etc. if everything is OK, it should return surveys from database.
public function surveys() {
$request = \Request::create('/api/surveys', 'GET');
$request->headers->set('Accept', 'application/json');
$request->headers->set('token', \Cookie::get('token'));
$response = \Route::dispatch($request);
print_r('<pre>');
print_r($response);
print_r('</pre>');
}
I have a website, that should use that API I just created to get all survey records. I create a new request object, set header "token" with token I get from a cookie and then try to dispatch and get a response. But the problem is that everytime I get "No auth token found." error. That means $request->hasHeader('token') returns false, even tough I set it here in my request. If I print_r $request->all() in Restful controller, I get an empty array.
I tried Postman to access this API with token parameter, and it works fine in postman, but here, it seems that Request disappears while it travels to API controller.
What I did wrong here?
When you manually create a request and dispatch it, that works to get the routing to call the correct controller, however that does not affect the request that is bound in the container.
When your "fake" request is handled by the api controller, the request that it pulls out of the container is the original "real" request that was made by the user.
Instead of dispatching the route with your new request, you will need to app()->handle($request) the new request. This, however, will completely replace the original "real" request with your new "fake" request, so everything from the original request will be lost.
Having said all that, this method of consuming your own api is discouraged, even by Taylor. You can read his comment on this Github issue. So, consuming your own api like this may work, but you may also run into some other unforeseen issues.
The more appropriate solution would be to extract out the logic called by the api routes to another class, and then call that extracted logic from both your api routes and your web routes.
When the user clicks add to cart I create an new cart and add the product to the cookie of the user. But how do I set the cookie on an ajax response. Im trying:
//set the values for the view make
$cartId = 'someval i set earlyer'
$cookie = Cookie::forever('cartid', $cartId);
$currentCart = Cart::findOrFail($cartId);
$items = CartItem::where('cart_id','=',$currentCart->id)->get();
//this function also check the $request on a valid cookie
$total = $this->calculateCartTotal($request);
return Response::json(View::make('front.cart.render',compact('items', 'total'))->withCookie($cookie)->render());
But the value is never set, I tryd refreshing the page but there is still no cookie for cartid. How can I set a cookie for an ajax reponse
Try this:
return Response::json(
View::make('front.cart.render',compact('items', 'total'))->render()
)->withCookie($cookie);
rendor belongs to View
withCookie belongs to Response
Check Response headers.
Set-Cookie:cartid=...
My application uses ajax to request data. I'm using Symfony2, and when the session expires and I make a request with ajax, the login form is shown inside the main area on my application, and not as another view as should be. How can solve this problem. Thanks
I would suggest creating event listener which will be listening for every request:
services.yml:
your_request_listener:
class: Acme\AppBundle\EventListener\RequestListener
arguments: [#security.token_storage]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onRequest }
In this event listener I would check for type of request so this would be only Ajax request listener. When request is ajax type then I would check if session has expired - if so, I would create response which will be valid response for ajax request (i.e. JsonResponse) and set this response to be sent to user.
class RequestListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->isXmlHttpRequest()) {
return; //we dismiss requests other than ajax
}
//now you check if user is authenticated/session expired/whatever you need
$token = $this->tokenStorage->getToken();
if ($token === null) {
//now you create response which you would expect in your js doing ajax, for example JsonResponse
$response = new JsonResponse(); //you should give some content here
$event->setResponse($response); //now you override response which will be sent to user
}
}
}
You could use an entry point in which you verify if the request is an AJAX request. If yes, you return a JSON response with 401 HTTP status code. Then in JS code you verify the HTTP status code. If 401, then redirect to login page.
You can read my post here with the complete solution (see my own answer to my own question). This solution is based on this excellent post.
Not sure if SFDebug is any help in this situation. I am making an ajax post using jQuery. Which retrieves JSON data in my action URL and then makes a call to the Model method that executes the action. The part until my action URL, and the jQuery call to it work fine. With the data transmitted from the client to the server well received and no errors being made.
It is the part where it calls the method on the Model that is failing. My jQuery method looks like this:
$.post(url, jsonData, function(servermsg) { console.log(servermsg); }) ;
My server action is like this
public function executeMyAjaxRequest(sfWebRequest $request)
{
if($request->isXmlHttpRequest())
{
// process whatever
$servermsg = Doctrine_Core::getTable('table')->addDataToTable($dataArray);
return $this->renderText($servermsg);
}
return false;
}
The method of concern in the Table.class.php file looks like this:
public function addDataToTable($dataArray)
{
// process $dataArray and retrieve the necessary data
$data = new Data();
$data->field = $dataArray['field'];
.
.
.
$data->save();
return $data->id ;
}
The method fails up here in the model, when renderText in the action is returned and logged into the console, it returns the HTMl for SFDEBUG. Which indicates that it failed.
If this was not an Ajax call, I could debug it by seeing what the model method spat out, but this is a little tedious with Ajax in the mix.
Not looking for exact answers here, but more on how I can approach debugging ajax requests in a symfony environment, so if there are suggestions on how I can debug this, that would be great.
You must send cookie with session ide key via ajax
(Assuming you have XDEBUG configured on the server)
In order to trigger a debug session by an AJAX request you have to somehow make that request to send additional URL parameter XDEBUG_SESSION_START=1. For your example:
$.post(url + '?XDEBUG_SESSION_START=1', jsonData, function(servermsg) { console.log(servermsg); }) ;
You can also trigger it via cookie, but appending URL parameter usually easier.