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可以靜態調用;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章