multiple select with inner join - php

I try to translate this simple SQL request with Doctrine but with no success:
SELECT `groups`.`departure`, COUNT(`group_users`.`group_id`) as 'teamLength' FROM `groups` INNER JOIN `group_users` WHERE `groups`.`id` = `group_users`.`group_id` AND departure BETWEEN '2017-03-01' AND '2017-03-31'
Currently, my code looks like:
public function findDatesBetween(\AppBundle\Entity\Itinerary $itinerary, \DateTime $firstDate, \DateTime $lastDate)
{
$q = $this->createQueryBuilder('g')
->select('g', 'COUNT(gu.group) teamLength')
->innerJoin('AppBundle:GroupUser', 'gu', Join::WITH, 'g.id = gu.group')
->andWhere('g.itinerary = :itineraryId')
->setParameter('itineraryId', $itinerary->getId())
->andWhere('g.departure BETWEEN :firstDate AND :lastDate')
->setParameter('firstDate', $firstDate->format('Y-m-d'))
->setParameter('lastDate', $lastDate->format('Y-m-d'));
return ($q->getQuery()->getResult());
}
If I change the select() like this : ->select('g'), it works. But I need to get COUNT(gu.group).
With the actual code, I have an exception when I try to use departure: Call to a member function getDeparture() on array
How can I fix it ?
Thank you.

You want to get an aggregate result with your query, that means that your result will be an associative array and not an array of entities instances.
Try to get your data with the getArrayResult method and access your data accordingly.
You can do a {{ dump(data) }} on your twig view to see the structure of your result.

Related

Reference parent column in nested relationship

Problem
I've spent the last few hours looking for a solution for this and can't seem to find anything that works. I'm trying to load all Routes that have at least one assigned Aircraft that is currently at the departure airport of the route, like this:
Route::has('availableAircraft');
The availableAircraft relationship on Route currently looks like this, with the issue stemming from not being able to find a way to inject the Route into the final where clause (see ROUTE_ID_HERE).
// Route.php
/**
* This returns all assigned aircraft that are not allocated to jobs and are at the departure airport of the route
*/
public function availableAircraft()
{
return $this->belongsToMany(
Aircraft::class, 'aircraft_route_assignments', 'route_id', 'aircraft_id')
->whereNull('current_job_id')
->where('current_airport_id', 'ROUTE_ID_HERE');
}
Raw SQL
I can perform this query using raw SQL, but I can't find a way to replicate this in Eloquent:
select
count(*) as aggregate
from
`routes`
where (
select
count(*)
from
`aircraft`
inner join `aircraft_route_assignments` on `aircraft`.`id` = `aircraft_route_assignments`.`aircraft_id`
where
`routes`.`id` = `aircraft_route_assignments`.`route_id`
and `current_job_id` is null
and `current_airport_id` = `routes`.`departure_airport_id`
) > 0
and `routes`.`deleted_at` is null
The crucial part here is the final and 'current_airport_id' = 'routes'.'departure_airport_id', which I can't seem to find a way to replicate in the query builder.
What I've Tried
I've tried to manually specify the field, like in the SQL query as so, but the actual SQL generated by this uses 'routes.departure_airport_id' as a literal string and so returns no results:
// Route.php
/**
* This returns all assigned aircraft that are not allocated to jobs and are at the departure airport of the route
*/
public function availableAircraft()
{
return $this->belongsToMany(
Aircraft::class, 'aircraft_route_assignments', 'route_id', 'aircraft_id')
->whereNull('current_job_id')
->where('current_airport_id', '`routes`.`departure_airport_id`');
}
Am I vastly over-thinking this?
Try this as your eloquent query:
Route::whereHas('availableAircraft', function (Builder $query) {
$query->whereNull('current_job_id')
->whereRaw('current_airport_id = `routes`.`departure_airport_id`');
})->get();
And change your model to this:
public function availableAircraft()
{
return $this->belongsToMany(
Aircraft::class, 'aircraft_route_assignments', 'route_id', 'aircraft_id');
}
I solved this by adapting Mahdi's answer to use whereRaw instead of where in the whereHas subquery. So the final Eloquent query looks like:
Route::whereHas('availableAircraft', function (Builder $query) {
$query->whereNull('current_job_id')
->whereRaw('current_airport_id = `routes`.`departure_airport_id`');
})->get()

Yii2 Converting model objects to array with ArrayHelper::toArray()

I am working in YII2 Framework on the following query
SELECT T.id, T.name, T.status, IFNULL(T.image,'no-image.png') as DP
FROM TABLE_NAME T;
here is my code
$modelTeam = Teams::find()
->select(
['T.id', 'T.name', 'T.status', 'IFNULL(T.image,"no-image.png") as DP']
)
->from('{{%teams}} T')
->all();
Edit:
The result set does not include DP column at all why is that so, and how can I do that.
Edit 2:
While telling that the results do not include the DP column I missed a piece of important information that I was using the ArrayHelper::toArray() to convert the model object to an array and then iterate over it
$results=ArrayHelper::toArray($modelTeam);
The actual problem is not where I was thinking it is, the query is alright, I used ArrayHelper::toArray($modelTeam) method to convert the model object to an array to further iterate over the array and display all the records, and that is where the problem lies.
I needed to use the second parameter $properties for the ArrayHelper::toArray(). The second argument converts properties mapping per class, as it has problems displaying the custom declared public properties of a model and the DP is declared public inside the Teams model as it is an alias in the ActiveRecrod query.
$modelTeam = Teams::find()->
select(['TM.id', 'TM.name', 'TM.status'])
->addSelect([new \yii\db\Expression('IFNULL(TM.image,\'no-image.png\') AS DP')])
->from('{{%teams}} TM')->all();
$results = ArrayHelper::toArray($modelTeam, [
'common\models\Teams' => [
'id',
'name',
'status',
'DP',
],
]);
$modelTeam = Teams::find()
->select(['T.id', 'T.name', 'T.status'])
->addSelect([new Expression('IFNULL(T.image,"no-image.png") as DP')])
->from('{{%teams}} T')
->all();
$arrTeam = $modelTeam->asArray()->all();
To use IFNULL in a select with Yii2 you must create a new expression.
$modelTeam = Teams::find()
->select(['T.id', 'T.name', 'T.status'])
->addSelect([new Expression('IFNULL(T.image,"no-image.png") as DP')])
->from('{{%teams}} T')
->all()

Laravel Eloquent - "whereNotIn" using a subquery?

I'm struggling to figure out how I can use this SQL with eloquent methods.
SELECT * FROM artists WHERE artists.id NOT IN
(SELECT artist_id FROM artist_issues WHERE issue = 'update_images')
I see that the "whereNotIn" method takes a column, and then an array as the second parameter, so it's not possible to pass a subquery.
Any ideas how I could do this?
Thanks.
Assuming you have the correct relationships set, it should be something like this:
$artists = Artist::whereHas('artist_issues', function(q) {
$q->where('issue', '<>', 'update_images');
});
I guess you have something like this in your Artist model:
public function artist_issues()
{
return $this->belongsTo('App\ArtistIssue');
}

use "()" in Fuelphp query builder

I'd like to use "()" in fuelphp's sql like this.
select * from shop where (item1=$item1 or item2=$item1) and flag=on;
I tried to express it like this;
$shop_query = DB::select()->from('shop');
$shop_query->where(function($shop_query){
$shop_query->where('item1','=',$item1)
->or_where('item2','=',$item1);
$shop_query ->and_where('flag','=','on');
However, This shows error: undefined index item1.$item1, and surely it has values.
How could I solve this?
You can use the grouping ->where_open/close method of the query builder:
public static function whatever($item1, ... the rest of your args)
{
$shop_query = DB::select()
->from('shop')
->where('flag', 'on')
->and_where_open()
->where('item1', $item1)
->or_where('item2', $item1)
->and_where_close()
->execute()->as_array(); // just change this to whatever you need
return $shop_query;
}
This turns into:
SELECT * FROM `shop` WHERE `flag` = 'on' AND (`item1` = '$item1' OR `item2` = '$item1')

PHP Doctrine toArray problem

I have a problem with the toArray() method in Doctrine. Its doesn't get my relations:
First query :
$q = Doctrine::getTable('posts')->find(1);
debug($q->toArray(true));
Print the postid=1 with out the relations
$q = Doctrine::getTable('posts')->find(1);
$q->Tags->toArray();
debug($q->toArray(true));
...prints the results with tag relation.
But i want to do:
Doctrine::getTable('posts')->findAll()->toArray(true);
...and get all of relations of posts , instead I got an array of post row.
Any idea about how to make it work with the relations?
(notice i added toArray(true) for deep property.
thanks for any help
You could create named query for this table with all relations attached:
Doctrine::getTable('posts')->addNamedQuery('get.by.id.with.relations', 'DQL here...');
And then just use something like this:
Doctrine::getTable('posts')->find('get.by.id.with.relations', array(123));
I beleive you need to do a Join with the query. Otherwise it doesnt hydrate the realated data.
$q = Doctrine_Query::create()
->from('Post p')
->leftJoin('p.RelatedModel1 rm1')
->leftJoin('p.RelatedModel2 rm2');
$q->findAll()->toArray(true);
$q = Doctrine_Query::create()
->from('Post p')
->leftJoin('p.RelatedModel1 rm1')
->leftJoin('p.RelatedModel2 rm2');
$q->findAll()->toArray(true);
Can i Add ->limit()->offset()
to the query ?
I guss that if i first create the query then findAll will act the same as execute right ?

Categories