laravel自定义模型方法抛异常Non-static method XXX should not be called statically

目标

我在laravel项目中自定义的Model中添加了一个方法,我想像Model的其他方法如all方法一样支持在实例上调用和静态方式调用:

$flights  =  (new App\Flight)->all(); //在实例上调用
$flights  =  App\Flight::all();	//静态方式调用

我们的Model名称为AvatarPic,我编写的测试代码为:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AvatarPic extends Model
{
	 protected $table = 'avatar_pic';
	  /**
	 * @var string
	 */  
	 private $path;

	 public function test()
	 {
	 	echo 'test';
	 }
}

问题

当我在实例上调用时,代码可以正常执行:

(new App\Models\AvatarPic)->test(); // 将会打印出test

当我使用静态方式调用时,代码将会抛出异常:

App\Models\AvatarPic::test(); //将会抛出ErrorException (E_DEPRECATED)

异常描述为:

Non-static method App\Models\AvatarPic::test() should not be called statically

我的环境信息:

  • 操作系统:windows10
  • PHP版本:PHP 7.2.1
  • laravel版本:Laravel Framework 5.5.48

检测

在看过laravel中Illuminate\Database\Eloquent\Model代码后,我对laravel模型像all方法的调用方式有了初步了解。
根据Illuminate\Database\Eloquent\Model__callStatic的使用,我编写了测试代码来探测问题发生在哪里。
我编写一个测试文件test.php

<?php
class TestService
{
		public static function __callStatic($name, $arguments)
		{
			echo 't';
		}

		public function test()
		{
			echo 'test';
		}
}
TestService::test();

当我运行这个测试文件时,程序成功打印出了’test’:

laravel中的什么设置使PHP中的__callStatic抛出Non-static method xxx should not be called statically异常?
这个结果给我了实现目标的希望,几乎同样的代码,在laravel外可以正常执行。为了验证是否由于继承Illuminate\Database\Eloquent\Model造成的异常,我在laravel项目中编写了一样的代码:

<?php


namespace App\Services;


class TestService
{
    public static function __callStatic($name, $arguments)
    {
        echo '__callStatic';
    }

    public function test()
    {
        echo 'test';
    }
}

当我运行代码时,程序还是抛出了异常:

laravel中的什么设置使PHP中的__callStatic抛出Non-static method xxx should not be called statically异常?
为了排除环境因素,我在centos7、php 7.3.1、laravel 5上执行也是如此。

猜想

  1. 应该是因为laravel内部做了限制。
  2. 在laravel整个项目中搜索"Non-static method",并没有搜索结果,也就是说这个异常是php产生的,不是laravel定义的。
  3. 可能laravel内部对php的配置做了修改。

在打印的异常信息中有"ErrorException (E_DEPRECATED)",那么上面的写法在laravel中的异常级别是E_DEPRECATED,使用原生php执行没有抛异常,可能是默认的php异常级别与laravel中配置的异常级别不一致。

验证

查看laravel中的错误级别:
laravel error_reporting
查看PHP中错误级别:
PHP error_reporting
laravel中设置为报告所有异常错误,PHP设置的报告异常有
PHP error
我们修改我们在测试代码中添加error_reporting(-1)``,重新执行程序:

<?php

error_reporting(-1);
class TestService
{
    public static function __callStatic($name, $arguments)
    {
        echo 't';
    }

    public function test()
    {
        echo 'test';
    }
}

TestService::test();
(new TestService)->test();

这时,使用php执行也会抛出异常:
PHP error

结尾

虽然知道了laravel和原生php执行结果不同的原因,但使用两种方式调用的目标依然没有解决。
要想静态访问可以设置自定义方法的访问限定为protected;参考:PHP 调用静态方法不存在时首先检查方法是否是静态的而不是走__callStatic? | Laravel China 社区

  • public可以在实例上调用;
  • protected可以静态调用;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章