A brief discussion on the simple implementation of thinkphp5 instance

不言
Release: 2023-03-24 21:16:02
Original
1397 people have browsed it

This article mainly introduces the simple implementation of thinkphp5 instance, which has certain reference value. Interested friends can refer to it

 I recently studied ThinkPHP5 and saw TestClass for the first time: :instance() method can create a TestClass instance. I was very curious. I looked through the source code of ThinkPHP and generally understood its design ideas. It is very advanced.

Old rule, go directly to the code:

 <?php
class TestClass {
 
 public static function instance() {
  return new self();
 }
 
 public $data = [];
 
 public function __set($name, $val) {
  return $this->data[$name] = $val;
 }
 
 public function __get($name) {
  return $this->data[$name];
 }
}
 
$app1 = TestClass::instance();
$app1->key = &#39;Application 1&#39;;
echo $app1->key . &#39;<br />&#39;;
?>
Copy after login

For the convenience of calling, I also wrote a helper function imitating ThinkPHP

<?php
function app() {
 return TestClass::instance();
}
 
$app2 = app();
$app2->key = &#39;Application 2&#39;;
echo $app2->key . &#39;<br />&#39;;
?>
Copy after login

In this way, instance is simply implemented.

However, there is a small problem with this method. Just imagine the following. If you call it 100 times, you need to create 100 instances. It is scary to think about it.

Add a static attribute to the Test class and save the created instance here. If you need to call it next time, call this instance directly.

<?php
class TestClass {
 
 public static $instance; //用于缓存实例
 
 public $data = [];
 
 public static function instance() {
  //如果不存在实例,则返回实例
  if (empty(self::$instance)) {
   self::$instance = new self();
  }
  return self::$instance;
 }
 
 public function __set($name, $val) {
  return $this->data[$name] = $val;
 }
 
 public function __get($name) {
  return $this->data[$name];
 }
 
}
 
function app($option = []) {
 return TestClass::instance($option);
}
 
header(&#39;content-type:text/plain&#39;);
 
$result = [];
$app1 = app();
$app1->key = "Application 1"; //修改 key 为 Application 1
$result[&#39;app1&#39;] = [
 &#39;app1&#39; => $app1->key, //实例中 key 为 Application 1
];
 
// 创建 app2,因为 instance 已经存在实例,直接返回 缓存的实例
$app2 = app();
$result[&#39;app2&#39;] = [
 &#39;setp1&#39; => [
  &#39;app1&#39; => $app1->key, // Application 1
  &#39;app2&#39; => $app2->key, //因为直接调用的实例的缓存,所以 key 也是 Application 1
 ],
];
 
// 无论 app1,app2 都对在内存中 对应的同一个实例,无论通过谁修改,都能改变值
$app1->key = "Application 2";
$result[&#39;app2&#39;][&#39;setp2&#39;] = [
 &#39;app1&#39; => $app1->key, // Application 2
 &#39;app2&#39; => $app2->key, // Application 2
];
print_r($result);
?>
Copy after login

Through the above experiment, you can see that no matter how many times it is called, the same instance will be used. This solves the problem of low efficiency.

So far, it basically satisfies most situations. The only small flaw is that the initial parameters of the instances may be different, so it cannot be called flexibly (commonly, the same program calls two databases). This can be solved by slightly modifying the above example, using the incoming parameters as keys and caching the unreasonable instances into an array.

<?php
class TestClass {
 
 public static $instance = []; //用于缓存实例数组
 public $data = [];
 
 public function __construct($opt = []) {
  $this->data = $opt;
 }
 
 public static function instance($option = []) {
  // 根据传入的参数 通过 serialize 转换为字符串,md5 后 作为数组的 key
  $instance_id = md5(serialize($option));
  //如果 不存在实例,则创建
  if (empty(self::$instance[$instance_id])) {
   self::$instance[$instance_id] = new self($option);
  }
  return self::$instance[$instance_id];
 }
 
 public function __set($name, $val) {
  return $this->data[$name] = $val;
 }
 
 public function __get($name) {
  return $this->data[$name];
 }
 
}
 
function app($option = []) {
 return TestClass::instance($option);
}
 
header(&#39;content-type:text/plain&#39;);
 
$result = [];
//传入 初始数据
$app1 = app([&#39;key&#39; => &#39;123&#39;]);
$result[&#39;init&#39;] = $app1->key; // 使用 传入的数据,即:123
$app1->key = "app1";
$result[&#39;app&#39;] = $app1->key; // 现在值改为了 自定义的 app1了
print_r($result);
 
$result = [];
// 创建 app2,注意 初始参数不一样
$app2 = app();
// 因为初始参数不一样,所以还是创建新的实例
$app2->key = "app2";
$result[&#39;app1&#39;] = $app1->key; // app1
$result[&#39;app2&#39;] = $app2->key; // app2
print_r($result);
 
$result = [];
// 创建 app3,传入的参数 和 app1 一样,所以会直接返回 和app1相同 的 实例
$app3 = app([&#39;key&#39; => &#39;123&#39;]);
$result[&#39;log&#39;] = [
 &#39;app1&#39; => $app1->key, // app1
 &#39;app2&#39; => $app2->key, // app2
 &#39;app3&#39; => $app3->key, // app1
];
 
// 设置 app3 的key,会自动修改 app1 的值,因为他们两个是同一个实例
$app3->key = &#39;app3&#39;;
$result[&#39;app3_set&#39;] = [
 &#39;app1&#39; => $app1->key, // app3
 &#39;app2&#39; => $app2->key, // app2
 &#39;app3&#39; => $app3->key, // app3
];
 
// 同理,设置 app1 的key,app3 的 key 也会修改
$app1->key = &#39;app1&#39;;
$result[&#39;app1_set&#39;] = [
 &#39;app1&#39; => $app1->key, // app1
 &#39;app2&#39; => $app2->key, // app2
 &#39;app3&#39; => $app3->key, // app1
];
print_r($result);
?>
Copy after login

Related recommendations:

thinkphp’s I() method is called on other php

thinkphp5 WeChat public account token authentication


The above is the detailed content of A brief discussion on the simple implementation of thinkphp5 instance. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template