为什么在php的laravel模型类中使用静态方法?


Why use static method in PHP's laravel model class?

在PHP laravel中,我们有这样的代码

$user = User::find(1);
var_dump($user->name);

我不关心如何使用find方法,我关心为什么laravel使用静态方法?使用静态方法不应该使方法难以测试吗?

如果用单例设计会更好吗?

$user = User::getInstance()->find(1);
var_dump($user->name);

实际上,您的示例与Laravel在幕后所做的非常相似。当您执行User::find()时,您实际上是在请求一个新实例,一个Collection的实例或一个QueryBuilder的实例。

照亮'雄辩的' '数据库模型(参考):

public static function find($id, $columns = array('*'))
{
    if (is_array($id) && empty($id)) return new Collection;
    $instance = new static;
    return $instance->newQuery()->find($id, $columns);
}

作为旁注,你还会看到在Laravel中使用静态方法的另一种方式,例如Input::get()。这些被称为facade。

facade提供了"static"到应用程序的IoC容器中可用的类的接口…Laravel"facades"充当"静态代理"到IoC容器中的底层类,提供简洁、富有表现力的语法的好处,同时保持比传统静态方法更多的可测试性和灵活性。

当用户引用…上的静态方法时facade, Laravel从IoC容器解析缓存绑定,并对该对象运行请求的方法(在本例中为get)。

你可以阅读更多关于Larave的立面:http://laravel.com/docs/facades

Unnawut有一个很好的答案,但是我觉得有必要添加进一步的解释。

在你的例子中

$user = User::find(1);
var_dump($user->name);

Laravel没有使用静态方法,你是。你可能正在寻找的另一种方法是使用依赖注入,Laravel让它变得非常简单,因为它可以自动完成。因此,无论你在什么课程中使用User模型,你都应该在构造函数中设置这样的内容…

public function __construct(User $user)
{
    $this->user = $user;
}

然后你可以修改你的代码,不使用静态绑定。

$user = $this->user->find(1);
var_dump($user->name);

这将限制系统只能拥有一个User。虽然find方法可能是静态的,但User类将具有其他非静态的方法和属性,您的示例中可能有一个示例:$user->name

不依赖于任何实例变量的方法,例如,变量的值是特定于特定对象实例的,而是提供适用于所有实例的通用功能,可以并且可能应该是静态的。这就是为什么$this操作符在静态方法中是非法的,因为它不能引用特定的对象实例。

@unnawut参考链接到Model.php的源代码不再使用静态find函数,因为类已被重构。最终被调用的函数在Builder.php(源代码)中,

逻辑还是一样的

- magic function `__callStatic` of Model class get called
- a new instance of Builder is created and return
- call the find method of the Builder instance

Model.php

    public function newEloquentBuilder($query)
    {
        return new Builder($query);
    }

Builder.php

    public function find($id, $columns = ['*'])
    {
        if (is_array($id) || $id instanceof Arrayable) {
            return $this->findMany($id, $columns);
        }
        return $this->whereKey($id)->first($columns);
    }