1

I'm a Yii framework user.

mostly I define functions as public static function in my model files like the example function below.

public static function getTrashedPostCount(){           
    $connection=Yii::app()->db;     
    $sql = "SELECT COUNT(publish_status)
                FROM {{post}}
                WHERE publish_status = 'trash'";              
    $command=$connection->createCommand($sql);
    $postCount = $command->queryScalar();
    return $postCount;      
}   

I wonder if I'm doing wrong.

are most of functions in model files supposed to be static function?

Please let me know if I'm doing or understanding wrong.

Thanks!!!

tereško
  • 58,060
  • 25
  • 98
  • 150
Hayato
  • 559
  • 1
  • 10
  • 15
  • 2
    came across a good article on this question, have a look! http://www.yiiframework.com/forum/index.php/topic/14456-class-level-methods-vs-static-methods/ – Sandip Pingle Dec 10 '13 at 13:04

2 Answers2

7

Yes, you are doing it wrong.

Static methods are easy to call but have several architectural drawbacks, so generally speaking they should be used sparingly (or, even better: avoided altogether).

In this instance there is no reason to use a static method and especially one that writes custom SQL. Use Yii's named scopes to accomplish the same goal:

class Post extends CActiveRecord
{
    public function scopes()
    {
        return array(
            'trashed'=>array(
                'condition' => "publish_status = 'trash'",
            ),
        );
    }
}

And then:

$trashedCount = Post::model()->trashed()->count();
Jon
  • 428,835
  • 81
  • 738
  • 806
  • I don't know how to use Yii's named scopes. I'll look up it!! Thanks!! – Hayato Sep 03 '13 at 08:35
  • So, I'd better use public method(or private, protected) than static method. I see. – Hayato Sep 03 '13 at 08:40
  • 2
    @Hayato: It's not that the method *itself* is better if it's not `static` -- the problem is that it forces the *caller* to write "worse" code. Simple example: in `$model->foo()` the caller need not specifically know what `$model` is exactly. But with `Model::foo()` you have hardcoded the name of the class at the call site, and hardcoding stuff in general makes you less flexible. The difference may not seem that important, but it becomes more and more important as you advance your skills. – Jon Sep 03 '13 at 08:43
  • Oh thanks for your advice! I see. instance method give me more flexibility and maintainability when building application. I'll study more about OOP! Thanks!!! – Hayato Sep 03 '13 at 08:48
2

You don't want to use static methods, because then you are giving up many nice yii features such as default scopes, events etc.

Also you don't want to use raw SQL if possible, because that might complicate transition to other database system.

So you want to do something like this instead:

public function getTrashedPostCount() {
    return $this->countByAttributes(array('publish_status' => 'trash'));
}

You can see that you are using CActiveRecord's countByAttributes method and the nice thing is that default scope is applied automatically, so you don't need to take care of that. I recommend that you take some time to learn what methods are available for you to use.

You then query for number of trashed posts like this:

Posts::model()->getTrashedPostCount()

Or even by using some magic

Posts::model()->trashedPostCount
Martin Komara
  • 767
  • 6
  • 9
  • 1
    Also note that you dont have to instantiate model manually, `Posts::model()` takes care of that –  Sep 03 '13 at 08:06
  • Ok, I'll take some time to learn Active Records. I've been hesitated to use Active Records because I heard the performance speed is slower than raw SQL query. – Hayato Sep 03 '13 at 08:38
  • So, I'd better not use static method in model files. I see. – Hayato Sep 03 '13 at 08:39