kind = self::normalizePart($kind); $this->category = self::normalizePart($category); $this->key = self::normalizePart($key); $this->legacyKey = trim($legacyKey); if ($this->kind === '' || $this->category === '' || $this->key === '' || $this->legacyKey === '') { throw new \InvalidArgumentException('插件身份 kind/category/key/legacyKey 均不能为空'); } if (!in_array($this->kind, ['module', 'driver'], true)) { throw new \InvalidArgumentException("不支持的插件 kind: {$this->kind}"); } } public function canonicalId(): string { return "{$this->kind}:{$this->category}:{$this->key}"; } public function __toString(): string { return $this->canonicalId(); } private static function normalizePart(string $value): string { $value = strtolower(trim($value)); $value = str_replace(['\\', '/', ' '], '_', $value); return preg_replace('/[^a-z0-9_.-]+/', '_', $value) ?: ''; } }