У меня есть контроллер в Symfony2 (2.8) для событий календаря, но у вас есть некоторые проблемы с полем DateTime. Контроллер является только контроллером api, но использует тот же объект и форму, что и «обычный» контроллер.API-контроллер для создания новых объектов с DateTime
В вызовах Ajax я получаю ответ, что значение поля даты недействительно. Я попытался прочитать его и обнаружил, что мне нужно создать DataTransformer, чтобы преобразовать его в объект DateTime и наоборот. Когда я добавляю DataTransformer
к форме события календаря, «нормальный» создает разрывы. Кажется, что он дважды преобразует значение?
Извлечение трансформатора модели и «нормальное» создание работ, но Ajax продолжает возвращать недействительные поля времени начала и окончания даты.
Я был бы очень признателен, если бы кто-то мог указать мне в правильном направлении.
Ресурсы Я прочитал: https://tech.enekochan.com/en/2015/11/21/symfony-forms-and-bootstrap-datetimepicker/ http://symfony.com/doc/current/cookbook/form/data_transformers.html и несколько больше, я не мог найти прямо сейчас.
Bellow - мой код. Пожалуйста, дайте мне знать, если я напишу дополнительную информацию.
Спасибо за ваше время.
Мой CalendarEvent объект выглядит следующим образом:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\CalendarEventRepository")
* @ORM\Table(name="calendar_events")
*/
class CalendarEvent
{
/**
* @ORM\Id
* @ORM\Column(type="integer", name="id")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, nullable=true, name="name")
*/
private $name;
/**
* @ORM\Column(type="datetime", nullable=true, name="start")
*/
private $start;
/**
* @ORM\Column(type="datetime", nullable=true, name="end")
*/
private $end;
/**
* @ORM\Column(type="string", length=255, nullable=true, name="status")
*/
private $status;
/**
* @ORM\Column(type="text", nullable=true, name="description")
*/
private $description;
/**
* @ORM\Column(type="boolean", nullable=true, options={"default":0})
*/
private $busy;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", fetch="EAGER")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
* @return CalendarEvent
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/**
* @return mixed
*/
public function getBusy()
{
return $this->busy;
}
/**
* @param mixed $busy
* @return CalendarEvent
*/
public function setBusy($busy)
{
$this->busy = $busy;
return $this;
}
/**
* Set name
*
* @param string $name
* @return CalendarEvent
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set start
*
* @param \DateTime $start
* @return CalendarEvent
*/
public function setStart($start)
{
$this->start = $start;
return $this;
}
/**
* Get start
*
* @return \DateTime
*/
public function getStart()
{
return $this->start;
}
/**
* Set end
*
* @param \DateTime $end
* @return CalendarEvent
*/
public function setEnd($end)
{
$this->end = $end;
return $this;
}
/**
* Get end
*
* @return \DateTime
*/
public function getEnd()
{
return $this->end;
}
/**
* Set status
*
* @param string $status
* @return CalendarEvent
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
* Set description
*
* @param string $description
* @return CalendarEvent
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
}
CalendarEventType выглядит следующим образом:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use AppBundle\Form\DataTransformer\DateTimeTransformer;
class CalendarEventType extends AbstractType
{
private $tokenStorage;
public function __construct($date = null, $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, array(
'attr' => array(
'placeholder' => 'app.forms.calendar.name',
),
'label' => 'app.forms.calendar.name',
'translation_domain' => 'AppBundle'
))
->add('description', TextareaType::class, array(
'label' => 'app.forms.calendar.description',
'translation_domain' => 'AppBundle'
))
->add('start', DateTimeType::class, array(
'label' => 'app.forms.calendar.start',
'translation_domain' => 'AppBundle',
'date_widget' => 'single_text',
'time_widget' => 'text'
))
->add('end', DateTimeType::class, array(
'label' => 'app.forms.calendar.end',
'translation_domain' => 'AppBundle',
'date_widget' => 'single_text',
'time_widget' => 'text'
));
$builder->get('start')->addModelTransformer(new DateTimeTransformer());
$builder->get('end')->addModelTransformer(new DateTimeTransformer());
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\CalendarEvent',
'csrf_protection' => true,
'csrf_field_name' => '_token',
// a unique key to help generate the secret token
'intention' => 'calendar_event',
));
}
/**
* @return string
*/
public function getName()
{
return 'appbundle_calendarevent';
}
}
The DateTimeTransformer:
<?php
namespace AppBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class DateTimeTransformer implements DataTransformerInterface
{
/**
* Transforms an object (DateTime) to a string.
*
* @param \DateTime|null $datetime
* @return string
*/
public function reverseTransform($datetime)
{
if (null === $datetime) {
return '';
}
return $datetime->format('yyyy-MM-dd HH:ii');
}
/**
* Transforms a string to an object (DateTime).
*
* @param string $datetime
* @return \DateTime|null
*/
public function transform($datetime)
{
// datetime optional
if (!$datetime) {
return null;
}
return date_create_from_format('yyyy-MM-dd', $datetime);
}
}
Контролер (я включаю только функцию создания здесь):
/**
* @Route("/events", name="api_event_create")
* @Method("post")
*
* @param Request $request
* @return array
*/
public function createAction(Request $request)
{
$response = new Response();
// Get logged in user if it exists, else return unauthorized status code
$user = $this->getUser();
if(! ($user instanceof User)) {
$response->setStatusCode(401);
$response->send();
};
// Handle the request
// Get data from post
$data = $request->request->get('appbundle_calendarevent');
// Create new entity
$entity = new CalendarEvent();
// Create form
$form = $this->createForm(new CalendarEventType('', $this->get('security.token_storage')), $entity);
// Submit form data
$form->submit($data);
// Check if form is valid
if($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$title = (array_key_exists('name', $data)) ? $data['name'] : 'Ny hendelse';
$desc = (array_key_exists('description', $data)) ? $data['description'] : NULL;
$entity->setUser($user);
$entity->setName($title);
$entity->setDescription($desc);
$entity->setStatus('normal');
$em->persist($entity);
$em->flush();
$response = new Response();
$response->setStatusCode(201);
$response->headers->set(
'Location',
$this->generateUrl('calendar_events_show', array('id' => $entity->getId()))
);
} else {
return array('errors' => $form->getErrors());
}
$response->send();
}
Javascript для Ajax звонки:
(function($){
$('.calendar td').on('dblclick', function() {
var self = $(this);
newEvent(self).done(handleDone);
});
var newEvent = function(self) {
var url = 'url to api';
var method = 'post';
var selectedDate = self.attr('id');
var eventStartDate = moment(selectedDate, "YYYYMMDD").format('YYYY-MM-DD HH:mm'); // Start date
var eventEndDate = moment(selectedDate, "YYYYMMDD").format('YYYY-MM-DD HH:mm'); // End date
return $.ajax({
url: url,
method: method,
data: {
"appbundle_calendarevent[name]": 'New event',
"appbundle_calendarevent[start]": eventStartDate,
"appbundle_calendarevent[end]": eventEndDate,
"appbundle_calendarevent[_token]": form_token
},
statusCode: {
400: handleStatus400,
401: handleStatus401,
402: handleStatus402,
404: handleStatus404,
422: handleStatus422,
500: handleStatus500
}
});
};
function handleDone(data) {
console.log(data);
}
function handleStatus400() {
console.log('400');
}
function handleStatus401() {
console.log('401');
}
function handleStatus402() {
console.log('402');
}
function handleStatus404() {
console.log('404');
}
function handleStatus422() {
console.log('422');
}
function handleStatus500() {
console.log('500');
}
})(jQuery);
Выполнение вызова Ajax посылает эти параметры:
appbundle_calendarevent[name]:"New+event"
appbundle_calendarevent[start]:"2016-03-25+00:00"
appbundle_calendarevent[end]:"2016-03-25+00:00"
appbundle_calendarevent[_token]:"97Ygs8Q9y70gi0vs24Mrg1LfpCvZ2wjaIcc41KASjkg"
Вместо 'date_create_from_format ('yyyy-MM-dd', $ datetime);' try 'new \ DateTime ($ datetime);' – LBA
Я пробовал, но, увы, это не сработало. Благодарю вас за предложение. – pusle