好像不怎么兼容php8,請(qǐng)指教下有沒有好的解決方案嗎?
你把那個(gè)Container 替換成我以前那個(gè)版本就好了
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace think;
use ArrayAccess;
use ArrayIterator;
use Closure;
use Countable;
use InvalidArgumentException;
use IteratorAggregate;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionFunctionAbstract;
use ReflectionMethod;
use think\exception\ClassNotFoundException;
use think\exception\FuncNotFoundException;
use think\helper\Str;
use Traversable;
/**
* 容器管理類 支持PSR-11
*/
class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, Countable
{
/**
* 容器對(duì)象實(shí)例
* @var Container|Closure
*/
protected static $instance;
/**
* 容器中的對(duì)象實(shí)例
* @var array
*/
protected $instances = [];
/**
* 容器綁定標(biāo)識(shí)
* @var array
*/
protected $bind = [];
/**
* 容器回調(diào)
* @var array
*/
protected $invokeCallback = [];
/**
* 獲取當(dāng)前容器的實(shí)例(單例)
* @access public
* @return static
*/
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
if (static::$instance instanceof Closure) {
return (static::$instance)();
}
return static::$instance;
}
/**
* 設(shè)置當(dāng)前容器的實(shí)例
* @access public
* @param object|Closure $instance
* @return void
*/
public static function setInstance($instance): void
{
static::$instance = $instance;
}
/**
* 注冊(cè)一個(gè)容器對(duì)象回調(diào)
*
* @param string|Closure $abstract
* @param Closure|null $callback
* @return void
*/
public function resolving($abstract, Closure $callback = null): void
{
if ($abstract instanceof Closure) {
$this->invokeCallback['*'][] = $abstract;
return;
}
$abstract = $this->getAlias($abstract);
$this->invokeCallback[$abstract][] = $callback;
}
/**
* 獲取容器中的對(duì)象實(shí)例 不存在則創(chuàng)建
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @param array|true $vars 變量
* @param bool $newInstance 是否每次創(chuàng)建新的實(shí)例
* @return object
*/
public static function pull(string $abstract, array $vars = [], bool $newInstance = false)
{
return static::getInstance()->make($abstract, $vars, $newInstance);
}
/**
* 獲取容器中的對(duì)象實(shí)例
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @return object
*/
public function get($abstract)
{
if ($this->has($abstract)) {
return $this->make($abstract);
}
throw new ClassNotFoundException('class not exists: ' . $abstract, $abstract);
}
/**
* 綁定一個(gè)類、閉包、實(shí)例、接口實(shí)現(xiàn)到容器
* @access public
* @param string|array $abstract 類標(biāo)識(shí)、接口
* @param mixed $concrete 要綁定的類、閉包或者實(shí)例
* @return $this
*/
public function bind($abstract, $concrete = null)
{
if (is_array($abstract)) {
foreach ($abstract as $key => $val) {
$this->bind($key, $val);
}
} elseif ($concrete instanceof Closure) {
$this->bind[$abstract] = $concrete;
} elseif (is_object($concrete)) {
$this->instance($abstract, $concrete);
} else {
$abstract = $this->getAlias($abstract);
if ($abstract != $concrete) {
$this->bind[$abstract] = $concrete;
}
}
return $this;
}
/**
* 根據(jù)別名獲取真實(shí)類名
* @param string $abstract
* @return string
*/
public function getAlias(string $abstract): string
{
if (isset($this->bind[$abstract])) {
$bind = $this->bind[$abstract];
if (is_string($bind)) {
return $this->getAlias($bind);
}
}
return $abstract;
}
/**
* 綁定一個(gè)類實(shí)例到容器
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @param object $instance 類的實(shí)例
* @return $this
*/
public function instance(string $abstract, $instance)
{
$abstract = $this->getAlias($abstract);
$this->instances[$abstract] = $instance;
return $this;
}
/**
* 判斷容器中是否存在類及標(biāo)識(shí)
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @return bool
*/
public function bound(string $abstract): bool
{
return isset($this->bind[$abstract]) || isset($this->instances[$abstract]);
}
/**
* 判斷容器中是否存在類及標(biāo)識(shí)
* @access public
* @param string $name 類名或者標(biāo)識(shí)
* @return bool
*/
public function has($name): bool
{
return $this->bound($name);
}
/**
* 判斷容器中是否存在對(duì)象實(shí)例
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @return bool
*/
public function exists(string $abstract): bool
{
$abstract = $this->getAlias($abstract);
return isset($this->instances[$abstract]);
}
/**
* 創(chuàng)建類的實(shí)例 已經(jīng)存在則直接獲取
* @access public
* @param string $abstract 類名或者標(biāo)識(shí)
* @param array $vars 變量
* @param bool $newInstance 是否每次創(chuàng)建新的實(shí)例
* @return mixed
*/
public function make(string $abstract, array $vars = [], bool $newInstance = false)
{
$abstract = $this->getAlias($abstract);
if (isset($this->instances[$abstract]) && !$newInstance) {
return $this->instances[$abstract];
}
if (isset($this->bind[$abstract]) && $this->bind[$abstract] instanceof Closure) {
$object = $this->invokeFunction($this->bind[$abstract], $vars);
} else {
$object = $this->invokeClass($abstract, $vars);
}
if (!$newInstance) {
$this->instances[$abstract] = $object;
}
return $object;
}
/**
* 刪除容器中的對(duì)象實(shí)例
* @access public
* @param string $name 類名或者標(biāo)識(shí)
* @return void
*/
public function delete($name)
{
$name = $this->getAlias($name);
if (isset($this->instances[$name])) {
unset($this->instances[$name]);
}
}
/**
* 執(zhí)行函數(shù)或者閉包方法 支持參數(shù)調(diào)用
* @access public
* @param string|Closure $function 函數(shù)或者閉包
* @param array $vars 參數(shù)
* @return mixed
*/
public function invokeFunction($function, array $vars = [])
{
try {
$reflect = new ReflectionFunction($function);
} catch (ReflectionException $e) {
throw new FuncNotFoundException("function not exists: {$function}()", $function, $e);
}
$args = $this->bindParams($reflect, $vars);
return $function(...$args);
}
/**
* 調(diào)用反射執(zhí)行類的方法 支持參數(shù)綁定
* @access public
* @param mixed $method 方法
* @param array $vars 參數(shù)
* @param bool $accessible 設(shè)置是否可訪問
* @return mixed
*/
public function invokeMethod($method, array $vars = [], bool $accessible = false)
{
if (is_array($method)) {
[$class, $method] = $method;
$class = is_object($class) ? $class : $this->invokeClass($class);
} else {
// 靜態(tài)方法
[$class, $method] = explode('::', $method);
}
try {
$reflect = new ReflectionMethod($class, $method);
} catch (ReflectionException $e) {
$class = is_object($class) ? get_class($class) : $class;
throw new FuncNotFoundException('method not exists: ' . $class . '::' . $method . '()', "{$class}::{$method}", $e);
}
$args = $this->bindParams($reflect, $vars);
if ($accessible) {
$reflect->setAccessible($accessible);
}
return $reflect->invokeArgs(is_object($class) ? $class : null, $args);
}
/**
* 調(diào)用反射執(zhí)行類的方法 支持參數(shù)綁定
* @access public
* @param object $instance 對(duì)象實(shí)例
* @param mixed $reflect 反射類
* @param array $vars 參數(shù)
* @return mixed
*/
public function invokeReflectMethod($instance, $reflect, array $vars = [])
{
$args = $this->bindParams($reflect, $vars);
return $reflect->invokeArgs($instance, $args);
}
/**
* 調(diào)用反射執(zhí)行callable 支持參數(shù)綁定
* @access public
* @param mixed $callable
* @param array $vars 參數(shù)
* @param bool $accessible 設(shè)置是否可訪問
* @return mixed
*/
public function invoke($callable, array $vars = [], bool $accessible = false)
{
if ($callable instanceof Closure) {
return $this->invokeFunction($callable, $vars);
} elseif (is_string($callable) && false === strpos($callable, '::')) {
return $this->invokeFunction($callable, $vars);
} else {
return $this->invokeMethod($callable, $vars, $accessible);
}
}
/**
* 調(diào)用反射執(zhí)行類的實(shí)例化 支持依賴注入
* @access public
* @param string $class 類名
* @param array $vars 參數(shù)
* @return mixed
*/
public function invokeClass(string $class, array $vars = [])
{
try {
$reflect = new ReflectionClass($class);
} catch (ReflectionException $e) {
throw new ClassNotFoundException('class not exists: ' . $class, $class, $e);
}
if ($reflect->hasMethod('__make')) {
$method = $reflect->getMethod('__make');
if ($method->isPublic() && $method->isStatic()) {
$args = $this->bindParams($method, $vars);
$object = $method->invokeArgs(null, $args);
$this->invokeAfter($class, $object);
return $object;
}
}
$constructor = $reflect->getConstructor();
$args = $constructor ? $this->bindParams($constructor, $vars) : [];
$object = $reflect->newInstanceArgs($args);
$this->invokeAfter($class, $object);
return $object;
}
/**
* 執(zhí)行invokeClass回調(diào)
* @access protected
* @param string $class 對(duì)象類名
* @param object $object 容器對(duì)象實(shí)例
* @return void
*/
protected function invokeAfter(string $class, $object): void
{
if (isset($this->invokeCallback['*'])) {
foreach ($this->invokeCallback['*'] as $callback) {
$callback($object, $this);
}
}
if (isset($this->invokeCallback[$class])) {
foreach ($this->invokeCallback[$class] as $callback) {
$callback($object, $this);
}
}
}
/**
* 綁定參數(shù)
* @access protected
* @param ReflectionFunctionAbstract $reflect 反射類
* @param array $vars 參數(shù)
* @return array
*/
protected function bindParams(ReflectionFunctionAbstract $reflect, array $vars = []): array
{
if ($reflect->getNumberOfParameters() == 0) {
return [];
}
// 判斷數(shù)組類型 數(shù)字?jǐn)?shù)組時(shí)按順序綁定參數(shù)
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters();
$args = [];
foreach ($params as $param) {
$name = $param->getName();
$lowerName = Str::snake($name);
$reflectionType = $param->getType();
if ($reflectionType && $reflectionType->isBuiltin() === false) {
$args[] = $this->getObjectParam($reflectionType->getName(), $vars);
} elseif (1 == $type && !empty($vars)) {
$args[] = array_shift($vars);
} elseif (0 == $type && array_key_exists($name, $vars)) {
$args[] = $vars[$name];
} elseif (0 == $type && array_key_exists($lowerName, $vars)) {
$args[] = $vars[$lowerName];
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
throw new InvalidArgumentException('method param miss:' . $name);
}
}
return $args;
}
/**
* 創(chuàng)建工廠對(duì)象實(shí)例
* @param string $name 工廠類名
* @param string $namespace 默認(rèn)命名空間
* @param array $args
* @return mixed
* @deprecated
* @access public
*/
public static function factory(string $name, string $namespace = '', ...$args)
{
$class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
return Container::getInstance()->invokeClass($class, $args);
}
/**
* 獲取對(duì)象類型的參數(shù)值
* @access protected
* @param string $className 類名
* @param array $vars 參數(shù)
* @return mixed
*/
protected function getObjectParam(string $className, array &$vars)
{
$array = $vars;
$value = array_shift($array);
if ($value instanceof $className) {
$result = $value;
array_shift($vars);
} else {
$result = $this->make($className);
}
return $result;
}
public function __set($name, $value)
{
$this->bind($name, $value);
}
public function __get($name)
{
return $this->get($name);
}
public function __isset($name): bool
{
return $this->exists($name);
}
public function __unset($name)
{
$this->delete($name);
}
#[\ReturnTypeWillChange]
public function offsetExists($key): bool
{
return $this->exists($key);
}
#[\ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->make($key);
}
#[\ReturnTypeWillChange]
public function offsetSet($key, $value)
{
$this->bind($key, $value);
}
#[\ReturnTypeWillChange]
public function offsetUnset($key)
{
$this->delete($key);
}
//Countable
public function count(): int
{
return count($this->instances);
}
//IteratorAggregate
public function getIterator(): Traversable
{
return new ArrayIterator($this->instances);
}
}