diff --git a/bin/build-phar b/bin/build-phar new file mode 100644 index 0000000000..65c31bf32a --- /dev/null +++ b/bin/build-phar @@ -0,0 +1,77 @@ +#!/usr/bin/env php +iterator = $iterator; + } + + public function current () + { + return $this->iterator->current(); + } + + public function key () + { + return $this->iterator->key(); + } + + public function next () + { + do{ + $this->iterator->next(); + $current = $this->iterator->current(); + if(false === $current) + { + return false; + } + }while($this->isDot($current)); + } + + public function rewind () + { + $this->iterator->rewind(); + if($this->isDot($this->iterator->current())) + { + $this->next(); + } + } + + public function valid () + { + return $this->iterator->valid(); + } + + private function isDot($fileName) + { + $basename = basename($fileName); + return '.' === $basename || '..' === $basename; + } +} + +if(is_file($pharFile)) +{ + echo 'deleting file: ', $pharFile, PHP_EOL; + unlink($pharFile); +} + +$phar = new Phar($pharFile); +$phar->stopBuffering(); +echo 'building from directory: ', $imiPath, PHP_EOL; + +$directory = new \RecursiveDirectoryIterator($imiPath); +$iterator = new \RecursiveIteratorIterator($directory); +$regex = new \RegexIterator($iterator, '/^((?!(\/.git\/)).)*$/'); +$fileIterator = new FileRegexIterator($regex); + +$phar->buildFromIterator($fileIterator, $imiPath); + +$phar->setStub($phar->createDefaultStub('src/PharMain.php')); + +echo 'build OK!', PHP_EOL; diff --git a/bin/imi.php b/bin/imi.php index b89366485c..409550bfeb 100644 --- a/bin/imi.php +++ b/bin/imi.php @@ -9,6 +9,11 @@ if(null === $namespace) { $config = include File::path(dirname($_SERVER['SCRIPT_NAME'], 2), 'config/config.php'); + if(!isset($config['namespace'])) + { + echo 'has no namespace, please add arg: -appNamespace "Your App Namespace"', PHP_EOL; + exit; + } $namespace = $config['namespace']; } diff --git a/src/App.php b/src/App.php index f31a015ee6..733de918cf 100644 --- a/src/App.php +++ b/src/App.php @@ -49,6 +49,13 @@ abstract class App */ private static $isDebug = false; + /** + * Composer ClassLoader + * + * @var \Composer\Autoload\ClassLoader + */ + private static $loader; + /** * 框架服务运行入口 * @param string $namespace 应用命名空间 @@ -109,7 +116,7 @@ private static function initMains() $servers = array_merge(['main'=>Config::get('@app.mainServer')], Config::get('@app.subServers', [])); foreach($servers as $serverName => $item) { - MainHelper::getMain($item['namespace'], 'server_' . $serverName); + MainHelper::getMain($item['namespace'], 'server.' . $serverName); } } @@ -186,12 +193,15 @@ public static function isInited() } /** - * 初始化worker + * 初始化 Worker,但不一定是 Worker 进程 * * @return void */ public static function initWorker() { + // Worker 进程初始化前置 + Event::trigger('IMI.INIT.WORKER.BEFORE'); + $appMains = MainHelper::getAppMains(); // 加载服务器注解 Annotation::getInstance()->init($appMains); @@ -255,5 +265,29 @@ public static function initWorker() CacheManager::addName($name, $cache['handlerClass'], $cache['option']); } } + + // Worker 进程初始化后置 + Event::trigger('IMI.INIT.WORKER.AFTER'); + } + + /** + * 设置 Composer ClassLoader + * + * @param \Composer\Autoload\ClassLoader $loader + * @return void + */ + public static function setLoader(\Composer\Autoload\ClassLoader $loader) + { + static::$loader = $loader; + } + + /** + * 获取 Composer ClassLoader + * + * @return \Composer\Autoload\ClassLoader|null + */ + public static function getLoader() + { + return static::$loader; } } \ No newline at end of file diff --git a/src/Bean/BeanProxy.php b/src/Bean/BeanProxy.php index 63e8299db7..fcc0b71aec 100644 --- a/src/Bean/BeanProxy.php +++ b/src/Bean/BeanProxy.php @@ -184,7 +184,7 @@ public static function getConfigInjects($className) $beanProperties = null; // 优先从服务器bean配置获取 try{ - $beanProperties = Config::get('@server_' . RequestContext::getServer()->getName() . '.beans.' . $beanName, null); + $beanProperties = Config::get('@server.' . RequestContext::getServer()->getName() . '.beans.' . $beanName, null); } catch(\Throwable $ex) { diff --git a/src/Config.php b/src/Config.php index 3c1800c12c..852790b8e7 100644 --- a/src/Config.php +++ b/src/Config.php @@ -20,15 +20,32 @@ abstract class Config */ public static function addConfig($name, array $config) { - if(isset(static::$configs[$name])) + $nameSplit = explode('.', $name); + + $first = array_shift($nameSplit); + if(!isset(static::$configs[$first])) { - return false; + static::$configs[$first] = new ArrayData([]); } - static::$configs[$name] = new ArrayData($config); - if(static::$configs[$name]->exists('configs')) + + if(isset($nameSplit[0])) { - static::load($name, static::$configs[$name]->get('configs', [])); + $configName = implode('.', $nameSplit); + static::$configs[$first]->set($configName, $config); + if(false !== ($configs = static::$configs[$first]->get($configName . '.configs'))) + { + static::load($name, $configs); + } } + else + { + static::$configs[$first]->set($config); + if(static::$configs[$first]->exists('configs')) + { + static::load($name, static::$configs[$first]->get('configs', [])); + } + } + return true; } diff --git a/src/Db/Aop/TransactionAop.php b/src/Db/Aop/TransactionAop.php index 3f2c76b575..edd918aa4c 100644 --- a/src/Db/Aop/TransactionAop.php +++ b/src/Db/Aop/TransactionAop.php @@ -44,7 +44,10 @@ public function defer(AroundJoinPoint $joinPoint) catch(\Throwable $ex) { // 回滚事务 - $db->rollBack(); + if($db->inTransaction()) + { + $db->rollBack(); + } throw $ex; } } diff --git a/src/Db/Drivers/CoroutineMysql/Driver.php b/src/Db/Drivers/CoroutineMysql/Driver.php index 18554cd562..b42b73dabf 100644 --- a/src/Db/Drivers/CoroutineMysql/Driver.php +++ b/src/Db/Drivers/CoroutineMysql/Driver.php @@ -114,8 +114,12 @@ public function getInstance(): \Swoole\Coroutine\MySQL */ public function beginTransaction(): bool { - $this->inTransaction = true; - return $this->instance->begin(); + $result = $this->instance->begin(); + if($result) + { + $this->inTransaction = true; + } + return $result; } /** diff --git a/src/Db/Query/Interfaces/IQuery.php b/src/Db/Query/Interfaces/IQuery.php index 107fd7210c..6e03ee1fe4 100644 --- a/src/Db/Query/Interfaces/IQuery.php +++ b/src/Db/Query/Interfaces/IQuery.php @@ -39,7 +39,7 @@ public function getDb(): IDb; * @param string $database 数据库名 * @return static */ - public function table(string $table, string $alias = null, string $database); + public function table(string $table, string $alias = null, string $database = null); /** * 设置表名,使用SQL原生语句 diff --git a/src/Listener/OnServerCreateAfter.php b/src/Listener/OnServerCreateAfter.php index c60a52a7bf..99557bbf3b 100644 --- a/src/Listener/OnServerCreateAfter.php +++ b/src/Listener/OnServerCreateAfter.php @@ -1,6 +1,7 @@ moduleName = $moduleName; $this->loadConfig(); + $this->loadComponents(); $this->__init(); } @@ -99,4 +101,17 @@ public function getModuleName(): string { return $this->moduleName; } + + /** + * 加载组件 + * + * @return void + */ + protected function loadComponents() + { + foreach(Config::get('@' . $this->moduleName . '.components', []) as $componentName => $namespace) + { + Helper::getMain($namespace, $componentName); + } + } } \ No newline at end of file diff --git a/src/Main/Helper.php b/src/Main/Helper.php index c6e2207a15..7a65a2aa86 100644 --- a/src/Main/Helper.php +++ b/src/Main/Helper.php @@ -13,13 +13,14 @@ abstract class Helper /** * 获取主类实例对象 * @param string $namespace + * @param string $componentName * @return \Imi\Main\BaseMain */ - public static function getMain($namespace, $serverName = null) + public static function getMain($namespace, $componentName = null) { if(null !== $namespace) { - if(null === $serverName) + if(null === $componentName) { // 获取 if(isset(static::$mains[$namespace])) @@ -40,17 +41,17 @@ public static function getMain($namespace, $serverName = null) } else { - return static::newInstance($namespace, $serverName); + return static::newInstance($namespace, $componentName); } } } - else if(null !== $serverName) + else if(null !== $componentName) { - if(!isset(static::$nameMap[$serverName], static::$mains[static::$nameMap[$serverName]])) + if(!isset(static::$nameMap[$componentName], static::$mains[static::$nameMap[$componentName]])) { return null; } - return static::$mains[static::$nameMap[$serverName]]; + return static::$mains[static::$nameMap[$componentName]]; } else { @@ -78,13 +79,13 @@ public static function getAppMains() return $mains; } - private static function newInstance($namespace, $serverName) + private static function newInstance($namespace, $componentName) { $className = $namespace . '\\Main'; if(class_exists($className)) { - static::$mains[$namespace] = new $className($serverName); - static::$nameMap[$serverName] = $namespace; + static::$mains[$namespace] = new $className($componentName); + static::$nameMap[$componentName] = $namespace; return static::$mains[$namespace]; } else diff --git a/src/Model/Annotation/Column.php b/src/Model/Annotation/Column.php index 61fcd85fa3..fc6e3e478c 100644 --- a/src/Model/Annotation/Column.php +++ b/src/Model/Annotation/Column.php @@ -71,4 +71,11 @@ class Column extends Base * @var boolean */ public $isAutoIncrement = false; + + /** + * 虚拟字段,不参与数据库操作 + * + * @var boolean + */ + public $virtual = false; } \ No newline at end of file diff --git a/src/Model/Event/Listener/IAfterFindEventListener.php b/src/Model/Event/Listener/IAfterFindEventListener.php new file mode 100644 index 0000000000..2f094a622b --- /dev/null +++ b/src/Model/Event/Listener/IAfterFindEventListener.php @@ -0,0 +1,17 @@ +eventName = $eventName; + $this->target = $target; + $this->data = $data; + foreach($data as $key => $value) + { + $this->$key = &$value; + } + } +} \ No newline at end of file diff --git a/src/Model/Event/Param/BeforeFindEventParam.php b/src/Model/Event/Param/BeforeFindEventParam.php new file mode 100644 index 0000000000..c59bfaa156 --- /dev/null +++ b/src/Model/Event/Param/BeforeFindEventParam.php @@ -0,0 +1,21 @@ +select()->get(); + + // 查找前 + Event::trigger(static::class . ModelEvents::BEFORE_FIND, [ + 'ids' => $ids, + 'query' => $query, + ], null, \Imi\Model\Event\Param\BeforeFindEventParam::class); + + $result = $query->select()->get(); + + // 查找后 + Event::trigger(static::class . ModelEvents::AFTER_FIND, [ + 'ids' => $ids, + 'model' => $result, + ], null, \Imi\Model\Event\Param\AfterFindEventParam::class); + + return $result; } /** @@ -82,8 +97,21 @@ public static function find(...$ids) */ public static function select($where = null) { - $query = static::query(); - return static::parseWhere($query, $where)->select()->getArray(); + $query = static::parseWhere(static::query(), $where); + + // 查询前 + Event::trigger(static::class . ModelEvents::BEFORE_SELECT, [ + 'query' => $query, + ], null, \Imi\Model\Event\Param\BeforeSelectEventParam::class); + + $result = $query->select()->getArray(); + + // 查询后 + Event::trigger(static::class . ModelEvents::AFTER_SELECT, [ + 'result' => &$result, + ], null, \Imi\Model\Event\Param\AfterSelectEventParam::class); + + return $result; } /** @@ -448,6 +476,11 @@ private static function parseSaveData($data, $object = null) $result = new LazyArrayObject; foreach(ModelManager::getFields($class) as $name => $column) { + // 虚拟字段不参与数据库操作 + if($column->virtual) + { + continue; + } if(array_key_exists($name, $data)) { $value = $data[$name]; diff --git a/src/Model/ModelManager.php b/src/Model/ModelManager.php index 530f7e1846..7505db78ae 100644 --- a/src/Model/ModelManager.php +++ b/src/Model/ModelManager.php @@ -22,6 +22,13 @@ abstract class ModelManager */ private static $keyRules = []; + /** + * 字段缓存 + * + * @var array + */ + private static $fields = []; + /** * 获取当前模型类的类注解 * @param string|object $object @@ -112,9 +119,7 @@ public static function getId($object) public static function getFields($object) { $objectClass = BeanFactory::getObjectClass($object); - $key = 'Model.fields.' . $objectClass; - $fields = RequestContext::get($key); - if(null === $fields) + if(!isset(static::$fields[$objectClass])) { $option = ModelParser::getInstance()->getData()[$objectClass] ?? []; $fields = []; @@ -122,9 +127,9 @@ public static function getFields($object) { $fields[$item['Column']->name] = $item['Column']; } - RequestContext::set($key, $fields); + static::$fields[$objectClass] = $fields; } - return $fields; + return static::$fields[$objectClass]; } /** diff --git a/src/PharMain.php b/src/PharMain.php new file mode 100644 index 0000000000..7eb6253121 --- /dev/null +++ b/src/PharMain.php @@ -0,0 +1,13 @@ +getFree() <= 0) diff --git a/src/Pool/BaseSyncPool.php b/src/Pool/BaseSyncPool.php index 89d2e524e4..16bdfa8ced 100644 --- a/src/Pool/BaseSyncPool.php +++ b/src/Pool/BaseSyncPool.php @@ -32,9 +32,9 @@ protected function initQueue() /** * 获取资源 - * @return IPoolResource + * @return IPoolResource|null */ - public function getResource(): IPoolResource + public function getResource() { if($this->getFree() <= 0) { diff --git a/src/Pool/Interfaces/IPool.php b/src/Pool/Interfaces/IPool.php index 1e3a7d3e16..357ddbc1eb 100644 --- a/src/Pool/Interfaces/IPool.php +++ b/src/Pool/Interfaces/IPool.php @@ -33,9 +33,9 @@ public function close(); /** * 获取资源 - * @return IPoolResource + * @return IPoolResource|null */ - public function getResource(): IPoolResource; + public function getResource(); /** * 尝试获取资源,获取到则返回资源,没有获取到返回false diff --git a/src/Pool/PoolManager.php b/src/Pool/PoolManager.php index c758ed4a07..55c6c7a1a6 100644 --- a/src/Pool/PoolManager.php +++ b/src/Pool/PoolManager.php @@ -67,9 +67,9 @@ public static function getInstance(string $name): IPool /** * 获取池子中的资源 * @param string $name - * @return IPoolResource + * @return IPoolResource|null */ - public static function getResource(string $name): IPoolResource + public static function getResource(string $name) { $resource = static::getInstance($name)->getResource(); @@ -84,9 +84,9 @@ public static function getResource(string $name): IPoolResource /** * 获取请求上下文资源,一个请求上下文通过此方法,只能获取同一个资源 * @param string $name - * @return IPoolResource + * @return IPoolResource|null */ - public static function getRequestContextResource(string $name): IPoolResource + public static function getRequestContextResource(string $name) { $resource = RequestContext::get('poolResource.' . $name); if(null === $resource) diff --git a/src/Tool/Listener/Init.php b/src/Tool/Listener/Init.php index 1661ec35ee..78221499ee 100644 --- a/src/Tool/Listener/Init.php +++ b/src/Tool/Listener/Init.php @@ -1,19 +1,9 @@ init(); - // cli参数初始化 - Args::init(2); - // 工具名/操作名 - list($tool, $operation) = explode('/', $_SERVER['argv'][1]); - // 获取回调 - $callable = ToolParser::getInstance()->getCallable($tool, $operation); - if(null === $callable) - { - throw new \RuntimeException(sprintf('tool %s does not exists!', $_SERVER['argv'][1])); - } - if(Args::get('h')) - { - // 帮助 - $className = get_parent_class($callable[0]); - $refClass = new \ReflectionClass($className); - $required = []; - $other = []; - foreach(ToolParser::getInstance()->getData()['class'][$className]['Methods'][$callable[1]]['Args'] ?? [] as $arg) - { - if($arg->required) - { - $required[] = $arg; - } - else - { - $other[] = $arg; - } - } - echo '工具名称:', $tool, '/', $operation, PHP_EOL, PHP_EOL; - echo $this->parseComment($refClass->getMethod($callable[1])->getDocComment()), PHP_EOL; - if(isset($required[0])) - { - echo PHP_EOL, '必选参数:', PHP_EOL; - foreach($required as $arg) - { - echo '-', $arg->name, ' ', $arg->comments, PHP_EOL; - } - } - if(isset($other[0])) - { - echo PHP_EOL, '可选参数:', PHP_EOL; - foreach($other as $arg) - { - echo '-', $arg->name, ' ', $arg->comments, PHP_EOL; - } - } - } - else - { - // 执行参数 - $args = $this->getCallToolArgs($callable, $tool, $operation); - // 执行工具操作 - call_user_func_array($callable, $args); - swoole_event_wait(); - } - } - catch(\Throwable $ex) - { - echo $ex->getMessage(), PHP_EOL; - } + Tool::run(); } - /** - * 初始化 - * @return void - */ - private function init() - { - Annotation::getInstance()->init([Helper::getMain(App::getNamespace())]); - RequestContext::create(); - // 获取配置 - $pools = $caches = []; - foreach(Helper::getMains() as $main) - { - $pools = array_merge($pools, $main->getConfig()['pools'] ?? []); - $caches = array_merge($caches, $main->getConfig()['caches'] ?? []); - } - // 同步池子初始化 - foreach($pools as $name => $pool) - { - if(isset($pool['sync'])) - { - $pool = $pool['sync']; - PoolManager::addName($name, $pool['pool']['class'], new PoolConfig($pool['pool']['config']), $pool['resource']); - } - } - // 缓存初始化 - foreach($caches as $name => $cache) - { - CacheManager::addName($name, $cache['handlerClass'], $cache['option']); - } - } - - /** - * 获取执行参数 - * @param callable $callable - * @param string $tool - * @param string $operation - * @return array - */ - private function getCallToolArgs($callable, $tool, $operation) - { - $className = get_parent_class($callable[0]); - $methodRef = new \ReflectionMethod($className, $callable[1]); - $args = []; - foreach(ToolParser::getInstance()->getData()['class'][$className]['Methods'][$methodRef->name]['Args'] ?? [] as $annotation) - { - if(Args::exists($annotation->name)) - { - $value = $this->parseArgValue(Args::get($annotation->name), $annotation); - } - else if($annotation->required) - { - throw new \InvalidArgumentException(sprintf('tool %s/%s param %s is required', $tool, $operation, $annotation->name)); - } - else - { - $value = $annotation->default; - } - $args[] = $value; - } - return $args; - } - - /** - * 处理参数值 - * @param string $value - * @param Arg $annotation - * @return mixed - */ - private function parseArgValue($value, Arg $annotation) - { - switch($annotation->type) - { - case ArgType::STRING: - break; - case ArgType::INT: - $value = (int)$value; - break; - case ArgType::FLOAT: - case ArgType::DOUBLE: - $value = (float)$value; - break; - case ArgType::BOOL: - case ArgType::BOOLEAN: - $value = (bool)json_decode($value); - break; - case ArgType::ARRAY: - $value = explode(',', $value); - break; - } - return $value; - } - - /** - * 处理注释 - * @param string $content - * @return string - */ - private function parseComment($content) - { - return trim(preg_replace('/@.+\n/', '', preg_replace('/\/*\s*\*\s*\/*/', PHP_EOL, $content))); - } } \ No newline at end of file diff --git a/src/Tool/Tool.php b/src/Tool/Tool.php new file mode 100644 index 0000000000..d6b603c646 --- /dev/null +++ b/src/Tool/Tool.php @@ -0,0 +1,223 @@ +getCallable(static::$toolName, static::$toolOperation); + if(null === $callable) + { + throw new \RuntimeException(sprintf('tool %s does not exists!', $_SERVER['argv'][1])); + } + if(Args::get('h')) + { + // 帮助 + $className = get_parent_class($callable[0]); + $refClass = new \ReflectionClass($className); + $required = []; + $other = []; + foreach(ToolParser::getInstance()->getData()['class'][$className]['Methods'][$callable[1]]['Args'] ?? [] as $arg) + { + if($arg->required) + { + $required[] = $arg; + } + else + { + $other[] = $arg; + } + } + echo '工具名称:', static::$toolName, '/', static::$toolOperation, PHP_EOL, PHP_EOL; + echo static::parseComment($refClass->getMethod($callable[1])->getDocComment()), PHP_EOL; + if(isset($required[0])) + { + echo PHP_EOL, '必选参数:', PHP_EOL; + foreach($required as $arg) + { + echo '-', $arg->name, ' ', $arg->comments, PHP_EOL; + } + } + if(isset($other[0])) + { + echo PHP_EOL, '可选参数:', PHP_EOL; + foreach($other as $arg) + { + echo '-', $arg->name, ' ', $arg->comments, PHP_EOL; + } + } + } + else + { + // 执行参数 + $args = static::getCallToolArgs($callable, static::$toolName, static::$toolOperation); + // 执行工具操作 + call_user_func_array($callable, $args); + swoole_event_wait(); + } + } + + /** + * 获取当前命令行工具名称 + * + * @return string + */ + public static function getToolName() + { + return static::$toolName; + } + + /** + * 获取当前命令行工具操作名称 + * + * @return string + */ + public static function getToolOperation() + { + return static::$toolOperation; + } + + /** + * 初始化 + * @return void + */ + private static function init() + { + // 仅初始化项目及组件 + $initMains = [Helper::getMain(App::getNamespace())]; + foreach(Helper::getAppMains() as $mainName => $main) + { + foreach($main->getConfig()['components'] ?? [] as $componentName => $namespace) + { + $componentMain = Helper::getMain($namespace); + if(null !== $componentMain) + { + $initMains[] = $componentMain; + } + } + } + Annotation::getInstance()->init($initMains); + + RequestContext::create(); + // 获取配置 + $pools = $caches = []; + foreach(Helper::getMains() as $main) + { + $pools = array_merge($pools, $main->getConfig()['pools'] ?? []); + $caches = array_merge($caches, $main->getConfig()['caches'] ?? []); + } + // 同步池子初始化 + foreach($pools as $name => $pool) + { + if(isset($pool['sync'])) + { + $pool = $pool['sync']; + PoolManager::addName($name, $pool['pool']['class'], new PoolConfig($pool['pool']['config']), $pool['resource']); + } + } + // 缓存初始化 + foreach($caches as $name => $cache) + { + CacheManager::addName($name, $cache['handlerClass'], $cache['option']); + } + } + + /** + * 获取执行参数 + * @param callable $callable + * @param string $tool + * @param string $operation + * @return array + */ + private static function getCallToolArgs($callable, $tool, $operation) + { + $className = get_parent_class($callable[0]); + $methodRef = new \ReflectionMethod($className, $callable[1]); + $args = []; + foreach(ToolParser::getInstance()->getData()['class'][$className]['Methods'][$methodRef->name]['Args'] ?? [] as $annotation) + { + if(Args::exists($annotation->name)) + { + $value = static::parseArgValue(Args::get($annotation->name), $annotation); + } + else if($annotation->required) + { + throw new \InvalidArgumentException(sprintf('tool %s/%s param %s is required', $tool, $operation, $annotation->name)); + } + else + { + $value = $annotation->default; + } + $args[] = $value; + } + return $args; + } + + /** + * 处理参数值 + * @param string $value + * @param Arg $annotation + * @return mixed + */ + private static function parseArgValue($value, Arg $annotation) + { + switch($annotation->type) + { + case ArgType::STRING: + break; + case ArgType::INT: + $value = (int)$value; + break; + case ArgType::FLOAT: + case ArgType::DOUBLE: + $value = (float)$value; + break; + case ArgType::BOOL: + case ArgType::BOOLEAN: + $value = (bool)json_decode($value); + break; + case ArgType::ARRAY: + $value = explode(',', $value); + break; + } + return $value; + } + + /** + * 处理注释 + * @param string $content + * @return string + */ + private static function parseComment($content) + { + return trim(preg_replace('/@.+\n/', '', preg_replace('/\/*\s*\*\s*\/*/', PHP_EOL, $content))); + } + +} \ No newline at end of file diff --git a/src/Util/Args.php b/src/Util/Args.php index bcf69d40c1..266ce57d99 100644 --- a/src/Util/Args.php +++ b/src/Util/Args.php @@ -1,6 +1,9 @@ $row) { - $array[$array[$i][$column]] = $array[$i]; + $key = $row[$column]; if(!$keepOld) { - unset($array[$i]); + unset($row[$column]); } + $newArray[$key] = $row; } + return $newArray; } /** diff --git a/src/Util/Bit.php b/src/Util/Bit.php index 3d0512c02a..6864c8b89a 100644 --- a/src/Util/Bit.php +++ b/src/Util/Bit.php @@ -2,7 +2,7 @@ namespace Imi\Util; /** - * 位操作工具 + * 位操作工具类 */ abstract class Bit { @@ -14,6 +14,6 @@ abstract class Bit */ public static function has($value, $subValue) { - return $value === $subValue || ($subValue === $value & $subValue); + return $value === $subValue || ($subValue === ($value & $subValue)); } } \ No newline at end of file diff --git a/src/Util/ClassObject.php b/src/Util/ClassObject.php index 3365ca7e13..320a50b64b 100644 --- a/src/Util/ClassObject.php +++ b/src/Util/ClassObject.php @@ -1,15 +1,19 @@ = 0; + $index = strpos(get_class($object), 'class@anonymous'); + return false !== $index && $index >= 0; } } \ No newline at end of file diff --git a/src/Util/Coroutine.php b/src/Util/Coroutine.php index b10a992022..d0b054ce8f 100644 --- a/src/Util/Coroutine.php +++ b/src/Util/Coroutine.php @@ -4,7 +4,7 @@ abstract class Coroutine extends \Swoole\Coroutine { /** - * 是否在协程中 + * 判断当前是否在协程中运行 * @return boolean */ public static function isIn() diff --git a/src/Util/File.php b/src/Util/File.php index 2a46f949e1..07bd47ff3a 100644 --- a/src/Util/File.php +++ b/src/Util/File.php @@ -2,6 +2,9 @@ namespace Imi\Util; +/** + * 文件相关工具类 + */ abstract class File { /** @@ -45,7 +48,16 @@ public static function path(...$args) { static $dsds = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; $result = implode(DIRECTORY_SEPARATOR, $args); - while(false !== strpos($result, $dsds)) + $offset = strpos($result, '://'); + if(false === $offset) + { + $offset = 0; + } + else + { + $offset += 3; + } + while(false !== strpos($result, $dsds, $offset)) { $result = str_replace($dsds, DIRECTORY_SEPARATOR, $result); } diff --git a/src/Util/Imi.php b/src/Util/Imi.php index 0b3753156b..cf97d896ad 100644 --- a/src/Util/Imi.php +++ b/src/Util/Imi.php @@ -188,22 +188,60 @@ public static function getClassShortName(string $className) } /** - * 根据命名空间获取真实路径 + * 根据命名空间获取真实路径,返回null则为获取失败 * @param string $namespace - * @return string + * @return string|null */ public static function getNamespacePath($namespace) { - $appNamespace = App::getNamespace(); - $appMain = Helper::getMain($appNamespace); - $refClass = new \ReflectionClass($appMain); - $path = dirname($refClass->getFileName()); - $namespaceSubPath = substr($namespace, strlen($appNamespace)); - return File::path($path, str_replace('\\', DIRECTORY_SEPARATOR, $namespaceSubPath)); + if('\\' !== substr($namespace, -1, 1)) + { + $namespace .= '\\'; + } + $loader = App::getLoader(); + if(null === $loader) + { + // Composer 加载器未赋值,则只能取Main类命名空间下的目录 + foreach(Helper::getMains() as $main) + { + $mainNamespace = $main->getNamespace(); + if('\\' !== substr($mainNamespace, -1, 1)) + { + $mainNamespace .= '\\'; + } + $len = strlen($mainNamespace); + if($mainNamespace === substr($namespace, 0, $len)) + { + $namespaceSubPath = substr($namespace, $len); + $refClass = new \ReflectionClass($main); + $path = dirname($refClass->getFileName()); + return File::path($path, str_replace('\\', DIRECTORY_SEPARATOR, $namespaceSubPath)); + } + } + } + else + { + // 依靠 Composer PSR-4 配置的目录进行定位目录 + $prefixDirsPsr4 = $loader->getPrefixesPsr4(); + foreach($prefixDirsPsr4 as $keyNamespace => $paths) + { + $len = strlen($keyNamespace); + if(substr($namespace, 0, $len) === $keyNamespace) + { + if(isset($paths[1])) + { + return null; + } + return File::path($paths[0], str_replace('\\', DIRECTORY_SEPARATOR, substr($namespace, $len))); + } + } + } + return null; } /** - * 获取类属性的值,支持传入Bean名称 + * 获取类属性的值,值为beans配置或默认配置,支持传入Bean名称 + * 构造方法赋值无法取出 * * @param string $className * @param string $propertyName diff --git a/src/Util/Random.php b/src/Util/Random.php index 8c855ec253..66d22fe5d9 100644 --- a/src/Util/Random.php +++ b/src/Util/Random.php @@ -1,6 +1,9 @@