how can I set content of request symfony? - symfony

I generate manually request content of my form and want to set data like:
form[1][]=2&form[2][]=3&form[3][]=5&form[4][]=8&form[apply]=
The Symfony Request object has an getContent() method, but hasn't setContent().
How can I set content alternatively?

Found a solution which is dirty but seems to work for me. Just reinitialize the request.
$request->initialize(
$request->query,
$request->request,
$request->attributes,
$request->cookies,
$request->files,
$request->server,
'<your-content>'
);

Symfony 4 > version:
$request->initialize(
$request->query->all(),
$request->request->all(),
$request->attributes->all(),
$request->cookies->all(),
$request->files->all(),
$request->server->all(),
'your-content>'
);

Another option is via Request::create method.
Request::create(
'<uri>',
'<method>',
<parameters>,
<cookies>,
<files>,
<server>,
'<your-content>'
);
Source: HTTP foundation

Another dirty solution with usage of closures: https://www.php.net/manual/en/closure.call.php
$requestClosure = function() use ($decryptedJson) {
$this->content = $decryptedJson;
return $this;
};
$request = $requestClosure->call($request);
How this works:
in closure the $this becomes the request itself so it's possible to call private content,
calling return $this in closure returns the $request in context of which the call was made,

Related

Transform GET parameters to clean URL

I use Datatables on fronted to send GET parameters to my Silex application.
Datatables send GET parameters of that type:
champs_societes%5B%5D=naf&zone-geographique=ville&effectif%5B%5D=eff_1a9&effectif%5B%5D=eff_10a19&effectif
%5B%5D=eff_20a49&effectif%5B%5D=eff_plus5000&ca%5B%5D=10k-50k&ca%5B%5D=50k-100k&ca%5B%5D=1kk-2kk&ca%5B
%5D=2kk-5kk&champs_societes%5B%5D=capital_int&fondation%5Bmin%5D=&fondation%5Bmax%5D=&champs_societes
%5B%5D=siren&champs_societes%5B%5D=siret&champs_societes%5B%5D=nature&nature%5B%5D=Etablissement&champs_societes
%5B%5D=formejur&champs_societes%5B%5D=emailg&champs_contacts%5B%5D=emailn&ac_formejur=Artisan-Commer
%C3%A7ant%2CBanque+Populaire%2FLoi+Mars+1917%2CCoop.+%C3%80+Responsabilit%C3%A9+Limit%C3%A9e&ac_naf=0113Z
%2C0121Z%2C0126Z%2C0130Z&ac_departements=14%2C50%2C61%2C68%2C03&ac_villes=77330%2C77680%2C77340&ac_fonction
=Assistant%2CCharg%C3%A9+D'Affaires%2CContr%C3%B4leur+De+Gestion%2CDirecteur+%2F+Responsable
I there a way to genereate a clean URL from this chain ? Ideally by using the Symfony/Silex routing.
Thanks for help
EDIT
I get the GET params above with Request:
$app->post('/ajax/formprocess', function (Request $request) use ($app) {
$df = new Filtres( $request->request->get('dataForm') );
$filtroAdd = $df->getRequest();
I would try with Request class first
Request class from HttpFoundation component (default in Symfony, not sure about Silex as I never used it)
/**
* #param \Symfony\Component\HttpFoundation\Request $request
*/
public function someAction(Request $request)
{
$request->getSchemeAndHttpHost();
$request->getBasePath();
$request->getQueryString(); // this will be the most helpful in your case
// access what you need and build normalized url
}
You should be able to build clean normalized url
Edit, solution for parsing query parameter string to array
$queryParameters = 'query parameters as string to be parsed';
$output = [];
parse_str($queryParameters, $queryParameters);
print_r($queryParameters);
http://php.net/manual/en/function.parse-str.php

CSRF Token from the controller

I have a controller getting a form posted.
public function myPostAction(Request $request)
{
$form = $this->createForm('my_form', $my_object);
$form->handleRequest($request);
#...
I can see my CSRF token posted as parameter
my_form[_token] => lH38HTm5P0Cv3TOc4-9xi2COx-cZ670mpJ_36gR8ccI
I simply need to read it
$form->get('_token')
This tells me
Child "_token" does not exist.
How can I get this token ?
Here is the workaround I'm going to use meanwhile:
$token = $request->get($form->getName())['_token'];
I also noticed by chance that the intention used to generate the token is the form name
$csrf = $this->get('form.csrf_provider');
$intention = $form->getName();
$token = $csrf->generateCsrfToken($intention);
Like #Pierre de LESPINAY said, it is possible to do it by retrieving Token Manager service.
This service can also be injected in your constructor like that :
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
...
public function __construct(CsrfTokenManagerInterface $tokenManager)
{
$this->tokenManager = $tokenManager;
}
And used later like previously demonstrated :
$token = $this->tokenManager->getToken('myformname')->getValue();
You can get it with:
$request->request->get('my_form[_token]');
If you didn't disable CSRF-protection it will be applied and validated automatically and you don't need to check it by self.

Symfony2 why does forward nest request objects?

When I do a forward() in a controller, I lose my route and route_parameters.
When I have ParentAction, that does a forward to ChildAction. In Childaction I do return $this->render('myTemplate.html.twig', array()); then the request attributes get nested!
So when the template gets rendered, instead of $request['attributes']['_route_parameters'] I get $request['attributes']['request']['attributes']['_route_parameters'].
Although in ChildAction, when I do a $this->getRequest(); the hierarchie is normal.
Is this a bug, or am I doing something wrong?
The reason is that symfony doesn't assume you have the same route parameters.
So when you forward you need to re-supply the route parameters required by the new route even if they are the same.
(Incidentally you must also provide any query parameters for the new route.)
public function indexAction($param)
{
return $this->forward(
'AppBundle\\Controller\\DefaultController::otherAction',
array("someOtherParam" => $param),
$request->query->all() // Causes query string params to be copied
);
}
// This route has a different parameter.
public function otherAction($someOtherParam) ...
A possible solution would be to pass your Request as second parameter when forwarding.
$response = $this->forward('MyBundle:MyController:myAction', array('request' => $request));
Also, as forward is just a shortcut for core Symfony2 functionality, this may probably help.
In my case following code helped:
$subRequest = $this->container->get('request')->duplicate(
array(),
null,
array('topicId' => $topicId,'_controller' => 'SomeBundle:Topic:close'));
return $this->container->get('http_kernel')
->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
"Topic" is TopicController and "close" is closeAction

Symfony 2 forwarding requests to another controller with changed content

I want to forward a request to another controller using something like this:
$controller_response = $this->forward( 'MyBundle:Clients:getClients' );
That works fine, but I need to updated the request to have different content, I can't work out what method I should be using, the following don't work:
$request->content->set('new content');
$request->set('content', 'new content');
$request->setContent('new content');
Is it even possible to do this? If not I could create a brand new request and add it in as an argument, I'd rather avoid doing that though if possible.
You can alter the Response content with the setContent method.
$response->setContent('<html>Hello</html>');
You can also alter the request
$request->request->set('key', 'value');
$request->query->set('key', 'value');
$request = Request::createFromGlobals();
$newContent = json_decode($request->getContent(), true);
$request->initialize($request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all(), $newContent);
Unfortunately, there doesn't seem to be a great way of doing it, but this worked for me.

How do I create a functional test which includes a POST to a page with parameters?

I've read the documentation from Symfony2 but it doesn't seem to work. Here's my functional test:
public function testSearch()
{
$client = static::createClient();
$crawler = $client->request('POST', '/search/results', array('term' => 'Carteron'));
$this->assertTrue($crawler->filter('html:contains("Carteron")')->count() > 0);
$this->assertTrue($crawler->filter('html:contains("Auctions")')->count() > 0);
}
In my controller the "term" parameter is null when this request comes in. However, search works just fine when I perform it on the site, so I know its a problem with setting up the test.
I had the same problem, neither $request->query nor $request->request worked. Both did the same for me: it returned $default, not the given $parameters (Symfony 2.3).
Same behaviour as chris, in normal web browsers it works. I fixed this by replacing:
public function searchResultsAction($name)
{
$request = Request::createFromGlobals();
$term = trim($request->request->get('term'));
return $this->searchResultsWithTermAction($term);
}
With:
public function searchResultsAction(Request $request, $name)
{
// do NOT overwrite $request, we got it as parameter
//$request = Request::createFromGlobals();
$term = trim($request->request->get('term'));
return $this->searchResultsWithTermAction($term);
}
So createFromGlobals() does only work if $_GET and $_POST are set. Shich is not the case if you use the symfony test client. you have to add the $request parameter to the action.
(I used $name as a GET parameter in my routing)
I've never gotten an answer to this, but have implemented a work around that seems to work for my testing purposes. I'd love to hear feedback or get a real answers to this questions.
What I've done is create a 2nd route for the purposes of testing.
In real usage the uri would be /search/results?term=searchtermhere
For the purposes of testing, this didn't work. I could never get access to the term value when invoked via the automated test.
So what I've done is create a 2nd route just for testing which has a uri of /search/results/{searchtermhere}.
Then my action class used for a real search would call down to another function and pass the term to the function:
public function searchResultsAction()
{
$request = Request::createFromGlobals();
$term = trim($request->request->get('term'));
return $this->searchResultsWithTermAction($term);
}
So my functional tests would excersize searchResultsWithTermAction(), so the only code coverage I'm missing from this workaround is the extraction of the term from the request.
I don't know if anyone is still searching for an answer to this, but basically the problem is that you are looking in the wrong place for the parameter.
For your example you would need:
$term = trim($request->query->get('term'));
Hope this helps!

Resources