Good mornings all, I make a POST request with the Type field (tinyint) in my unit tests. I give it the value FALSE. When I check in the database, the Type field is 1 so TRUE. I don't know how this is possible and it happens to me several times on my unit tests.
The POST request with the column type :
"title" => "Une fausse formation"
"number" => "faux-numer0"
"organism" => "Un faux organisme"
"type" => false
"status" => 0
"costs" => array:2 [
0 => array:4 [
"title" => "Frais pédagogiques"
"type" => 0
"amount" => 102.5
"isCollective" => true
]
1 => array:4 [
"title" => "Frais de transport"
"type" => 0
"amount" => 10
"isCollective" => true
]
]
"sessions" => []
"visibility" => 2
]
the row that was inserted into the table :
"title" => "Une fausse formation"
"number" => "faux-numer0"
"type" => true
"status" => 0
"organism" => "Un faux organisme"
"visibility" => array:2 [
"establishment" => []
"employees" => array:1 [
0 => []
]
]
"costs" => array:2 [
0 => array:4 [
"title" => "Frais pédagogiques"
"type" => 0
"amount" => "102.50"
"is_collective" => true
]
1 => array:4 [
"title" => "Frais de transport"
"type" => 0
"amount" => "10.00"
"is_collective" => true
]
]
]
Here is my field declaration in the Entity:
/**
* @var bool
*
* @ORM\Column(name="`type`", type="boolean")
* @Serializer\Groups({"get_employee", "get_training", "get_trainings", "get_training_user", "get_training_session"})
*/
private $type;
This is my POST TEST request :
public function testPostTraining($user, $data, $result)
{
$this->authUser($user[0], $user[1], $user[2]);
// Retrieve created visibility id
$visibilityData = array(
'establishment' => 1
);
$this->apiCall('POST', '/api/secure/trainings/visibilities.json', $visibilityData);
// Check status code (visibility created)
$this->assertEquals(201, $this->client->getResponse()->getStatusCode());
$data['visibility'] = json_decode($this->client->getResponse()->getContent(), true)['id'];
$this->apiCall('POST', '/api/secure/trainings.json', $data);
// Check status code (created)
$this->assertEquals(201, $this->client->getResponse()->getStatusCode());
// Check if id is returned
$response = json_decode($this->client->getResponse()->getContent(), true);
$this->assertArrayHasKey('id', $response);
//$this->assertInternalType('integer', $response['id']);
$this->assertEquals('integer', gettype($response['id']));
// Check data
$this->apiCall('GET', '/api/secure/trainings/'.$response['id'].'.json');
$training = json_decode($this->client->getResponse()->getContent(), true);
// Remove ids
$this->recursive_unset($training, 'id');
$this->recursive_unset($training, 'created_at');
$this->recursive_unset($training, 'updated_at');
$this->recursive_unset($training['visibility']['establishment'], 'roles');
// Check content
$this->assertEquals($training, $result);
}
The data of the post request :
$data_two= array(
'title' => 'Une vrai formation',
'number' => 'vrai-numer0',
'organism' => 'Un vrai organisme',
'type' => false,
'status' => 1,
'costs' => array(
array(
'title' => 'Frais pédagogiques',
'type' => 1,
'amount' => 10.25,
'isCollective' => true
),
),
'sessions' => array()
);
This is the POST controller :
public function postAction(Request $request)
{
try {
if (($employee = $this->getEmployee()) == null)
return FOSView::create(null, Response::HTTP_FORBIDDEN);
$manager = $this->getTrainingManager();
$training = $manager->createTraining();
$form = $this->createForm(TrainingType::class, $training, array(
'method' => $request->getMethod()
));
$this->removeExtraFields($request, $form);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->denyAccessUnlessGranted('create', $training);
$manager->save($training);
$dispatcher = $this->eventDisptacher;
$event = new TrainingActionEvent($training, $this->getEmployee(), $request->getMethod());
$dispatcher->dispatch($event,TrainingActionEvent::TRAINING_ACTION);
return $training;
}
} catch(\Exception $e) {
return FOSView::create($e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
}
return FOSView::create($form, Response::HTTP_BAD_REQUEST);
}
CodePudding user response:
I assume you are using CheckboxType
for the boolean field in your form definition.
If you take a look at the class, you can see that a BooleanToStringTransformer
is used to convert the submitted value to a real boolean.
Only the configured value
(default: '1'
) is converted to true
, and the configured false_values
(default: [null]
) are converted to false
.
Going through the documentation in the FOSRestBundle
, this issue has been resolved already: https://github.com/FriendsOfSymfony/FOSRestBundle/pull/883
See: https://fosrestbundle.readthedocs.io/en/3.x/body_listener.html#decoders
If you want to be able to use a checkbox within a form and have true and false values (without any issue) you have to use:
fos_rest.decoder.jsontoform
CodePudding user response:
I finally found the solution. The POST requests in my unit tests were incorrectly formatted.
Before :
private function apiCall($method, $endpoint, $parameters=array())
{
$this->client->request($method, $endpoint, $parameters);
return json_decode($this->client->getResponse()->getContent(), true);
}
After :
private function apiPostCall($method, $endpoint, $parameters=array())
{
$this->client->request(
$method,
$endpoint,
[],
[],
['CONTENT_TYPE' => 'application/json'],
json_encode($parameters)
);
return json_decode($this->client->getResponse()->getContent(),true);
}