Symfony Serializer of DateTime Response String - symfony

When attempting to perform a doctrine query and serialze it to json (not using JSM, using the symfony serializer) I get the following in the json:
""due":{"timezone":{"name":"Europe/Berlin","transitions":[{"ts":-2147483648,"time":"1901-12-13T20:45:52+0000","offset":3208,"isdst":false,"abbr":"LMT"},{"ts":-2147483648,"time":"1901-12-13T20:45:52+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-1693706400,"time":"1916-04-30T22:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-1680483600,"time":"1916-09-30T23:00:00+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-1663455600,"time":"1917-04-16T01:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-1650150000,"time":"1917-09-17T01:00:00+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-1632006000,"time":"1918-04-15T01:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-1618700400,"time":"1918-09-16T01:00:00+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-938905200,"time":"1940-04-01T01:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-857257200,"time":"1942-11-02T01:00:00+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-844556400,"time":"1943-03-29T01:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-828226800,"time":"1943-10-04T01:00:00+0000","offset":3600,"isdst":false,"abbr":"CET"},{"ts":-812502000,"time":"1944-04-03T01:00:00+0000","offset":7200,"isdst":true,"abbr":"CEST"},{"ts":-796777200,"time":"1944-10-02T01:00:00+0000","offset":3600,"
When storing the due date, the timezone is saved and there is an additional timezone field stored. Is there a way to pull the date in a specific format or specify the timezone to use when retrieving?
public function blahAction(Request $request)
{
$currentUser = $this->getUser();
$em = $this->getDoctrine()->getManager();
$blahs = $em->getRepository('AppBundle:blah')->findAllByStatus($currentUser,'TODO');
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizer = array(new ObjectNormalizer());
$serializer = new Serializer($normalizer, $encoders);
$response = new Response($serializer->serialize($blahs, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
}

You have 2 ways to get RFC3339 Datetime format ...
Option 1:
Add DateTimeNormalizer as normalizer. An example is https://symfony.com/doc/current/components/serializer.html#recursive-denormalization-and-type-safety.
Change
$normalizer = array(new ObjectNormalizer());
by
$normalizer = array(new DateTimeNormalizer(), new ObjectNormalizer());
Option 2
More simple is using "serializer" container service ... your code will look like ...
public function blahAction(Request $request)
{
$currentUser = $this->getUser();
$em = $this->getDoctrine()->getManager();
$blahs = $em->getRepository('AppBundle:blah')->findAllByStatus($currentUser,'TODO');
$response = new Response($this->get('serializer')->serialize($blahs, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
.. or, if your prefer autowiring way (this code is unchecked)
public function blahAction(Request $request, \Symfony\Component\Serializer\SerializerInterface $serializer)
{
$currentUser = $this->getUser();
$em = $this->getDoctrine()->getManager();
$blahs = $em->getRepository('AppBundle:blah')->findAllByStatus($currentUser,'TODO');
$response = new Response($serializer->serialize($blahs, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
}

In Symfony 5.1 it's recomended to add a callback function to specify datetime field format.For example:
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
$dateCallback = function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = []) {
return $innerObject instanceof \DateTime ? $innerObject->format(\DateTime::ISO8601) : '';
};
$defaultContext = [
AbstractNormalizer::CALLBACKS => [
'created_at' => $dateCallback,
'updated_at' => $dateCallback
],
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER =>
function ($articles, $format, $context) {
return $articles->getId();
}
];
$encoders = [new JsonEncoder()];
$normalizers = [
new ObjectNormalizer(null, null, null,
null, null, null,
$defaultContext)
];
$serializer = new Serializer(
$normalizers, $encoders
);
$articles = $serializer->serialize($articles, 'json');
Where $articles = array of App\Entity\Article objects
You can specify datetime format you need in your callback function.

Another option is to pass arguments to the default DateTimeNormalizer in services.yaml:
Symfony\Component\Serializer\Normalizer\DateTimeNormalizer:
arguments:
$defaultContext:
datetime_format: 'Y-m-d\TH:i:s.v\Z'

Related

How to pass variables to a RedirectResponse

I've a variable name $email but I don't know how to send it to dashController.php:
$action = $this->client->auth($username, $password);
if (isset($action->success) && $action->success){
$email = $action->data->email;
$response = new RedirectResponse('/dash');
$cookie = new Cookie('JWT', $action->data->jwt->token, new \DateTime($action->data->jwt->expires_at));
$response->headers->setCookie($cookie);
return $response;
}
in dashController.php
class dashController extends authContainer {
#[Route("/dash", "dashboard")]
public function indexAction(): Response
{
return $this->render('dash.twig', [
'email' => ...
]);
}}
If your class inherit from Symfony AbstractController class, you can use the
redirectToRoute method helper. Your code will be like :
if (isset($action->success) && $action->success){
$email = $action->data->email;
$response = $this->redirectToRoute('dashboard');
$cookie = new Cookie('JWT', $action->data->jwt->token, new \DateTime($action->data->jwt->expires_at));
$response->headers->setCookie($cookie);
return $response;
}

Symfony Serializer Component AbstractNormalizer::CALLBACKS denormalize

I am trying to use Serialize with callbacks like in https://symfony.com/doc/current/components/serializer.html#using-callbacks-to-serialize-properties-with-object-instances . But it doesn't seem to go into the callback. I can ignore attributes with 'IGNORED_ATTRIBUTES' just fine, just CALLBACKS not working. What could I be doing wrong?
$dateCallback = function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = []) {
dump('foo');
return 'faa';
};
$defaultContext = [
AbstractNormalizer::CALLBACKS => [
'order_date' => $dateCallback,
]
];
$normalizer = new ObjectNormalizer(null, null, null, null, null, null, $defaultContext);
$serializer = new Serializer([$normalizer], []);
$order = $serializer->denormalize($data, Orderform::class, 'array');
The data is a simple array.
$data = ['order_date' => '2020-07-07',
'order_number' => '123'];
I would expect the $dateCallback to be called. But it doesn't seem to do that. The Orderform entity is getting populated but not with the value I would expect from the callback.
I tried making all this with json and xml too, since array doesn't show up in the documentation (but it works except for the callback)
Symfony 4.4
I didn't debug your code, instead I made a working version of the deserialization example based on the docs, hope it's serve as guide:
<?php
include 'vendor/autoload.php';
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Serializer;
//
//Inializing the Serializer, enconders and callbacks
//
$encoders = [new XmlEncoder(), new JsonEncoder()];
$dateCallback = function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = []) {
return $innerObject instanceof \DateTime ? $innerObject->format('Y-m-d H:i:sP') : '';
};
$defaultContext = [
AbstractNormalizer::CALLBACKS => [
'createdAt' => $dateCallback,
]
];
$normalizer = [new ObjectNormalizer(null, null, null, null, null, null, $defaultContext)];
$serializer = new Serializer($normalizer, $encoders);
//
//Creating Object Person that will be serialized
//
$person = new Person();
$person->setName('foo');
$person->setAge(99);
$person->setSportsperson(false);
$person->setCreatedAt(new \DateTime());
$arrayContent = $serializer->serialize($person, 'json');
// $arrayContent contains ["name" => "foo","age" => 99,"sportsperson" => false,"createdAt" => null]
//print_r($arrayContent); // or return it in a Response
// Lets deserialize it
$desrializedPerson = $serializer->deserialize($arrayContent, Person::class, 'json');
var_dump($desrializedPerson);
//
// Foo Bar stuff
//
// Entity Person declaration
class Person
{
private $age;
private $name;
private $sportsperson;
private $createdAt;
// Getters
public function getName()
{
return $this->name;
}
public function getAge()
{
return $this->age;
}
public function getCreatedAt()
{
return $this->createdAt;
}
// Issers
public function isSportsperson()
{
return $this->sportsperson;
}
// Setters
public function setName($name)
{
$this->name = $name;
}
public function setAge($age)
{
$this->age = $age;
}
public function setSportsperson($sportsperson)
{
$this->sportsperson = $sportsperson;
}
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
}
}

undefined variable company in zendframework 3

undefined variable company
undefined variable i m getting error
public function addPolicyAction()
{
if ($this->sessionContainer->empId == "")
{
return $this->redirect()->toRoute('admin_user_login');
}
$ouCode = $this->sessionContainer->ouCode;
$langCode = $this->sessionContainer->langCode;
$empId = $this->sessionContainer->empId;
$arrLabel = array('company_policy','pdid','pdname','file_name','active');
$commonTransalationLabel = $this->commonTranslation->getCommonTransactionInformation($arrLabel, $langCode);
$companyPolicyForm = new CompanyPolicyForm($commonTransalationLabel);
if ($this->getRequest()->isPost()) {
// $data = $this->params()->fromPost();
$request = $this->getRequest();
$data = array_merge_recursive(
$request->getPost()->toArray(), $request->getFiles()->toArray()
);
$data['ouCode'] = $ouCode;
$data['langCode'] = $langCode;
$companyPolicyForm->setData($data);
$chkValidate = $this->hrCompanypolicy->findBy([
'ouCode' => $this->sessionContainer->ouCode,
'langCode' => $this->sessionContainer->langCode
]);
if ($companyPolicyForm->isValid()) {
$data = $companyPolicyForm->getData();
if(isset($_POST['Submit'])){
$name = $_FILES['fileName']['name'];
$target_dir = 'public/media/policy_photos/';
$target_file = $target_dir . basename($_FILES["fileName"]["name"]);
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$extensions_arr = array("jpg","jpeg","png","gif");
if( in_array($imageFileType,$extensions_arr) ){
move_uploaded_file($_FILES['fileName']['tmp_name'],$target_dir.$name);
}
}
$company = $this->companyPolicyManager->add($data,$ouCode, $langCode,$empId);
$cpData = $this->companyPolicyManager->getcpDataBycpId($data,$ouCode,$langCode);
$companyPolicyForm->buildCompanyPolicyData($cpData);
$this->flashMessenger()->addMessage($commonTransalationLabel['success_message']);
}
}
return new ViewModel([
'form' => $company,
'companypolicydata' => $cpData,
'label' => $commonTransalationLabel,
'form' => $companyPolicyForm,
'flashMessages' => $this->flashMessenger()->getMessages()
]);
}
i want to remove undefined variable in zendframework 3
i m using zendframework 3 and getting undefined variable in zendframework 3 what is the issue in the code ?
How to defined a variable in zendframework 3 i want to solve the issue
Problem is that you're using the $company variable in your return new ViewModel statement, but you only create the variable when the entire form is valid.
Instead of what you're doing, make sure that you provide a Form instance (whichever you need, e.g. CompanyForm) to your controller via the Factory. Then have your function along the lines like below (I've removed some error checking):
public function editAction()
{
$id = $this->params()->fromRoute('id', null);
/** #var Company $entity */
$entity = $this->getObjectManager()->getRepository(Company::class)->find($id);
/** #var CompanyForm $form */
$form = $this->getForm();
$form->bind($entity);
/** #var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
/** #var Company $entity */
$entity = $form->getObject();
$this->getObjectManager()->persist($entity);
try {
$this->getObjectManager()->flush();
} catch (Exception $e) {
throw new Exception('Could not save. Error was thrown, details: ', $e->getMessage());
}
return $this->redirectToRoute('companies/view', ['id' => $entity->getId()]);
}
}
return [
'form' => $form,
];
}

Array Collection persistence on symfony2

i'm using a event listener on the submit of a form where, i need to catch a xml file, open it and extract his contents, put it on an entity and add that to a collection from other entity.
right now this is works:
$builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event){
$entity = $event->getData();
if($entity){
$parent = $event->getForm()->getParent()->getData();
$gpx = $entity['gpx'];
if($gpx){
$xmlGpx = simplexml_load_file($gpx);
foreach ($xmlGpx->wpt as $pt) {
$point = new MonitoringPoint();
$point->setPoint(new \CrEOF\Spatial\PHP\Types\Geometry\Point((string) $pt['lat'], (string) $pt['lon']));
$point->setAltitude((float) $pt->ele);
$point->setDate(($pt->time->count() ? new \DateTime((string)$pt->time) : null ));
$point->setAccuracy((float) $pt->hdop);
$parent->addMonitoringPoint($point);
}
$fileName = $gpx->getClientOriginalName();
$directory = __DIR__.'/../../../../web/uploads/';
$date = new \DateTime();
$newFileName = md5($gpx->getClientOriginalName().$date->getTimestamp());
$gpx->move($directory, $fileName);
$fs = new Filesystem();
$fs->rename($directory.$fileName, $directory.$newFileName.'.gpx');
$parent->setGpx($newFileName.'.gpx');
}
}
});
$parent is an instance of Monitoring, if i open $parent i will see that the $point vars has been added on the collection monitoringPoints of the variable, and the gpx too.
but then i go so see the entity right before been persisted, inside newAction
$entity = new Monitoring($params);
$form = $this->createForm(new MonitoringType(), $entity, array(
'action' => $this->generateUrl('my_route'),
'method' => 'POST',
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
dump($entity);die;
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
}
and the collection is empty! but the gpx attribute contains the right value.
does the collection gets reseted?
i had to pass the points in to an array within the session, still think that was not the best option, but worked
$array = [];
foreach ($xmlGpx->wpt as $pt) {
$point = new MonitoringPoint();
$point->setPoint(new \CrEOF\Spatial\PHP\Types\Geometry\Point((string) $pt['lat'], (string) $pt['lon']));
$point->setAltitude((float) $pt->ele);
$point->setDate(($pt->time->count() ? new \DateTime((string)$pt->time) : null ));
$point->setAccuracy((float) $pt->hdop);
$point->setMonitoring($parent);
array_push($array, $point);
}
$session = new Session();
$session->getFlashBag()->add('array', $array);
in the newAction:
$em = $this->getDoctrine()->getManager();
$session = new Session();
$array = $session->getFlashBag()->get('array');
foreach($array[0] as $point) {
$point->setMonitoring($entity);
$entity->addMonitoringPoint($point);
}
$em->persist($entity);
$em->flush();
dont know why the array got reseted when it comes to the controller, cause i had setted the points in the entity during the submit

FOSUserBundle fetch data from the form in the listener

I'm trying to insert a data passed in the form (e-mail) in the response that I create in the listener to ensure that the response is a json object.
I can not take the form data from 'event in any way ..
There is a solution to what I want?
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess',
);
}
public function onProfileEditSuccess(FormEvent $event)
{
$response = new Response();
$output = array('success' => true, 'new_mail' => $event); //event return empty object
$response->headers->set('Content-Type', 'application/json');
$response->setContent(json_encode($output));
$event->setResponse($response);
}
I tried to listen to the event COMPLETED, but does not make me change response!
You can grab form from $event object with $event->getForm() in PROFILE_EDIT_SUCCESS event.
in FOS\UserBundle\Controller\ProfileController:
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event);
To access email
$form = $event->getForm();
$email = $form['email']->getData();

Resources