How to hide events that happened today and have passed ? Symfony - symfony

In my Symfony project, I have created the table "event" and datatime field in it named start. In twig, I wish to filter and display upcoming events. So events that have passed would be visible any more.
At the moment, I used {% if event.start > date() %}. It worked to hide events that happened days before today. I wanted also to hide events that already happened today but currently it doesn't work when time has passed of the today's event.
How can I hide events that time already has passed ?

better to make a function in the repository and call it in the controller not using findAll and hide events.
// EventRepository
public function eventsList()
{
return $this->createQueryBuilder('e')
->andWhere('e.date >= :today')
->setParameter('today', new \DateTime())
->orderBy('e.id', 'DESC')
->getQuery()
->getResult()
;
}

Here is the solution :
Make sure the field is datetime.
Use {% if event.start > 'now' %}and it will take into account day (of today) and (current) time.

Here is a better solution (I precise that an address is given to events, and address has a "bigcity" registered, this why I am using LocationRepository) :
EventController.php
#[Route('/events', name: 'events')]
public function events(
Request $request,
EventRepository $eventRepository,
CategoryRepository $categoryRepository,
BigCityRepository $bigcityRepository,
LocationRepository $locationRepository
){
$category = $categoryRepository->findOneById($request->query->get('category'));
$bigcity = $bigcityRepository->findOneById($request->query->get('bigcity'));
$location = $locationRepository->findAll($request->query->get('location.bigcity'));
$events = $eventRepository->findBy(['category' => $category, 'address' => $location]);
return $this->render("front/events.html.twig", [
'events' => $events,
'category' => $category,
'bigcity' => $bigcity
]);
}

Related

Doctrine weird behavior, changes entity that I never persisted

I have this situation:
Symfony 4.4.8, in the controller, for some users, I change some properties of an entity before displaying it:
public function viewAction(string $id)
{
$em = $this->getDoctrine()->getManager();
/** #var $offer Offer */
$offer = $em->getRepository(Offer::class)->find($id);
// For this user the payout is different, set the new payout
// (For displaying purposes only, not intended to be stored in the db)
$offer->setPayout($newPayout);
return $this->render('offers/view.html.twig', ['offer' => $offer]);
}
Then, I have a onKernelTerminate listener that updates the user language if they changed it:
public function onKernelTerminate(TerminateEvent $event)
{
$request = $event->getRequest();
if ($request->isXmlHttpRequest()) {
// Don't do this for ajax requests
return;
}
if (is_object($this->user)) {
// Check if language has changed. If so, persist the change for the next login
if ($this->user->getLang() && ($this->user->getLang() != $request->getLocale())) {
$this->user->setLang($request->getLocale());
$this->em->persist($this->user);
$this->em->flush();
}
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::TERMINATE => [['onKernelTerminate', 15]],
];
}
Now, there is something very weird happening here, if the user changes language, the offer is flushed to the db with the new payout, even if I never persisted it!
Any idea how to fix or debug this?
PS: this is happening even if I remove $this->em->persist($this->user);, I was thinking maybe it's because of some relationship between the user and the offer... but it's not the case.
I'm sure the offer is persisted because I've added a dd('beforeUpdate'); in the Offer::beforeUpdate() method and it gets printed at the bottom of the page.
alright, so by design, when you call flush on the entity manager, doctrine will commit all the changes done to managed entities to the database.
Changing values "just for display" on an entity that represents a record in database ("managed entity") is really really bad design in that case. It begs the question what the value on your entity actually means, too.
Depending on your use case, I see a few options:
create a display object/array/"dto" just for your rendering:
$display = [
'payout' => $offer->getPayout(),
// ...
];
$display['payout'] = $newPayout;
return $this->render('offers/view.html.twig', ['offer' => $display]);
or create a new non-persisted entity
use override-style rendering logic
return $this->render('offers/view.html.twig', [
'offer' => $offer,
'override' => ['payout' => $newPayout],
]);
in your template, select the override when it exists
{{ override.payout ?? offer.payout }}
add a virtual field (meaning it's not stored in a column!) to your entity, maybe call it "displayPayout" and use the content of that if it exists

Add method in Entity not reached

I need to bugfix a Symfony3 project with Sonata Admin & Doctrine.
I got a field list, with all textures saved in base
The problem is in the "addTexture" method, the previous developer did :
public function addTexture(\AppBundle\Entity\Texture $texture)
{
if (count($this->textures[]) < 26)
$this->textures[] = $texture;
return $this;
}
And we can add more than 25 textures : that's my bug.
So I added a dump($this->textures); exit; and nothing happen, the app never reach this. While in other entities, the "add" method is reached.
EDIT :
Seems like it's my Doctrine2 ArrayCollection that never fire all my addXXX methods. But it saving my collections on database, and i don't know why.
EDIT 2 :
I found where the list is declared :
->add('colors','sonata_type_model', [
'multiple' => true,
'expanded' => false,
'property' => 'Name'
])
Is there a way to add a limit or maximum item ? Then I won't need to update the Entity if it's UI restricted.
Try to use ArrayCollection methods (let's say that we work on Color Entity):
public function addTexture(\AppBundle\Entity\Texture $texture)
{
if ($this->textures->count() < 26) {
$this->textures->add($texture);
$texture->setColor($this); //Add this if you have bidirectional mapping
}
return $this;
}

Open a specific day using FullCalendar package

I wonder if someone has already figured my problem out.
I'm using Laravel 5 Full Calendar Helper in order to create a booking app.
What I want to achieve is to render the calendar on an specific day which is the booking date
For example if someone wants to book a room for 12/31/2015, he will be able to see the calendar on that date (day view), before book their room.
So far I got this
ConsultController
<?php
namespace App\Http\Controllers;
use App\Booking;
use App\Http\Requests\BookingRequest;
use App\Room;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
class ConsultController extends Controller
{
public function consult(BookingRequest $request){
// Look for the booking which matches with our search
$seek = Booking::where('room_id','=',$request->room)
->where('day','=',$request->day)
->where('start','=',$request->start)->first();
// If no booking matches, then book
if(is_null($seek)){
$book = $request;
// Get all the bookings on day requested
$bookings = Booking::where('day','=',$request->day)->get();
// creating events for the calendar
$events = [];
foreach($bookings as $booking){
$events[] = \Calendar::event(
''.$booking->room->name, //event title
false, //full day event?
$booking->day->format('Y-m-d').$booking->start, //start time (you can also use Carbon instead of DateTime)
$booking->day->format('Y-m-d').$booking->end, //end time (you can also use Carbon instead of DateTime)
$booking->id //optionally, you can specify an event ID
);
}
$events [] = \Calendar::event(
''.Room::find($book->room)->name, //event title
false,
$book->day.$book->start,
$book->day.$book->end,
0,
[
'backgroundColor' => '#ff5722'
]
);
// Adding event for the calendar
$calendar = \Calendar::addEvents($events);
return view('consult.book')->with(['calendar' => $calendar,'book'=>$book]);
}
// If a record matches then redirect back
else{
Session::flash('flash_message','Lo sentimos ese horario está ocupado');
return redirect()->back();
}
}
}
I have this view
but what I want is this view
Taking a detailed review to the documentation I found out that this helper class has a setOptions method which allows to have more control when rendering the calendar
I just added that method and reached what I was looking for
$calendar = \Calendar::addEvents($events)->setOptions([ 'defaultDate' => $book->day,'defaultView' => 'agendaDay']);

How to tell if no result were matched using doctrine Criteria?

I have number of blog posts in my database and im using doctrine criteria to filter them. If I write criteria that matches some of the posts everything works perfect.
Imagine that there are 3 users (User 1 , User 2, User 3) and there are some posts marked as private from User 1 and user 2.
This is my php code :
$criteria = Criteria::create();
$criteria->Where($criteria->expr()->eq('private', 1);
$criteria->andWhere($criteria->expr()->eq('author', $author));
$posts=$service->findPostBy($criteria);
return array(
'page' => $page,
'posts'=>$posts,
'filter' => $form->createView()
);
/*findPostBy calls Doctrine matching function*/
public function matching(Criteria $criteria)
{
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
return new ArrayCollection($persister->loadCriteria($criteria));
}
If i ask for User 1 private posts it builds functional query and return posts i want. But if I ask for User 3 private posts It returns all posts in my database without any filtering. How can I tell if my criteria works if they dont return empty result in case of no matches.
Try this:
$criteria = Criteria::create()
->where(Criteria::expr()->eq('private', 1);
->andWhere(Criteria::expr()->eq('author', $author));
I'm not sure why you are using criteria in the first place for your example though. You could eliminate the Criteria altogether and accomplish what you want in one line:
$posts $service->findPostBy(array('private' => 1, 'author' => $author);

smarty phpunit empty fetch

I need help please.
I'm using Smarty with PHPUnit, and I have troubles.
For example:
In some checks, I call fetch function many times, and I only receive right the first call, the others only return empty. Why???
I let some code here as an example:
/**
* #dataProvider provider_test
*/
public function test_field($field) {
// with this I instance smarty
$front = $this->get_template();
$front->assign('function', 'fb_user_field');
$front->assign('field', $field);
// this fetch only return right widh the first value of field
$result = $front->fetch('tests/generic.tpl');
$this->assertNotNull($result);
}
public function provider_test() {
return array(
array('field' => 'subdomain'),
array('field' => 'login')
);
}
I check $field and in every iteration receive the correct value, but after the first one, fetch return only empty.
Why???? Thanks!!!
My suggestion is to use the MakeGood or similar to step by step debug your php code. Otherwise it is guess and check till you die!
Here's some links
http://blog.loftdigital.com/running-phpunit-tests-in-eclipse-pdt
http://www.youtube.com/watch?v=1qnWL52wt58
I used to spend hours guess and check with phpunit until I discovered MakeGood. Hope it helps!

Resources