Yii 2.0 table alias in SQL query - yii2

I am using Yii2.0 and I have following error when I doing filtering with relationship:
Exception (Database Exception) 'yii\db\Exception' with message
'SQLSTATE[42S22]: Column not found: 1054 Unknown column
'userContact.email' in 'where clause' The SQL being executed was:
SELECT tbl_user.* FROM tbl_user LEFT JOIN tbl_user_contact ON
tbl_user.id = tbl_user_contact.user_id WHERE
userContact.email='me#me.com'
And it is obvious that the table name alias is not given. Following is my code that generate the query above:
Class Files
class User extends ActiveRecord{
public function getUserContacts(){
return $this->hasMany(UserContact::className(), ['user_id' => 'id']);
}
}
class UserContact extends ActiveRecord {
public function getUser(){
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
}
Query
User::find()->joinWith('userContacts', false)
->where(['userContact.email' => $email])
->one();
I follow the instruction given here.
Is there a way to have the alias in the query?

Use method "alias('string')".
User::find()->alias('u')->joinWith(['userContacts' => function($query) use ($email){
$query->alias('uc')->where(['uc.email' => $email])
}])
->one();
Look this API doc

In MySQL, your user table is called tbl_user_contact. However, you are referring to it as userContact, which results in the error.
When adding conditions, you should refer to fields using the actual table name. Here's the proper code:
User::find()->joinWith('userContacts', false)
->where([UserContact::tableName().'.email' => $email])
->one();
You could just replace UserContact::tableName().'.email' with tbl_user_contact.email, but using tableName() is better practice.

ActiveQuery extends of Query, you can use methods of query in ActiveQuery:
$query = \app\models\db\AnuncioConsulta::find();
$query->from(\app\models\db\AnuncioConsulta::tableName() . ' as ac' );
$query->join = [
['INNER JOIN', 'anuncio as a' , ' a.id = ac.anuncio_id AND a.status = 1 '],
['INNER JOIN', 'autor as au' , ' au.id = a.autor_id AND au.agente_inmobiliario = 0 '],
['INNER JOIN', 'usuario as u' , ' u.id = au.object_id '],
];
$query->andWhere('ac.news =:status' , [':status' => 1 ]);
$query->andWhere('ac.delete =:status' , [':status' => 0 ]);
$query->andWhere('u.id =:userId' , [':userId' => Yii::$app->user->id ]);
return new \yii\data\ActiveDataProvider([
'query' => $query,
]);

Related

Left join in select query Yii2 - Unknown column 'single' in 'on clause'

Why this query is not working?
public function actionInsert()
{
$model = new NotificationsEvents();
$date_at = (new Query())
->select(['single-events.date_at'])
->from('single-events')
->leftJoin('user', 'user.birthday = single-events.date_at');
$event_id = (new Query())
->select(['single-events.id'])
->from('single-events')
->leftJoin('user', 'user.id = single-events.id');
(new Query())->createCommand()->insert('notifications_events', [
'type' => 7,
'date_at' => $date_at,
'event_id' => $event_id,
])->execute();
}
I need to insert user birthday in notifications_events.date_at, and user ID in notifications_events.event_id, but this code is not working:
Unknown column 'single' in 'on clause'
single-events is not a valid/safe name for table, because it contains -. You should either quote it in every possible place:
public function actionInsert() {
$model = new NotificationsEvents();
$date_at = (new Query())
->select(['{{single-events}}.date_at'])
->from('single-events')
->leftJoin('user', 'user.birthday = {{single-events}}.date_at');
$event_id = (new Query())
->select(['{{single-events}}.id'])
->from('single-events')
->leftJoin('user', 'user.id = {{single-events}}.id');
(new Query())->createCommand()->insert('notifications_events', [
'type' => 7,
'date_at' => $date_at,
'event_id' => $event_id,
])->execute();
}
Or use some more practical name for table, like single_events.
Another quoting method: using backtics:
`single-events`

Zend Framework 2 SQL Join Issue

I am trying to use two left outer joins with Zend Framework 2's SQL classes but for some reason it is not returning one result but the other one is working fine. I've ran the actual SQL in MySQL Workbench and it returns just like I want but it is not doing it with Zend Framework. Here is my code:
Pure SQL:
SELECT groups.group_name, members.username, groups.id FROM groups
LEFT OUTER JOIN group_admins ON groups.id = group_admins.group_id
LEFT OUTER JOIN members ON group_admins.user_id = members.id
WHERE group_admins.user_id = " . parent::getUserId()['id']
This returns the result I wish, (which can be seen here: http://imgur.com/8ydmn4f)
Now, here is the Zend Framework 2 code I have in place:
$select_admins = new Select();
$select_admins->from(array(
'g' => 'groups',
))
->join(array(
'ga' => 'group_admins'
), 'g.id = ga.group_id')
->join(array(
'm' => 'members'
), 'ga.user_id = m.id', array('username'))
->where(array('ga.user_id' => parent::getUserId()['id']));
$query_group_admin = parent::$sql->getAdapter()->query(parent::$sql->buildSqlString($select_admins), Adapter::QUERY_MODE_EXECUTE);
$group_admins = array();
foreach ($query_group_admin as $group_admin) {
$group_admins[] = $group_admin;
}
// get the group members
$select = new Select();
$select->from(array(
'g' => 'group_members'
))
->join(array(
'm' => 'members'
), 'g.member_id = m.id')
->join(array(
'grp' => 'groups'
), 'g.group_id = grp.id')
->where(array(
'g.group_id' => $group_id
));
$query = parent::$sql->getAdapter()->query(parent::$sql->buildSqlString($select), Adapter::QUERY_MODE_EXECUTE);
$member_username = array();
foreach ($query as $member) {
$member_username[] = $member['username'];
}
// get the rest of the group info
$fetch = $this->gateway->select(array(
'id' => $group_id
));
$row = $fetch->current();
if (!$row) {
return false;
}
return array(
'admins' => implode(", ", $group_admins),
'members' => implode(", ", $member_username),
'info' => $row
);
Controller:
public function grouphomeAction()
{
$id = $this->params()->fromRoute('id', 0);
if (0 === $id) {
return $this->redirect()->toRoute('members/groups', array('action' => 'index'));
}
if (!$this->getGroupsService()->getGroupInformation($id)) {
return $this->redirect()->toRoute('members/groups', array('action' => 'index'));
}
return new ViewModel(array('group_info' => $this->getGroupsService()->getGroupInformation($id)));
}
However, this only shows the group name, group creator and group members but leave the group admins field empty.
Here is the print_r result of the array returned:
Array ( [admins] => [members] => jimmysole, fooboy [info] => ArrayObject Object ( [storage:ArrayObject:private] => Array ( [id] => 2 [group_name] => Tim's Group [group_creator] => timlinden [group_created_date] => 2017-01-16 17:39:56 ) ) )
If it helps, here is a screenshot as well of the page - http://imgur.com/xUQMaUu
Any help would be appreciated!
Thanks.
Basically your joins are INNER JOINS...I know....you must hate Zend right now :p . By default they are INNER JOINS so i assume that is what is wrong. SO try to specify the type of join and you should be fine. You can find more examples here: examples
$select12->from('foo')->join('zac', 'm = n', array('bar', 'baz'), Select::JOIN_OUTER);

Cakephp 3 findAuth join table return array

I am attempting to implement a role based authentication system using a custom finder.
public function findAuth(\Cake\ORM\Query $query, array $options)
{
$query
->select(['id', 'username', 'passwordHash', 'locked', 'roles.role'])
->group('username')
->join([
'table' => 'user_roles',
'conditions' => ['user_roles.userid = Users.id']])
->join([
'table' => 'roles',
'conditions' => ['roles.id = user_roles.role']])
->toArray()
;
return $query;
}
The resulting mysql query i need is:
select users.id, username, passwordHash, locked, group_concat(roles.role) role from users INNER JOIN user_roles on user_roles.userid = users.id INNER JOIN roles on roles.id = user_roles.role group by users.id
What I finally ended up going with is this:
public function findAuth(\Cake\ORM\Query $query, array $options)
{
$query
->select(['id', 'username', 'passwordHash', 'locked'])
->join([
'table' => 'user_roles',
'conditions' => ['user_roles.user_id = Users.id']])
->contain(['UserRoles.Roles'])
->join([
'table' => 'roles',
'conditions' => ['roles.id = user_roles.role']])
->group(['Users.username']);
return $query;
}
This gives me a multi-dimensional array of:
user_roles[index[id, user_id, roles[id, role]]]
in my case I have 2 entries for the index (0 and 1) and I can check the role of the user with the in_array function within a foreach loop

cakephp2 join two tables from two database

I have developing a SAAS based site, which i have to join two tables from two DBs, say table1 from DB1 and table2 from DB2. I have to get the matching records from table1 and table 2 using join in cakephp, but it throws error as below :
Error: SQLSTATE[42000]: Syntax error or access violation: 1142 SELECT command denied to user 'dbname'#'localhost' for table 'table_name' .
can anyone explain me how to done this using cakephp .
class table1 extends AppModel{
public $useDbConfig = 'DB1';
}
Class table2 extends AppModel{
public $useDbConfig = 'DB2';
function desc(){
$this->Store->useDbConfig = 'default';
$rslted = $this->find('all',array(
'conditions' => array('Jewel.id' =>1),
'joins' => array(
array(
'alias' => 'Store',
'table' => 'stores',
'type' => 'INNER',
'conditions' => 'Store.id = Jewel.store_id'
)
)
));
return $rslted;
}
}
while called the desc function from controller is not working throws error:
Base table or view not found: 1146 Table 'site1.site1_stores' doesn't exist
but using the hasmany or belongsto on model will working , the join query is not working in controller
Please follow the steps:
Step 1: Create two models named Jewel.php and Store.php for model classes
Content of Jewel.php
class Jewel extends AppModel{
public $useDbConfig = 'DB1';
}
Content of Store.php
Class Store extends AppModel{
public $useDbConfig = 'DB2';
}
Step 2: Create one method in Store model as shown below
function getData(){
$this->bindModel(array(
'hasOne' => array(
'Jewel' => array(
'foreignKey' => false,
'conditions' => array('Store.id = Jewel.store_id')
)
)
));
$returnData = $this->find('all',array('conditions' => array('Jewel.id' =>1)));
}
Hope this will help!

Zend Framework 2: LEFT JOIN issue

public function getInterests($userID) {
$result = $this->tableGateway->select(function (Select $select) use ($userID) {
$select->join('interests', 'users_interests.interest_id = interests.interest_id', array('*'), 'left');
$where = new Where();
$where->equalTo('user_id', $userID);
$select->where($where);
});
return $result;
}
Here is my method. It simply selects all records from users_interests with user_id = $userID and joins the 'interests' table. So far, so good, but when trying to display the fetched results, the fields from the joined table just do not exist. Here is the dump of the $result:
Zend\Db\ResultSet\ResultSet Object
(
[allowedReturnTypes:protected] => Array
(
[0] => arrayobject
[1] => array
)
[arrayObjectPrototype:protected] => Object\Model\UsersInterests Object
(
[settings_id] =>
[user_id] =>
[interest_id] =>
)
[returnType:protected] => arrayobject
[buffer:protected] =>
[count:protected] => 2
[dataSource:protected] => Zend\Db\Adapter\Driver\Pdo\Result Object
(
[statementMode:protected] => forward
[resource:protected] => PDOStatement Object
(
[queryString] => SELECT `users_interests`.*, `interests`.* FROM `users_interests` LEFT JOIN `interests` ON `users_interests`.`interest_id` = `interests`.`interest_id` WHERE `user_id` = :where1
)
[options:protected] =>
[currentComplete:protected] =>
[currentData:protected] =>
[position:protected] => -1
[generatedValue:protected] => 0
[rowCount:protected] => 2
)
[fieldCount:protected] => 6
[position:protected] =>
)
I badly need help on this because I am supposed to finish my project until Sunday. Thanks in advance.
You can use the following to apply left join. $select::JOIN_LEFT instead of 'left'.
public function getInterests($userID) {
$result = $this->tableGateway->select(function (Select $select) use ($userID) {
$select->join('interests', 'users_interests.interest_id = interests.interest_id', array('*'), $select::JOIN_LEFT);
$where = new Where();
$where->equalTo('user_id', $userID);
$select->where($where);
});
return $result;
}
It seems you have a problem in the WHERE clause of the join. This also shows in the error here:
[queryString] => SELECT `users_interests`.*, `interests`.* FROM `users_interests` LEFT JOIN .
`interests` ON `users_interests`.`interest_id` = `interests`.`interest_id`
WHERE `user_id` = :where1
Try this:
$select->from($this->table)
->join('interests', 'users_interests.interest_id = interests.interest_id',
array('*'), 'left');
$where = new Where();
$where->equalTo('user_id', $userID) ;
$select->where($where);
I can not follow your code completely, like here:
$this->tableGateway->select(function (Select $select) use ($userID) {
But, here is a very nice article on this. I think, you can simplify your code a little.
Have you iterated over the resultset? You can see there's two matching rows:
[rowCount:protected] => 2
You have a ResultSet object, but it will not load any of the rows until requested, they are "lazy loaded" when you iterate over the object.
You can force the resultset to get them all for you:
var_dump($resultSet->toArray()); // force load all rows
or iterate over the ResultSet:
foreach($resultset as $row) {
var_dump($row); // each row loaded on request
}
I have written about this before and maybe it will help you as well.
TableGateway with multiple FROM tables