`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 方法?

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

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 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可能都需要修改,简直就是自找麻烦呀。
5年前 评论
HarveyNorman 3年前
ruodee

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

5年前 评论

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

5年前 评论

@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');
    }
5年前 评论

@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 通篇都没有使用(我没有发现), 也许是是保持统一性, 降低干扰吧

5年前 评论
  • 建议你复习一下什么是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可能都需要修改,简直就是自找麻烦呀。
5年前 评论
HarveyNorman 3年前

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