Doctrine2 Native Query ManyToMany - php

I've read the Doctrine2 documentation about native sql queries.
It doesn't talk about entities joined by a ManyToMany relation.
I didn't figure how to handle that, any idea or example.

You just have to manually add the join table into the sql. Extending the example in chpt 14 of the Doctrine manual:
$rsm = new ResultSetMapping;
$rsm->addEntityResult('User', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addJoinedEntityResult('Address' , 'a', 'u', 'address');
$rsm->addFieldResult('a', 'address_id', 'id');
$rsm->addFieldResult('a', 'street', 'street');
$rsm->addFieldResult('a', 'city', 'city');
$sql = 'SELECT u.id, u.name, a.id AS address_id, a.street, a.city FROM users u ' .
'INNER JOIN address__user j ON u.id = j.user '.
'INNER JOIN address a ON a.id = j.address '.
'WHERE u.name = ?';
$query = $this->_em->createNativeQuery($sql, $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
This example assumes your join table has fields address and user for its keys.

Related

How to write sql query in yii2

I have a raw sql query which i run using yii2 Yii::$app->db->createCommand() but then i wonder i how i can use yii's method of writing queries to actualize the same thing.
$m = "SELECT p.basic_plan_amt AS basic,p.premium_plan_amt AS premium,p.daju_plan_amt AS daju,c.name
AS country FROM price p LEFT JOIN country c ON p.country_id = c.id WHERE p.country_id = " .$country_id;
though the above query works well and provide expected result, but then how can i write the same query using the below format
$model = \backend\models\Price::find()->select([p.basic_plan_amt AS basic,p.premium_plan_amt AS
premium,p.daju_plan_amt AS daju,c.name
AS country])->where(['country_id' => $country_id])->all();
Below are the examples of query in yii hope it will help you More reference
Relation Model
$model = User::find()
->with('comments')
->all();
foreach ($model as $user) {
// get data from relation model
$comments = $user->comments;
......
foreach($comments as $comment){
........
}
}
joinWith()
Sample 1:
$model = User::find()
->joinWith('comments')
->all();
Sample 2:
$model = User::find()
->joinWith('comments')
->orderBy('tbl_comments_id.id, tbl_user.id')
->all();
innerJoinWith()
$model = User::find()
->innerJoinWith('comments', false)
->all();
// equivalent to the above
$model = User::find()
->joinWith('comments', false, 'INNER JOIN')
->all();
Join()
JOIN_TYPE = INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN etc
Syntax
$query = new Query;
$query ->select(['SELECT COLUMNS'])
->from('TABLE_NAME_1')
->join( 'JOIN_TYPE',
'TABLE_NAME_2',
'TABLE_NAME_2.COLUMN =TABLE_NAME_1.COLUMN'
);
$command = $query->createCommand();
$data = $command->queryAll();
Sample 1:
$query = new Query;
$query ->select([
'tbl_user.username AS name',
'tbl_category.categoryname as Category',
'tbl_document.documentname']
)
->from('tbl_user')
->join('LEFT OUTER JOIN', 'tbl_category',
'tbl_category.createdby =tbl_user.userid')
->join('LEFT OUTER JOIN', 'tbl_document',
'tbl_category.cid =tbl_document.did')
->LIMIT(5) ;
$command = $query->createCommand();
$data = $command->queryAll();
Output Query
SELECT `tbl_user`.`username` AS `name`, `tbl_category`.`categoryname` AS `Category`
FROM `tbl_user`
LEFT OUTER JOIN `tbl_category` ON tbl_category.createdby =tbl_user.userid
LEFT OUTER JOIN `tbl_document` ON tbl_category.cid =tbl_document.did
LIMIT 5
leftJoin()
Sample 1:
$query = new Query;
$query ->select(['tbl_user.username AS name', 'tbl_category.type as Category'])
->from('tbl_user')
->leftJoin('tbl_category', 'tbl_category.createdby = tbl_user.userid')
->limit(2);
$command = $query->createCommand();
$data = $command->queryAll();
Output Query
SELECT `tbl_user`.`username` AS `name`, `tbl_category`.`type` AS `Category`
FROM `tbl_user`
LEFT JOIN `tbl_category` ON tbl_category.createdby = tbl_user.useridd
LIMIT 2
use createcommand() method:
use yii\db\Query();
$connection = \Yii::$app->db;
$query = new Query;
$insql = $connection->createCommand("SELECT* FROM inventory );
$result=$insql->queryAll();
the above method list all data from the inventory table.

Subquery With Yii Active Record

Is it possible to write sub queries with Yii active record?
I need to add a subquery in the FROM clause. Below is the SQL with the subquery but I want to specifically write it using Active Record.
In SQL, Policy has a many to many relationship with policy_vehicles.
SQL Query:
select * from (SELECT Name , GROUP_CONCAT(PV.VehicleId SEPARATOR ',') as VehicleIds
FROM `policies` `t`
LEFT JOIN policy_vehicles PV USING(PolicyId)
WHERE (Type IN ('C', 'E')) AND (Status='Active')
GROUP BY t.PolicyId
) k where VehicleIds like '%1%' AND VehicleIds like '%2%'
This is how I want to use it in the Controller class:
$model = Policy::model();
$model->Status = array('Active');
$model->VehicleIds = array(1,2);
$model->Type = array('C', 'E');
$datas = $model->search()->getData();
print_r($datas);
Search function in the model:
public function search() {
$joins = array();
$criteria = new CDbCriteria;
$criteria->compare('Type', $this->Type);
$criteria->compare('Status', $this->Status);
array_push($joins, 'LEFT JOIN policy_vehicles PV USING(PolicyId)');
$criteria->join = implode(' ', $joins);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}

Convert from query to ModelSearch of Yii2

I'm new in Yii2, and I have a query with right result:
SELECT DISTINCT workloadTeam.project_id, wp.project_name, workloadTeam.user_id, workloadTeam.commit_time, wp.workload_type FROM
(SELECT p.id, p.project_name, w.user_id, w.commit_time, w.comment, w.workload_type
FROM workload as w, project as p
WHERE w.user_id = 23 AND p.id = w.project_id) wp
INNER JOIN workload as workloadTeam ON wp.id = workloadTeam.project_id
But in my ModelSearch.php, I wrote:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select('p.id', 'p.project_name', 'w.user_id', 'w.commit_time', 'w.comment', 'w.workload_type')
->from(['project as p', 'workload as w'])
->where(['user_id' => $user_id, 'p.id' => 'w.project_id']);
$query = Workload::find()
->select(['workloadTeam.project_id', 'wp.project_name', 'workloadTeam.user_id', 'workloadTeam.from_date', 'workloadTeam.to_date', 'workloadTeam.workload_type', 'workloadTeam.comment'])
->where(['', '', $subquery]);
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
It happended error:
SELECT COUNT(*) FROM `workload` INNER JOIN `workload` `workloadTeam` ON wp.id = workloadTeam.project_id WHERE `` (SELECT p.project_name `p`.`id` FROM `project` `p`, `workload` `w` WHERE (`user_id`=20) AND (`p`.`id`='w.project_id'))
And I can't fix it with right query above.
You have any solution about this?
Is this error shown in the Yii-debug toolbar? Then your query (which you mentioned as error) is probably only the count from the query which is listed before.
You missed to add the sub-query in from clause like you shown in your working sql. Add this in your where clause were just the wrong place. Put sub-queries in whereconditions, if you have scalar results, because you have to use this result with operands like =, >=, in...
This could work:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select([
'p.id as id',
'p.project_name as project_name',
'w.user_id as user_id',
'w.commit_time as commit_time',
'w.comment as comment',
'w.workload_type as workload_type'
])
->from([
'project as p',
'workload as w'
])
->where([
'user_id' => $user_id,
'p.id' => 'w.project_id'
]);
$query = Workload::find()
->select([
'workloadTeam.project_id',
'wp.project_name',
'workloadTeam.user_id',
'workloadTeam.from_date',
'workloadTeam.to_date',
'workloadTeam.workload_type',
'workloadTeam.comment'
])
->from([$subquery => 'wp']); //you were missing this line
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
But you don't use any selects from your workload table in your main-query $query...
Since I don't know what's your goal to achieve I can't help you at this topic...

How to build a Docterine Inner Join Query in Symfony

Im working on a Symfony project and I want to create Doctrine Query for this SQL.
USER table :
columns -
NICK_NAME
REVIEWS table:
columns -
USER_ID
, REVIEW,
CREATED_AT
Thank you
SELECT
`USER`.NICK_NAME,
REVIEWS.REVIEW,
REVIEWS.CREATED_AT
FROM
REVIEWS
INNER JOIN `USER` ON REVIEWS.USER_ID = `USER`.ID
WHERE
REVIEWS.MOVIE_ID = 625
GROUP BY
REVIEWS.USER_ID
I tried something like this
$q = Doctrine_Query::create()
->select("u.NICK_NAME,r.REVIEW,r.CREATED_AT")
->from('REVIEWS r')
->innerJoin('`USER` ON REVIEWS.USER_ID = `USER`.ID')
->where('REVIEWS.MOVIE_ID = 625')
->groupBy('REVIEWS.USER_ID');
and got this:
500 | Internal Server Error | Doctrine_Exception Couldn't find class `USER`
Without using complex DQL in Symfony you can use simple SQL.
Try this function in the controller where you want to run the DQL.
function getUserReviews($params) {
$query = "SELECT REVIEWS.REVIEW, `USER`.NICK_NAME, REVIEWS.CREATED_AT FROM REVIEWS INNER JOIN `USER` ON REVIEWS.USER_ID = `USER`.ID WHERE REVIEWS.MOVIE_ID ='".$params."'";
return Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query);
}
You Should Specify Entity name not table name in DQL like this YourBundleName:EntityName
Use it like this:
$q = Doctrine_Query::create()
->select("u.NICK_NAME,r.REVIEW,r.CREATED_AT")
->from('REVIEWS r')
->innerJoin('YourBundleName:EntityName ON REVIEWS.USER_ID = `USER`.ID')
->where('REVIEWS.MOVIE_ID = 625')
->groupBy('REVIEWS.USER_ID');
Alternative Solution if above solution doesn’t work:
$q = Doctrine_Query::create()
->select("u.NICK_NAME,r.REVIEW,r.CREATED_AT")
->from('REVIEWS r')
->innerJoin('YourBundleName:EntityName', 'USER_ID')
->where('REVIEWS.MOVIE_ID = 625')
->groupBy('REVIEWS.USER_ID');
If that doesn't work, use Inner join in following manner:
->InnerJoin('YourBundleName:Entity', '<alias>', Expr\Join::ON, $qb->expr()->eq('IDENTITY(<alias.<clummn_name>)', '<comapring_column>'))
inner Join from Doctrine2 Documentation:
Example -
$qb->innerJoin('u.Group', 'g', Expr\Join::WITH, qb->expr()->eq('u.status_id', '?1'))
$qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1')
$qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1', 'g.id')
innerJoin Method Prototype:
innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null);
Find More Here
Hope this will help you.

how to use join in yii

How to join using table model
model name:User
Query:
SELECT
DISTINCT (u.UserID),
u.usertypeid,
u.UserName
FROM user u, lkusergroup lug, `group` g
WHERE u.userid = lug.userid
AND g.groupid = lug.groupid
AND UserName = 'abcd';
Something like this but using model
$user = Yii::app()->db->createCommand()
->select('*')
->from('user u')
->join('lkusergroup lug', 'u.userid = lug.userid')
->join('group g', 'g.groupid = lug.groupid')
->where('UserName=:UserName', array(':UserName'=>$this->username))
->queryRow();

Categories