how to convert mysql subquery to yii CDbCriteria
table list:
1) user_group
2) user_group_data
3) user_group_data_revision
select * from (
select
ugd.group_id as group_id,
ug.user_id as user_id,
ugd.id as group_data_id,
ugd.group_name as group_name,
ugd.group_description as group_description,
ugd.email as group_admin_email,
ugd.image as group_image,
ugd.group_type as group_type,
ugd.request_type as group_request_type,
ugdr.revision_version as revision_version,
ugdr.admin_approve as revision_approve_status,
ugdr.publish as revision_publish,
ugdr.created_at as revision_created_at
from user_group_data_revision ugdr
left join user_group_data ugd on ugdr.group_data_id = ugd.id
left join user_group ug on ugdr.group_id = ug.id
order by `revision_version` desc
) rgd group by rgd.group_id
Here a small example(if I correctly understood structure/relations):
//Model UserGroupDataRevision
class UserGroupDataRevision extends CActiveRecord
{
public function relations()
{
return array(
'userGroup' => array(self::BELONGS_TO, 'UserGroup', 'group_id'),
'userGroupData' => array(self::BELONGS_TO, 'UserGroupData', 'group_data_id'),
);
}
//....
}
//model UserGroup
class UserGroup extends CActiveRecord {...}
//model UserGroupData
class UserGroupData extends CActiveRecord {...}
Criteria:
$criteria = new CDbCriteria();
$criteria->select = 'ugdr.revision_version'; // other fields
$criteria->alias = 'ugdr';
$criteria->with = array(
'userGroup' => array(
'alias' => 'ug',
'together' => true,
'select' => array('ug.user_id'), // other fields
),
'userGroupData' => array(
'alias'=> 'ugd',
'together' => true,
'select'=>array('ugd.group_id, ugd.group_name'), // other fields
),
);
$criteria->group = 'rgd.group_id';
$criteria->order = 'rgd.group_id'; // or something else
Data checking:
$dataProvider = new CActiveDataProvider('UserGroupDataRevision', array(
'criteria' => $criteria,
)
);
var_dump($dataProvider->getData());
die();
Related
i need to use yii1 CGridView with the custom SQL.
i have followed this article
inside model I've created
public function searchUserStats()
{
$count = Yii::app()->db->createCommand()
->select('count(DISTINCT user_id)')
->from('casino_sg_sessions')
->queryScalar();
$sql = '
SELECT
SUM(bet) bet_sum,
SUM(win) win_sum,
SUM(bet_count) bet_count,
user_id,
userName,
modified
FROM
(SELECT
(SELECT IFNULL(SUM(tr1.amount), 0) FROM casino_sg_transactions tr1 WHERE t.id = tr1.session_id AND tr1.action = \'bet\' ) AS bet,
(SELECT IFNULL(SUM(tr2.amount), 0) FROM casino_sg_transactions tr2 WHERE t.id = tr2.session_id AND tr2.action = \'win\' ) AS win,
(SELECT count(0) FROM casino_sg_transactions tr3 WHERE t.id = tr3.session_id) AS bet_count,
t.user_id,
u.userName,
t.modified
FROM `casino_sg_sessions` t
INNER JOIN user u ON u.id = t.user_id
ORDER BY modified DESC
) user_stats
GROUP BY user_id
ORDER BY modified DESC
';
$command = Yii::app()->db->createCommand($sql);
$dataProvider = new CSqlDataProvider($command, array(
'totalItemCount'=>$count,
'pagination'=>array(
'pageSize'=>15,
),
));
return $dataProvider;
}
in the controller:
$model = new CasinoSgSessions('searchUserStats');
$this->render('index', array(
'model' => $model,
));
inside the view i call it this way:
$this->widget('application.widgets.grid.CGridView', array(
'dataProvider' => $model->searchUserStats(),
'filter' => $model,
'columns' => array(
[
'header' => 'User ID',
'name' => 'user_id',
'value' => '$data->user_id',
'htmlOptions' => array('width'=>'150px'),
],
.....
.....
i receive paginated grid without data.
spent huge amount of time and now gave up, what i did wrong ?
sql query itself works good.
PS: i cant use mysql views and create model for the view.
PPS: query will be a bit more complex, so the only way i see is using CGridView through the sql query.
in the template instead of
$data->user_id
i had to use
$data['user_id']
absolutely not expected behavior. Seems to me they didn't hear about SOLID
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);
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
I have 3 models:
User
Like
Post
Like has 2 foreign key set using CakePHP convention on user_id and post_id (that are the id column of the other 2 models).
I want to run a find that mime the LEFT JOIN in sql on Post with a condition on the foreign key.
In detail i want:
1: all the posts.
1a: if the post have a like from the user XXX I want it included in the result
1b: else the post doesn't have a ->Like attribute.
So, if i do this:
$posts = $this->Post->find('all');
in $posts i have all the posts, and for each posts all the likes.
Reading the book, I feel like i should write something like:
$options['joins'] = array(
array('table' => 'likes',
'alias' => 'Likes',
'type' => 'LEFT',
'conditions' => array(
'Post.id = Likes.post_id',
'Likes.user_id = 536f6a29-babc-4724-a74d-2ce100000000'
)
)
);
$posts = $this->Post->find('all', $options);
But this doesn't work.
Hope this is clear.
well you need put in your models
class User extends AppModel
{
public $useTable = 'users';
public $primaryKey = 'id';
public $hasMany = array(
'Post',
'Like'
);
}
class Post extends AppModel
{
public $useTable = 'posts';
public $primaryKey = 'id';
public $belongsTo = array('User');
public $hasMany = array(
'Like'
);
}
class Like extends AppModel
{
public $useTable = 'likes';
public $primaryKey = 'id';
public $belongsTo = array('Post','User');
}
and in you controller
$this->loadModel("User");
$query = $this->User->find('all', array(
'joins' => array(
array(
'table' => 'posts',
'alias' => 'Post',
'type' => 'LEFT',
'conditions' => array(
'User.id = Post.user_id'
)
),
array(
'table' => 'likes',
'alias' => 'Like',
'type' => 'LEFT',
'conditions' => array(
'User.id = Like.user_id'
)
)
),
'conditions' => array(
'Post.id = Likes.post_id',
'Likes.user_id = 536f6a29-babc-4724-a74d-2ce100000000'
),
'order' => array(
'Post.id' => 'ASC'
),
'fields' => array('Post.*','User.id'),
'recursive' => -1
));
I am trying to run two model functions from one view. The first query appears to be working fine.
The second query returns a blank array. I noticed when printing the query to the screen that the queries appear to be joining together and are not separate, like this:
JDatabaseQueryMySQL Object ( [db:protected] => JDatabaseMySQL Object ( [name] => mysql [nameQuote:protected] => ` [nullDate:protected] => 0000-00-00 00:00:00 [dbMinimum:protected] => 5.0.4 [_database:JDatabase:private] => Curling_Schedule [connection:protected] => Resource id #19 [count:protected] => 0 [cursor:protected] => Resource id #72 [debug:protected] => [limit:protected] => 0 [log:protected] => Array ( ) [offset:protected] => 0 [sql:protected] => SELECT team_name, division FROM #_autoschedTeams ORDER BY division [tablePrefix:protected] => encex [utf:protected] => 1 [errorNum:protected] => 0 [errorMsg:protected] => [hasQuoted:protected] => [quoted:protected] => Array ( ) ) [type:protected] => select [element:protected] => [select:protected] => JDatabaseQueryElement Object ( [name:protected] => SELECT [elements:protected] => Array ( [0] => sheet, id ) [glue:protected] => , ) [delete:protected] => [update:protected] => [insert:protected] => [from:protected] => JDatabaseQueryElement Object ( [name:protected] => FROM [elements:protected] => Array ( [0] => #__autoschedPlayingSheets ) [glue:protected] => , ) [join:protected] => [set:protected] => [where:protected] => [group:protected] => [having:protected] => [columns:protected] => [values:protected] => [order:protected] => JDatabaseQueryElement Object ( [name:protected] => ORDER BY [elements:protected] => Array ( [0] => sheet ) [glue:protected] => , ) [union:protected] => [autoIncrementField:protected] => )
Model:
public function getTeams()
{
// Create a new query object.
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Select some fields
$query->select('team_name, division');
// From the hello table
$query->from('#__autoschedTeams');
$query->order('division');
$db->setQuery((string)$query);
$teams = $db->loadResultArray();
$div = $db->loadResultArray(1);
$divs = array_unique($div);
$result = [];
foreach($divs as $key)
{
$result[$key] = [];
foreach(array_keys($div, $key) as $index)
{
array_push($result[$key], $teams[$index]);
}
}
return $result;
}
public function getSheets()
{
// Create a new query object.
$db = JFactory::getDBO();
print_r($query);
$query = $db->getQuery(true);
// Select some fields
$query->select('sheet, id');
// From the hello table
$query->from('#__autoschedPlayingSheets');
$query->order('sheet');
//print_r($query);
$db->setQuery($query);
$result = $db->loadResultArray();
return $result;
}
}
relevant code from View:
$teams_sched = $this->get('Teams');
$sheets_sched = $this->get('Sheets');
Change the name of the variable and check with it.
If you are not getting the result again, then print the query echo $query; and check with it.
public function getSheets()
{
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('sheet, id');
$query->from('#__autoschedPlayingSheets');
$query->order('sheet');
$db->setQuery($query);
$Sheets = $db->loadResultArray();
print_r($Sheets);
return $Sheets;
}