Booking system using query builder and Symfony - php

I am trying to build an app like airbnb using Symfony 4. I have properties that are listed by users and reservations for these properties. The relation between those entities is OneToMany. One property to many reservations. Each reservation has a start_date and an end_date. I want to run a query that returns all properties that are not taken for certain dates selected by users. My query so far is like this:
->andWhere('NOT (reservations.startDate BETWEEN :checkInDate AND :checkOutDate) AND ' .
'NOT (reservations.endDate BETWEEN :checkInDate AND :checkOutDate) AND ' .
'NOT (reservations.startDate <= :checkInDate AND reservations.endDate >= :checkOutDate)')
->setParameter('checkInDate', new \DateTime($checkIn))
->setParameter('checkOutDate', new \DateTime($checkOut))
->innerJoin('p.reservations', 'reservations');
However this seems to check only the first reservation that shows up in the database for each property and ignores the rest. How can I write the code so that the query checks all reservations made for a property not just the first one in the database. Thank you so much

I figured it out. I created another query for reservations that are not overlapping with the dates selected by users and then used notIn in the property query to get all properties which do not have such reservation. Here is the code. This is the query for the reservations:
$subQueryBuilder = $this->getEntityManager()->createQueryBuilder();
$subQuery = $subQueryBuilder
->select('prop.id')
->from('App:Reservation', 'reservation')
->orWhere('reservation.startDate BETWEEN :checkInDate AND :checkOutDate')
->orWhere('reservation.endDate BETWEEN :checkInDate AND :checkOutDate')
->orWhere('reservation.startDate <= :checkInDate AND reservation.endDate >= :checkOutDate')
->andWhere('reservation.confirmedAt IS NOT NULL')
->andWhere('reservation.rating IS NULL')
->innerJoin('reservation.property', 'prop')
;
And this is the query for the properties which returns only properties which are not found in the first query. It uses the property id to check that.
$properties = $this->createQueryBuilder('p')
->select('p')
->andWhere('p.approved = 1')
->andWhere($properties->expr()->notIn('p.id', $subQuery->getDQL()))
->andWhere('reservations.confirmedAt IS NOT NULL')
->andWhere('reservations.rating IS NULL')
->setParameter('checkInDate', new \DateTime($checkIn))
->setParameter('checkOutDate', new \DateTime($checkOut))
->innerJoin('p.reservations', 'reservations')
->getQuery();

Related

Yii2 query all get value in join

I have an database with tablenames like this: tbl_accessoires_1, tbl_accessoires_2 etc. In my main table is a column that gives me the number for the table I have to join. But how do I get this value if I use ->all().
This is my query:
$query = (new Query())
->select([
'a.id id',
'a.soort soort',
])
->from('auto_new a')
->leftJoin('tbl_accessoires_--soort-- acc', 'acc.id = a.id')
->all();
So the a.soort in the select must be at the --soort--
Is there any way to do this?
If I only get one car it is possible because I could get the soort value before this query. but how do I do this when I want to get all cars
So because it's not possible in my situation I've just made a new query to get the options. This will do for now because I don't really need the options when I get all cars.

Symfony get distinct months from database DateTime field

Currently I have a Query Builder which gets all distinct dates from DateTime field but I need to get only distinct months and years and ignore the days. For example if dates where 2015-06-15, 2015-06-20, 2015-07-10, 2016-06-13 I should get 2015-06, 2015-07, 2016-06.
Is there any way to get this result right from database or do I need to this with php?
My current query looks like this:
$dates = $this->getEntityManager()->getRepository('EventBundle:Event')
->createQueryBuilder('e')
->select('e.startDate')
->where('e.startDate >= :startDate')
->setParameter('startDate', new DateTime('now'))
->orderBy('e.startDate', 'ASC')
->distinct()
->getQuery();
$dates = $dates->getResult();
You can get it from the database but I think you will need to use a native mysql query e.g.
select distinct(DATE_FORMAT(e.startDate,'%Y-%m'))
from event e
where e.startDate >= :startDate
To perform a native query see How to use Doctrine DBAL

get user with most articles and its amount with active record or query

I want to get the user that wrote the most articles. I do so fine in two ways with ActiveRecord like the following:
$table = Articles::find()
->select('articles.*, COUNT(*) AS cnt')
->with('user','userDetails')
->groupBy('articles.user_id')
->orderBy(('cnt DESC'))
->limit(10)
->offset($offset)
->all();
and with a query like the following:
$query = (new Query())
->select('articles.user_id, COUNT(*) AS num_articles')
->from('articles')
->join('LEFT JOIN', 'user_details', 'user_details.user_id = articles.user_id')
->groupBy('articles.user_id')
->orderBy('num_articles DESC')
->limit(10)
->offset($offset)
->all();
The problem is that the ActiveRecord gives me further needed informations userDetails that I need. But I do not get the amount of articles of user that should be on cnt
With the Query I get the user_id and the amount of articles. But I do not get it working by joining with userDetails. All of these does not work: LEFT JOIN, RIGHT JOIN, INNER JOIN.
I am interested in resolving both for learning, but for concrete I need help with the ActiveRecord problem.
Okay well I solved it for the ActiveRecord. The ActiveRecords needs a public $var; in the Model. So to get the amount you have to add the mentioned public... to your Model so that in my case:
public $cnt; extends the ActiveRecord of Articles
now I can access it with the given Request in my Question. But this just solves the first point. I am still interested in the second way for more complex Queries.
I dont have much idea about active record but I think the below is something what you are looking for
select * from user_details where user_id in
(select A.user from
(select user_id as user, COUNT(*) AS num_articles
from articles group by user_id order by num_articles desc LIMIT 10)A
);
for second point you should include required column from joined table to select statement:
$query = (new Query())
->select('articles.user_id, COUNT(*) AS num_articles, user_details.username as username')
->from('articles')
->join('LEFT JOIN', 'user_details', 'user_details.user_id = articles.user_id')
->groupBy('articles.user_id')
->orderBy('num_articles DESC')
->limit(10)
->offset($offset)
->all();

How to tell Paris/ORM which table to use for the Model?

I've just added some Joins to my application which uses Idiorm/Paris, I'm finding that when I search via Model::factory() the object returned is getting the ID from the joined object, not the 'parent' object.
How can I tell Paris which table alias should form the model?
I'm doing this in a search context, so I don't think that I can use has_many() but I'd be happy to be wrong!
Sample code:
// Find a booking with a join
$query = Model::factory('Booking');
$query->where('booking.id', '2282');
$query->join(
'customer',
array('booking.id', '=', 'customer.booking_id'),
'customer'
);
$bookingWithJoin = $query->find_one();
// Find the same booking, without a join
$query = Model::factory('Booking');
$query->where('id', '2282');
$bookingWithoutJoin = $query->find_one();
// The booking with a join gets the ID of the customer it's joined with
echo $bookingWithJoin->id .' != '. $bookingWithoutJoin->id;
I discovered the answer was $query->select('booking.*');
Does the equivelant of
SELECT booking.* FROM bookings JOIN customer on booking.customer_id = customer.id
So the returned results won't have customer.* fields included.

How to write a Doctrine Query with multiple conditions?

I am trying to write a doctrine query that meets the following conditions:
published = 1
AND
subsection = "gui" OR "lvo" OR "tnn" OR "wer"
This is what I have:
$getPrograms = Doctrine::getTable('Program')
->createQuery()
->where('published=?', '1')
->andWhere('subsection=?', 'gui')
->orWhere('subsection=?', 'lvo')
->orWhere('subsection=?', 'tnn')
->orWhere('subsection=?', 'wer')
->orderBy('title ASC')
->execute();
This is pulling the correct subsection records, but is pulling records all published records, instead of only ones set to 1.
I feel I need to isolate the two conditions ( this AND (this OR this OR this)) but I do not know how.
Put your OR in the andWhere :
$getPrograms = Doctrine::getTable('Program')
->createQuery()
->where('published=?', '1')
->andWhere(
'subsection=? OR subsection=? OR subsection=? OR subsection=?',
array('gui', 'lvo', 'tnn', 'wer')
)
->orderBy('title ASC')
->execute();

Categories