`Model::` 和 `$model->` 还是有区别啊

之前问过一个问题Topic:: 和 $topic-> 有区别么?
当时的代码是这样的,两种方式调用都是正常的

public function index(Request $request, Topic $topic)
{
    $topics = $topic->withOrder($request->order)->paginate(20);
    return view('topics.index', compact('topics'));
}
public function index(Request $request)
{
    $topics = Topic::withOrder($request->order)->paginate(10);
    return view('topics.index', compact('topics'));
}

因为我习惯了和实例无关的方法不用实例去调用,所以这次在活跃用户中也用了一样的写法却不好使了

public function index(Request $request)
{
    $topics = Topic::withOrder($request->order)->paginate(10);
    $active_users = User::getActiveUsers();
    return view('topics.index', compact('topics'));
}

运行报错

Non-static method App\Models\User::getActiveUsers() should not be called statically

必须写成教程那样$user->getActiveUsers(),通过实例对象去调用方法

public function index(Request $request, User $user)
{
    $topics = Topic::withOrder($request->order)->paginate(10);
    $active_users = $user->getActiveUsers();
    return view('topics.index', compact('topics'));
}

分享到这里记录一下,后面回过头再来了解其中细节:

  • php 中的静态方法到底是怎样的?
  • Topic::withOrder()User::getActiveUsers() 有什么不同?
  • 如何在不使用实例的情况下调用 getActiveUsers 方法?

如果有朋友对这个话题感兴趣 欢迎评论交流

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 7
  • 建议你复习一下什么是scope方法。看看源码,了解一下原理:scopeWithOrder ($query, $order), $query 是怎么来的
  • Topic::withOrder()和$Topic->withOrder()为什么都能使用?因为在Topic model中根本就没有这个方法,所以才会去调用魔术方法。最后调用了scopeWithOrder方法。
  • User::getActiveUsers()却会出错,而只有$User->getActiveUsers()才能得到结果: 这是因为user model中有getActiveUsers()这个方法,而作者已经定义为了非静态方法。这样就不会去调用魔术方法,从而报错”Non-static method App\Models\User::getActiveUsers() should not be called statically"
  • 为什么作者会使用非静态方法,因为你定义为静态方法后,那么\App\Models\Traits\ActiveUserHelper所有的$this可能都需要修改,简直就是自找麻烦呀。
6年前 评论
HarveyNorman 4年前
ruodee

静态方法是类方法,定义为public static function(){}是属于类的方法,实例方法是非静态方法,必须由实例调用。php之所以很乱,是因为php不是严格的面向对象。

6年前 评论

本书作者写的类方法, 就没有静态方法, 所以这里如果不是系统自带,而是自定义的方法, 全部都需要实例化后调用

6年前 评论

@beatles Topic::withOrder() 这种属于什么类型的方法

    public function scopeWithOrder($query, $order)
    {
        // 不同的排序,使用不同的数据读取逻辑
        switch ($order) {
            case 'recent':
                $query->recent();
                break;

            default:
                $query->recentReplied();
                break;
        }
        // 预加载防止 N+1 问题
        return $query->with('user', 'category');
    }
6年前 评论

@tooyond 你该看看 php 手册 语言参考--类与对象,

  • public static function a(){...} 这是静态方法, 通过 ::(双冒号, 范围解析操作符) 访问, 在类内部 使用 self::a() 来访问, 在类外部使用 类名::a() 来访问

  • public function b(){...} 这是非静态方法,通过 -> (对象操作符) 访问, 在类内部使用 $this->b()访问, 在类外部使用 类实例(也就是类的一个对象)->访问
class Person
{
    public static function sayHello()
    {// 这是静态方法
        echo 'Hello';
    }

    public function sayHi()
    {// 这是非静态方法
        echo 'Hi';
    }
}

Person::sayHello(); // 输出 Hello

$person1  = new Person();
$person1->sayHi(); // 输出 Hi

ps: 我也觉得活跃用户这种由全体对象统计出来, 而非单个对象特征的东西做成静态方法会更好一些, 但是本书上 summer 通篇都没有使用(我没有发现), 也许是是保持统一性, 降低干扰吧

6年前 评论
  • 建议你复习一下什么是scope方法。看看源码,了解一下原理:scopeWithOrder ($query, $order), $query 是怎么来的
  • Topic::withOrder()和$Topic->withOrder()为什么都能使用?因为在Topic model中根本就没有这个方法,所以才会去调用魔术方法。最后调用了scopeWithOrder方法。
  • User::getActiveUsers()却会出错,而只有$User->getActiveUsers()才能得到结果: 这是因为user model中有getActiveUsers()这个方法,而作者已经定义为了非静态方法。这样就不会去调用魔术方法,从而报错”Non-static method App\Models\User::getActiveUsers() should not be called statically"
  • 为什么作者会使用非静态方法,因为你定义为静态方法后,那么\App\Models\Traits\ActiveUserHelper所有的$this可能都需要修改,简直就是自找麻烦呀。
6年前 评论
HarveyNorman 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!