大部分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 代码自动提示功能失效的问题?
下面提供两种解决方法:
(1)从代码上解决代码提示失效的问题
我怀疑是 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]; // } }
(2)从注释上解决代码提示失效的问题
直接添加一个@return static的注解即可(phpstorm还支持@return $this @return self这两种注解)
示例代码如下:
<?php namespace framework; defined('SITE_PATH') or die('Access Denied'); /** * 业务基类 * * @package framework */ class Base { /** * 类实例化(单例模式) * * @return static //以上代码仅需改动这里即可 * @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]; } }