Question

I have query like this:

SELECT * FROM activity
WHERE (((userId = 1 OR userId IN(SELECT userId FROM follower WHERE followerId = 1))
AND activityType IN(1, 2, 3))
OR (targetId = 24 AND aType IN(1, 2, 3, 4, 5)))
ORDER BY id DESC;

I have try to use model()->findAllBySql($sql) and it works. But I want to make it using CDbCriteria, if you have another solutions let me know it :D

Was it helpful?

Solution

You could still build this statement with a CDbCriteria I think... something like:

$criteria=new CDbCriteria;
$criteria->condition = '
  (
    (
      userId = 1 OR 
      userId IN (SELECT userId FROM follower WHERE followerId = 1)
    )
    AND activityType IN(1, 2, 3)
  )
  OR (
    targetId = 24 
    AND aType IN(1, 2, 3, 4, 5)
  )
';
$criteria->order = 'id DESC';
$results=Activity::model()->findAll($criteria);

As this point you might as well just write a regular SQL statement, but there might be some benefits to doing it this way: binding params, merging criteria, adding additional criteria, etc.

OTHER TIPS

As long as your plain SQL works, you're safe. There are many times when I have to throw Active Record away and just get the job done in the ol' saner way.

I tried to translate this query into a readable CDbCriteria construction. Bad idea. Yii sucks when it comes to query complex data.

The answer can be found here: http://www.yiiframework.com/doc/guide/1.1/en/database.dao#executing-sql-statements

In your case:

$sql = 'SELECT * FROM activity';
$sql .= 'WHERE (((userId = 1 OR userId IN(SELECT userId FROM follower WHERE followerId = 1))';
$sql .= 'AND activityType IN(1, 2, 3))';
$sql .= 'OR (targetId = 24 AND aType IN(1, 2, 3, 4, 5)))';
$sql .= 'ORDER BY id DESC';

$connection = Yii::app()->db;
$command = $connection->createCommand($sql);
$results = $command->queryAll();

@pestaa is right that sometimes you have to throw active record out the window. This is especially true if you're doing mass updates where looping through numerous models is horribly inefficient.

Just use CSqlDataProvider http://www.yiiframework.com/doc/api/1.1/CSqlDataProvider

Disclaimer: I know it's not precise answer to this particural question but it might help work around the problem that was given. I suspect the main purpose of this question is getting way to use CGridView, CListView etc. with arbitrary SQL.

I use CDbCriteria for complex queries in which I use the with feature.

You can build complex criteria like this:

$dbCriteria->with=array(
   '<relation1>'=>array( 'condition'=>'<condition for given relation>',
        'with'=>array('<relation2:relation of relation1>'
            =>array(<conditions for relation2>)
        )
        'scopes'=><scopes for relation1>
    )
);

I have not checked how OR can get into play here.

By using scopes, you can also insert some more complex criteria and still keep your search condition readable.

This is pretty powerful. I didn't see a complete 'tutorial' about this yet; I kind of concluded this from the source code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top