douyongwan5946
2017-05-05 11:07
浏览 51
已采纳

静态在php中,为什么它为这两个类使用一个缓存

I create parent class for my models, it look like this

class Model {

   protected static $cache = [];

   public static function load($id)
   {
       return static::$cache[$id];
   }

   public static function findById($id)
   {
       $model = static::find($id);

       static::$cache[$id] = model;

       return model;
   }

   ...
}

And i have two child class, examples

class A extend Model {}
class B extend Model {}

then, i write

A::findById(1);
B::findById(1);

$a = A::load(1);
$b = B::load(1);

I think type of class $b is class B, but not, it is class A, because function "load" use static cache and load result from function A::findById(1). Why?

图片转代码服务由CSDN问答提供 功能建议

我为我的模型创建父类,它看起来像这样

 <  code> class Model {
 
 protected static $ cache = []; 
 
 public static function load($ id)
 {
 return static :: $ cache [$ id]; 
} 
  
公共静态函数findById($ id)
 {
 $ model = static :: find($ id); 
 
 static :: $ cache [$ id] = model; 
 
返回模型;  
} 
 
 ... 
} 
   
 
 

我有两个子类,示例

 <  code> class A extend Model {} 
class B扩展Model {} 
   
 
 

然后,我写

   A :: findById(1); 
B :: findById(1); 
 
 $ a = A :: load(1); 
 $ b = B :: load(1); 
   
 
 

我认为类$ b的类型是B类,但不是,它是A类,因为函数“load”使用静态缓存并从函数A :: findById加载结果(1 )。 为什么?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douhao7889 2017-05-05 11:21
    已采纳

    By accessing static class properties as static::$cache you tell the interpreter to use the $cache property of the class used to call the method and not the one of the class where the method is defined.

    In plain English, when you call A::findById() you expect that findById() uses the property $cache of A and not the one of Model. The same for A::load() and similar for B::findById() and B::load().

    The question now is: do the A and B classes declare a static property $cache on their own? Because if they do not declare this property, the static:: in front of $cache in the function A::findById() cannot find A::$cache and uses Model::$cache instead. The same for B::findById().

    The easy solution to your problem is to declare the protected static $cache property in all classes that extend Model.

    The correct solution is to not use static properties and methods. Static properties and methods are not OOP. They are procedural programming (and thinking) disguised as OOP code. Code that is difficult to understand and test.

    打赏 评论
  • douwanc63652 2017-05-05 11:15

    static properties are inherited, if you want to have them separately, redefine them

    class A extend Model { static $cache; }
    class B extend Model { static $cache; }
    

    also what you are trying to do is bad OOP practice.

    this is how you can do it proper way

    class CacheFactory
    {
        static public function createModelCache($model)
        {
            static $instances = [];
            if (!isset($instances[$model])) {
                $instances[$model] = new Cache($model);
            }
            return $instances[$model];
        }
    }
    
    class Cache
    {
        protected $name;
    
        protected $data = [];
    
        public function __construct($name)
        {
            $this->name = $name;
        }
    
        public function get($key)
        {
            return isset($this->data[$key]) ? $this->data[$key] : null;
        }
    
        public function set($key, $value)
        {
            $this->data[$key] = $value;
        }
    }
    
    abstract class Model
    {
        abstract protected $name;
    
        /**
         * @type Cache
         */
        protected $cache;
    
        public function __construct()
        {
            $this->cache = CacheFactory::createModelCache($this->name);
        }
    
        public function findById($id)
        {
            if (($data = $this->cache->get($id)) !== null) {
                return $data;
            }
            $data = ...;
            $this->cache->put($id, $data);
        }
    }
    
    class A extends Model
    {
        protected $name = "modelA";
    }
    
    
    class B extends Model
    {
        protected $name = "modelB";
    }
    

    this just an example and you can change few bits like

    • you can move CacheFactory::createModelCache to Cache
    • you can use get_class instead using abstract protected $name
    • you can just create static array instead Cache class

    but thing is - you just don't use static everywhere, this is not how you code in OOP

    from my example you can see the only thing what is static is an array with Cache objects and factory method. this is only thing you need to store globally.

    打赏 评论

相关推荐 更多相似问题