IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Passage d'un paramètre à un listener avec fullCalendar [4.x]


Sujet :

Symfony PHP

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Points : 356
    Points
    356
    Par défaut Passage d'un paramètre à un listener avec fullCalendar
    Bonjour,

    Je désire mettre en place un calendrier de réservations. Pour ce faire, j'utilise le bundle tattali/CalendarBundle interagissant avec fullCalendar.

    Je sais créer une réservation et afficher toutes les réservations dans un calendrier. Cependant, je voudrais qu'une réservation soit liée à un véhicule et pour chaque véhicule, qu'un calendrier n'affiche que les réservations liées à celui-ci.

    Donc, voici mon entité Booking :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
     
    <?php
     
    namespace App\Entity;
     
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
     
    /**
     * @ORM\Entity(repositoryClass="App\Repository\BookingRepository")
     * 
     * @UniqueEntity(
     *               fields={"beginAt"},
     *               message="Une réservation existe déjà avec cette date de début."
     * )
     */
    class Booking
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
     
        /**
         * @ORM\Column(type="datetime")
         * 
         * @Assert\NotBlank(
         *      message = "La date de construction ne peut pas être vide."
         * )
         * @Assert\Type("\DateTime")
         * @Assert\GreaterThan("today")
         */
        private $beginAt;
     
        /**
         * @ORM\Column(type="datetime", nullable=true)
         */
        private $endAt;
     
        /**
         * @ORM\Column(type="string", length=255)
         */
        private $title;
     
        /**
         * @ORM\ManyToOne(targetEntity="App\Entity\Vehicle", inversedBy="bookings")
         * @ORM\JoinColumn(nullable=false)
         */
        private $vehicle;
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getBeginAt(): ?\DateTimeInterface
        {
            return $this->beginAt;
        }
     
        public function setBeginAt(\DateTimeInterface $beginAt): self
        {
            $this->beginAt = $beginAt;
     
            return $this;
        }
     
        public function getEndAt(): ?\DateTimeInterface
        {
            return $this->endAt;
        }
     
        public function setEndAt(?\DateTimeInterface $endAt): self
        {
            $this->endAt = $endAt;
     
            return $this;
        }
     
        public function getTitle(): ?string
        {
            return $this->title;
        }
     
        public function setTitle(string $title): self
        {
            $this->title = $title;
     
            return $this;
        }
     
        public function getVehicle(): ?Vehicle
        {
            return $this->vehicle;
        }
     
        public function setVehicle(?Vehicle $vehicle): self
        {
            $this->vehicle = $vehicle;
     
            return $this;
        }
    }
    Afin d'afficher les réservations dans le calendrier, j'ai ce listener :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    <?php
     
    namespace App\Listener;
     
    use App\Entity\Booking;
    use App\Repository\BookingRepository;
    use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
    use CalendarBundle\Entity\Event;
    use CalendarBundle\Event\CalendarEvent;
     
    class CalendarListener
    {
        private $bookingRepository;
        private $router;
     
        public function __construct(BookingRepository $bookingRepository, UrlGeneratorInterface $router) 
        {
     
            $this->bookingRepository = $bookingRepository;
            $this->router = $router;
     
        }
     
        public function load(CalendarEvent $calendar): void
        {
     
            $start = $calendar->getStart()->format('Y-m-d H:i:s');
            $end = $calendar->getEnd()->format('Y-m-d H:i:s');
     
            $filters = $calendar->getFilters();
     
            $bookings = $this->bookingRepository->findBetweenDates($start, $end);
     
            foreach ($bookings as $booking) 
            {
     
                // this create the events with your data (here booking data) to fill calendar
                $bookingEvent = new Event(
                                            $booking->getTitle(),
                                            $booking->getBeginAt(),
                                            $booking->getEndAt() // If the end date is null or not defined, a all day event is created.
                                         )
                ;
     
                /*
                 * Add custom options to events
                 *
                 * For more information see: https://fullcalendar.io/docs/event-object
                 * and: https://github.com/fullcalendar/fullcalendar/blob/master/src/core/options.ts
                 */
     
                $bookingEvent->setOptions([
                                            'backgroundColor' => 'red',
                                            'borderColor' => 'red',
                                          ]
                                         )
                ;
     
                $bookingEvent->addOption(
                                            'url',
                                            $this->router->generate('admin.booking.show', ['id' => $booking->getId(),])
                                        )
                ;
     
                // finally, add the event to the CalendarEvent to fill the calendar
                $calendar->addEvent($bookingEvent);
     
            }
     
        }
     
    }
    Ce que désirerais faire, c'est passer un paramètre vehicle supplémentaire à ma fonction "findBetweenDates" afin de ne ramener que les réservations liées à celui-ci. Ca donnerait donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $bookings = $this->bookingRepository->findBetweenDates($start, $end, $vehicle);
    .

    Cependant, malgré 2 jours de recherches, je ne vois pas comment transmettre ce paramètre véhicule à mon listener soit via l'objet calendar, soit directement à mon mistener.

    Quelqu'un aurait une idée?

    Merci d'avance pour votre aide.

  2. #2
    Membre actif
    Inscrit en
    Août 2006
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 191
    Points : 263
    Points
    263
    Par défaut
    Salut,

    tu n'as pas mis le code de BookingRepository ni le code qui initialise les appel a CalendarListener et autre enfin il nous faudrait plus de code pour pouvoir t aider.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Points : 356
    Points
    356
    Par défaut
    Bonjour,

    Merci pour ton intérêt.

    Voici mon BookingRepository :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    <?php
     
    namespace App\Repository;
     
    use App\Entity\Booking;
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Symfony\Bridge\Doctrine\RegistryInterface;
     
    /**
     * @method Booking|null find($id, $lockMode = null, $lockVersion = null)
     * @method Booking|null findOneBy(array $criteria, array $orderBy = null)
     * @method Booking[]    findAll()
     * @method Booking[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
     */
    class BookingRepository extends ServiceEntityRepository
    {
        public function __construct(RegistryInterface $registry)
        {
            parent::__construct($registry, Booking::class);
        }
     
         /**
          * @return Booking[]
          */
        public function findBetweenDates($start, $end)
        {
     
            return $this->createQueryBuilder('b')
                                ->where('b.beginAt BETWEEN :start and :end')
    //                            ->where('b.vehicle = :vehicleId')
                                ->setParameter('start', $start)
                                ->setParameter('end', $end)
    //                            ->setParameter('vehicleId', $vehicleId)
                                ->getQuery()
                                ->getResult()
            ;
        }
     
        // /**
        //  * @return Booking[] Returns an array of Booking objects
        //  */
        /*
        public function findByExampleField($value)
        {
            return $this->createQueryBuilder('b')
                ->andWhere('b.exampleField = :val')
                ->setParameter('val', $value)
                ->orderBy('b.id', 'ASC')
                ->setMaxResults(10)
                ->getQuery()
                ->getResult()
            ;
        }
        */
     
        /*
        public function findOneBySomeField($value): ?Booking
        {
            return $this->createQueryBuilder('b')
                ->andWhere('b.exampleField = :val')
                ->setParameter('val', $value)
                ->getQuery()
                ->getOneOrNullResult()
            ;
        }
        */
    }
    La fonction d'appel dans le contrroller :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
        /**
         * @Route("/adverts/{slug}-{id}", name="advert.show", requirements = {"slug": "[a-z0-9\-]*"})
         */
        public function show(Advert $advert, String $slug, Request $request, ContactNotification $notification ): Response 
        {
     
            $advertSlug = $advert->getSlug();
     
            if ($advertSlug !== $slug) {
     
                return $this->redirectToRoute('advert.show', ['id' => $advert->getId(),
                                                              'slug' => $advertSlug,
                                                             ],
                                              301 
                                             )
                ;
     
            }
     
            $contact = new Contact();
            $contact->setAdvert($advert);
     
            $minPrice = $this->getMinPrice($advert);
            $mainPhoto = $this->photoRepository->findOneBy(array('advert' => $advert, 'mainPhoto' => true));
     
            $cellEquipments = array();
            $carrierEquipments = array();
     
            foreach($advert->getVehicle()->getEquipments() as $equipment)
            {
     
                if ($equipment->getBelonging() === 'Cellule') 
                {
     
                    $cellEquipments[] = $equipment;
     
                }
                else
                {
     
                    $carrierEquipments[] = $equipment;
     
                }
     
            }
     
            $form = $this->createForm(ContactType::class, $contact);
            $form->handleRequest($request);
     
            if ($form->isSubmitted() && $form->isValid()) 
            {
     
                $notification->notify($contact);
     
                $this->addFlash('success', 'Votre message a été envoyé avec succès.');
    /*
                return $this->redirectToRoute('advert.show', ['id' => $advert->getId(),
                                                              'slug' => $advertSlug,
                                                             ]
                                             )
                ;
    */
            }
     
            return $this->render('advert/show.html.twig', ['current_menu' => 'adverts', 
                                                           'controller_name' => 'AdvertController', 
                                                           'advert' => $advert,
                                                           'minPrice' => $minPrice,
                                                           'mainPhoto' => $mainPhoto,
                                                           'cellEquipments' => $cellEquipments,
                                                           'carrierEquipments' => $carrierEquipments,
                                                           'form' => $form->createView(),
                                                          ]
                                )
        ;
    Et la partie de mon template qui fait appel au calendar :

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                    <div class="row">
     
                        {% include '@Calendar/calendar.html' %}
     
                    </div>

    Cependant, je ne pense pas que le repository et le twig interviennent dans mon problème : je voudrais envoyer un paramètre depuis le controller ou via le javascript qui instancie le calendar au listener pour que celui-ci le transmette au repository afin que la requête ne me ramène que les réservations liées au véhicule sélectionné.

  4. #4
    Membre actif
    Inscrit en
    Août 2006
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 191
    Points : 263
    Points
    263
    Par défaut
    Salut,

    Voici comment tu peux modifier BookingRepository->findBetweenDates()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public function findBetweenDates($start, $end, $vehicle=null)
        {
    		$query = $this->createQueryBuilder('b')
                                ->andWhere('b.beginAt BETWEEN :start and :end');
    		if (!empty($vehicule)){
    			$query->andWhere('b.vehicle = :vehicleId');
    		}					
     
            $query->setParameter('start', $start)
                  ->setParameter('end', $end)
    		if (!empty($vehicule)){
    			$query->setParameter('vehicleId', $vehicleId);
    		}
     
    		return $query->getQuery()
                         ->getResult()
            ;
        }
    par contre, il manque le bout de code qui instancie le CalendarListener et appel sa méthode load().

  5. #5
    Membre actif
    Inscrit en
    Août 2006
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 191
    Points : 263
    Points
    263
    Par défaut
    Bon j'ai regardé les sources de fullcallendar

    voici ce que je te propose comme modification sur CalendarListener:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    <?php
     
    namespace App\Listener;
     
    use App\Entity\Booking;
    use App\Repository\BookingRepository;
    use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
    use CalendarBundle\Entity\Event;
    use CalendarBundle\Event\CalendarEvent;
     
    class CalendarListener
    {
        private $bookingRepository;
        private $router;
     
        public function __construct(BookingRepository $bookingRepository, UrlGeneratorInterface $router) 
        {
     
            $this->bookingRepository = $bookingRepository;
            $this->router = $router;
     
        }
     
        public function load(CalendarEvent $calendar): void
        {
     
            $start = $calendar->getStart()->format('Y-m-d H:i:s');
            $end = $calendar->getEnd()->format('Y-m-d H:i:s');
     
            $filters = $calendar->getFilters();
     
    		$vehicule = null;
    		$filters_tab = json_decode($filters, true);
    		if (!empty($filters_tab)){
    			if (array_key_exists('vehicule',$filters_tab)){
    				$vehicule = $filters_tab['vehicule'];
    			}
    		}
     
     
            $bookings = $this->bookingRepository->findBetweenDates($start, $end, $vehicule);
     
            foreach ($bookings as $booking) 
            {
     
                // this create the events with your data (here booking data) to fill calendar
                $bookingEvent = new Event(
                                            $booking->getTitle(),
                                            $booking->getBeginAt(),
                                            $booking->getEndAt() // If the end date is null or not defined, a all day event is created.
                                         )
                ;
     
                /*
                 * Add custom options to events
                 *
                 * For more information see: https://fullcalendar.io/docs/event-object
                 * and: https://github.com/fullcalendar/fullcalendar/blob/master/src/core/options.ts
                 */
     
                $bookingEvent->setOptions([
                                            'backgroundColor' => 'red',
                                            'borderColor' => 'red',
                                          ]
                                         )
                ;
     
                $bookingEvent->addOption(
                                            'url',
                                            $this->router->generate('admin.booking.show', ['id' => $booking->getId(),])
                                        )
                ;
     
                // finally, add the event to the CalendarEvent to fill the calendar
                $calendar->addEvent($bookingEvent);
     
            }
     
        }
     
    }
    et dans l'initialisation javascript de ton calendar : (n'ayant pas le tien j'ai pris celui de la doc mais en gros faut juste charger l'option filter en lui passant ton paramètre)
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <script type="text/javascript">
            document.addEventListener('DOMContentLoaded', () => {
                var calendarEl = document.getElementById('calendar-holder');
     
                var calendar = new FullCalendar.Calendar(calendarEl, {
                    defaultView: 'dayGridMonth',
                    editable: true,
                    eventSources: [
                        {
                            url: "{{ path('fc_load_events') }}",
                            type: "POST",
                            data: {
                                filters: {"vehicule":42},
                            },
                            error: () => {
                                // alert("There was an error while fetching FullCalendar!");
                            },
                        },
                    ],
                    header: {
                        left: 'prev,next today',
                        center: 'title',
                        right: 'dayGridMonth,timeGridWeek,timeGridDay',
                    },
                    plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
                    timeZone: 'UTC',
                });
                calendar.render();
            });
        </script>

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Points : 356
    Points
    356
    Par défaut
    Encore un tout grand merci pour ton implication. Ce problème me prend bien la tête depuis plusieurs jours

    J'avais de fait déjà testé cette solution et je viens de le refaire : en faisant de la sorte, j'obtiens cette erreur :

    Warning: json_decode() expects parameter 1 to be string, array given
    Elle se déclenche sur cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $filters_tab = json_decode($filters, true);
    Or, si je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $vehicule = $filters['vehicule'];
    j'ai l'erreur

    Undefined index: vehicule
    Pour répondre à ta question sur l'instanciation du CalendarListener, elle se fait via l'utilisation d'un service dont voici la configuration :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        App\Listener\CalendarListener:
            tags:
                - { name: 'kernel.event_listener', event: 'calendar.set_data', method: load }

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Points : 356
    Points
    356
    Par défaut
    Finalement, c'était un problème avec le bundle dû à une modification au niveau de FullCalendar. Le développeur du bundle a effectué les modifications nécessaires et cela maintenant fonctionne avec cette paramétrisation dans le javascript :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    ...
            var calendar = new Calendar(calendarEl, {
     
                defaultView: 'dayGridMonth',
                editable: true,
                eventSources: [
                                {
     
                                    url: "/fc-load-events",
                                    method: "POST",
                                    extraParams: {
                                    filters: JSON.stringify({ vehicle: vehicleId }),
                                    },
                                    failure: () => {},
     
                                },
                              ],
    ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 28/01/2010, 16h54
  2. Passage d'un paramètre avec quote pour une procédure dynamique
    Par dcarroz dans le forum Développement
    Réponses: 7
    Dernier message: 26/01/2010, 11h06
  3. Réponses: 2
    Dernier message: 11/11/2009, 20h31
  4. [Web Service][SOAP] passage de paramètre en php4 avec nusoap
    Par jbbordas dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 28/02/2008, 15h38
  5. [AJAX] Passage de 2 paramètres avec la méthode GET
    Par furth dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 01/06/2007, 16h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo