解決 PhpStorm 對 用單例模式實例化PHP類時,代碼自動提示功能失效 的問題


大部分PHP框架中,為了防止一個類被重復實例化,往往采用“單例模式”實例化類。我們的項目框架是這樣做的:

先寫好一個基類 /framework/Base.class.php,內容如下:

<?php
namespace framework;

defined('SITE_PATH') or die('Access Denied');

/**
 * 業務基類
 *
 * @package framework
 */
class Base
{
	/**
	 * 類實例化(單例模式)
	 *
	 * @return mixed
	 * @throws \Exception
	 */
	public static function instance()
	{
		static $_instance = array();

		$classFullName = get_called_class();
		if (!isset($_instance[$classFullName]))
		{
			core_load_class($classFullName);
			if (!class_exists($classFullName, false))
			{
				throw new \Exception('"' . $classFullName . '" was not found !');
			}
			$_instance[$classFullName] = new $classFullName();
		}

		return $_instance[$classFullName];
	}
}
?>

某個 會員模型類 繼承 Base 基類, \common\model\MemberModel.class.php

<?php
namespace common\model;

use framework\Base;

defined('SITE_PATH') or die('Access Denied');

/**
 * 會員 模型
 */
class MemberModel extends Base
{
	protected $tableName = 'member';
	protected $pk = 'memberId';

	/**
	 * 根據memberId獲取記錄
	 *
	 * @param string $memberId 會員ID
	 * @param string $field 要顯示的字段
	 * @return array
	 */
	public function getByMemberId($memberId = '', $field = '*')
	{
		return array(); // 隨便寫下
	}
}
?>

其他方法中,使用該 會員模型,參考代碼如下:

MemberModel::instance()->getByMemberId('168');

 

遇到的問題

本以為很完美,但是在 PhpStorm 中,根本識別不了 MemberModel::instance() 實例化類的方式,它會提示 getByMemberId() 方法不存在。這很讓人崩潰,因為這樣,

1、當敲完代碼 MemberModel::instance()-> 后,PhpStorm 不會自動彈出它的 屬性/方法 下拉提示框;

2、無法通過快捷鍵 重構 MemberModel 類的 getByMemberId() 方法;

 

如何解決上述 PhpStorm 代碼自動提示功能失效的問題?

我懷疑是 PhpStorm 對基類中的代碼:

$_instance[$classFullName] = new $classFullName();
return $_instance[$classFullName];

不識別導致的!

今天在逛別人的博客時,看到對“PHP延遲靜態綁定”知識點的介紹,先前早就看到過這個概念,但一直沒有仔細去研究,查了下資料,匯總如下:

父類方法返回子類實例:PHP延遲靜態綁定

文章提到,通過 static() 方法,能返回子類的實例。static 正好是 PHP 的關鍵字,相信 PhpStorm 對它一定是很敏感的。

果不出我所料,調整了下基類方法,問題解決:

<?php
namespace framework;

defined('SITE_PATH') or die('Access Denied');

/**
 * 業務基類
 *
 * @package framework
 */
class Base
{
	/**
	 * 類實例化(單例模式)
	 */
	public static function instance()
	{
		static $_instance = array();

		$classFullName = get_called_class();
		if (!isset($_instance[$classFullName]))
		{
			core_load_class($classFullName);
			if (!class_exists($classFullName, false))
			{
				throw new \Exception('"' . $classFullName . '" was not found !');
			}

			// $_instance[$classFullName] = new $classFullName();
			// 1、先前這樣寫的話,PhpStrom 代碼提示功能失效;
			// 2、並且中間變量不能是 數組,如 不能用 return $_instance[$classFullName] 形式返回實例對象,否則 PhpStrom 代碼提示功能失效;
			$instance = $_instance[$classFullName] = new static();
			return $instance;
		}

		return $_instance[$classFullName];
	}

	/**
	 *【老版本】類實例化(單例模式)
	 *【缺陷】PhpStorm 的代碼提示功能失效
	 *
	 * @return mixed
	 * @throws \Exception
	 */
//	public static function instance()
//	{
//		static $_instance = array();
//
//		$classFullName = get_called_class();
//		if (!isset($_instance[$classFullName]))
//		{
//			core_load_class($classFullName);
//			if (!class_exists($classFullName, false))
//			{
//				throw new \Exception('"' . $classFullName . '" was not found !');
//			}
//			$_instance[$classFullName] = new $classFullName();
//		}
//
//		return $_instance[$classFullName];
//	}
}
?>

效果圖如下:

 

 

延伸閱讀:

父類方法返回子類實例:PHP延遲靜態綁定

PHP的繼承方法如何獲取子類名?get_class() 和 get_called_class()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM