Ver Fonte

feat(core): 添加symfony/console依赖并更新composer配置- 在composer.json中添加symfony/console依赖- 更新项目描述为英文版本- 添加项目关键词数组
- 更新.gitignore模板文件内容
- 添加composer.lock文件- 优化composer.json模板中的命名空间引用方式

runphp há 6 meses atrás
pai
commit
6292903fa4

+ 2 - 1
.gitignore

@@ -1,2 +1,3 @@
 /vendor/
-/.idea/
+/.idea/
+/.composer.lock

+ 282 - 0
README.md

@@ -0,0 +1,282 @@
+# SixShop Maker Bundle
+
+A powerful command-line tool for generating SixShop extension boilerplate code, designed to streamline the development process within the SixShop ecosystem.
+
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+[![PHP Version](https://img.shields.io/badge/PHP-%3E%3D8.0-blue)](https://php.net)
+[![ThinkPHP](https://img.shields.io/badge/ThinkPHP-%5E8.1-green)](https://github.com/top-think/framework)
+
+## 🚀 Features
+
+- **Automated Code Generation**: Generates complete SixShop extension structure with zero manual coding
+- **Intelligent Detection**: Automatically detects existing extensions and pre-fills configuration values
+- **Smart Path Management**: Flexible target path selection with validation and confirmation
+- **Template-Based**: Uses configurable PHP templates for consistent code generation
+- **PSR-4 Compliant**: Generates proper namespace structure and autoloading configuration
+- **Interactive CLI**: User-friendly command-line interface with helpful prompts and validation
+
+## 📋 Requirements
+
+- **PHP**: >= 8.0
+- **Composer**: Latest version recommended
+- **ThinkPHP Framework**: ^8.1
+- **Symfony Console**: ^7.3
+
+## 🛠 Installation
+
+### Via Composer (Recommended)
+
+```bash
+# Install as development dependency
+composer require six-shop/maker-bundle --dev
+
+# Or install globally
+composer global require six-shop/maker-bundle
+```
+
+### Manual Installation
+
+```bash
+# Clone the repository
+git clone https://github.com/sixshop/maker-bundle.git
+cd maker-bundle
+
+# Install dependencies
+composer install
+```
+
+## 🎯 Usage
+
+### Quick Start
+
+```bash
+# If installed locally
+php vendor/bin/sixshop-maker
+
+# If installed globally
+sixshop-maker
+
+# Or directly
+php bin/sixshop-maker
+```
+
+### Interactive Workflow
+
+The tool guides you through a step-by-step process:
+
+1. **Target Path Selection**: Choose where to generate your extension
+2. **Package Configuration**: Set package name, namespace, and description
+3. **Extension Settings**: Configure extension ID and metadata
+4. **File Generation**: Automatic creation of all necessary files
+
+### Example Session
+
+```bash
+$ php vendor/bin/sixshop-maker
+
+请输入扩展生成的目标路径 [/current/path]: ./my-extension
+将在以下路径生成扩展: /full/path/to/my-extension
+确认使用此路径? [yes]
+
+请输入Composer包名 (例如: six-shop/hello): my-vendor/awesome-extension
+请输入包描述 [A SixShop extension package]: My awesome SixShop extension
+请输入命名空间 (例如: SixShop\Hello\) [MyVendor\AwesomeExtension\]: 
+请输入扩展ID [my-vendor-awesome-extension]: 
+
+✅ 扩展创建完成!
+```
+
+## 📁 Generated Structure
+
+The tool creates a complete extension structure:
+
+```
+my-extension/
+├── composer.json          # Package configuration
+├── .gitignore            # Git ignore rules
+├── src/
+│   └── Extension.php     # Main extension class
+├── route/
+│   ├── api.php          # API routes
+│   └── admin.php        # Admin routes
+├── config.php           # Extension configuration
+└── info.php            # Extension metadata
+```
+
+## 🔧 Smart Features
+
+### Existing Extension Detection
+
+The tool automatically detects existing `composer.json` files and offers:
+
+- **One-click regeneration** with existing configuration
+- **Pre-filled prompts** with current values
+- **Seamless updates** for existing extensions
+
+### Path Intelligence
+
+- **Automatic validation** of target paths
+- **Permission checking** before generation
+- **Directory creation** if paths don't exist
+- **Confirmation prompts** for safety
+
+### Namespace Handling
+
+- **Consistent formatting** across all generated files
+- **PSR-4 compliance** with proper autoloading
+- **JSON-safe escaping** in configuration files
+- **User-friendly display** in terminal interfaces
+
+## 🎨 Customization
+
+### Templates
+
+All generated files use PHP templates located in `/templates/`:
+
+- `composer.json.tpl.php` - Package configuration
+- `src/Extension.php.tpl.php` - Main extension class
+- `.gitignore.tpl.php` - Git ignore rules
+- `route/api.php.tpl.php` - API routes
+- `route/admin.php.tpl.php` - Admin routes
+- `config.php.tpl.php` - Configuration file
+- `info.php.tpl.php` - Metadata file
+
+### Available Variables
+
+Templates have access to these variables:
+
+- `$name` - Package name (e.g., "vendor/package")
+- `$namespace` - PHP namespace (e.g., "Vendor\\Package\\")
+- `$id` - Extension ID (e.g., "vendor-package")
+- `$description` - Package description
+
+## 🏗 Architecture
+
+### Components
+
+- **`Maker`** - Main command controller and user interaction
+- **`ComposerGenerator`** - Handles composer.json generation and detection
+- **`DirectoryGenerator`** - Creates directory structure
+- **`GitignoreGenerator`** - Generates .gitignore files
+- **`PhpCodeGenerator`** - Creates PHP source files from templates
+
+### Design Patterns
+
+- **Generator Pattern**: Specialized classes for each artifact type
+- **Template Method**: Consistent generation workflow
+- **Single Responsibility**: Each generator handles one concern
+- **Command Pattern**: CLI interface implementation
+
+## 🔄 Workflow Examples
+
+### Creating a New Extension
+
+```bash
+# Start the maker
+php vendor/bin/sixshop-maker
+
+# Follow prompts
+Target Path: ./my-new-extension
+Package Name: sixshop/payment-gateway
+Namespace: SixShop\PaymentGateway\
+Extension ID: sixshop-payment-gateway
+
+# Result: Complete extension ready for development
+```
+
+### Regenerating an Existing Extension
+
+```bash
+# Run in directory with existing composer.json
+php vendor/bin/sixshop-maker
+
+# Tool detects existing configuration
+Found existing composer.json: ./composer.json
+Package: sixshop/payment-gateway
+Namespace: SixShop\PaymentGateway\
+
+# Confirm regeneration
+Use existing configuration? [yes]
+
+# Files updated with current templates
+```
+
+## 🐛 Troubleshooting
+
+### Common Issues
+
+**Permission Errors**
+```bash
+Error: Target path not writable
+```
+Solution: Ensure write permissions on target directory
+
+**Missing Dependencies**
+```bash
+Error: Composer autoload not found
+```
+Solution: Run `composer install` first
+
+**Invalid Package Names**
+```bash
+Error: Package name format incorrect
+```
+Solution: Use format "vendor/package" with lowercase and hyphens
+
+### Debug Mode
+
+For verbose output, use PHP's built-in debugging:
+
+```bash
+# Enable error reporting
+php -d display_errors=1 vendor/bin/sixshop-maker
+```
+
+## 🤝 Contributing
+
+We welcome contributions! Please see our contributing guidelines:
+
+1. Fork the repository
+2. Create a feature branch
+3. Make your changes
+4. Add tests if applicable
+5. Submit a pull request
+
+### Development Setup
+
+```bash
+# Clone and setup
+git clone https://github.com/sixshop/maker-bundle.git
+cd maker-bundle
+composer install
+
+# Run the tool locally
+php bin/sixshop-maker
+```
+
+## 📄 License
+
+This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
+
+## 👥 Authors
+
+- **runphp** - *Initial work* - [runphp@qq.com](mailto:runphp@qq.com)
+
+## 🔗 Links
+
+- [SixShop Framework](https://github.com/sixshop)
+- [ThinkPHP Framework](https://github.com/top-think/framework)
+- [Symfony Console](https://symfony.com/doc/current/console.html)
+
+## 📝 Changelog
+
+### v1.0.0
+- Initial release with core generation features
+- Smart existing extension detection
+- Flexible path management
+- Template-based file generation
+- PSR-4 compliant namespace handling
+
+---
+
+**Made with ❤️ for the SixShop community**

+ 12 - 16
bin/sixshop-maker

@@ -1,26 +1,22 @@
 #!/usr/bin/env php
 <?php
+declare(strict_types=1);
 
-$dir = __DIR__.'/..';
-
-if (!file_exists($dir.'/autoload.php')) {
-    $dir = __DIR__.'/../vendor';
-}
-
-if (!file_exists($dir.'/autoload.php')) {
-    $dir = __DIR__.'/../../..';
-}
-
-if (!file_exists($dir.'/autoload.php')) {
-    echo 'Autoload not found.';
+// 自动加载类
+if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
+    require __DIR__ . '/../vendor/autoload.php';
+} elseif (file_exists(__DIR__ . '/../../../autoload.php')) {
+    require __DIR__ . '/../../../autoload.php';
+} else {
+    echo "Error: Composer autoload not found.\n";
+    echo "Please run 'composer install' first.\n";
     exit(1);
 }
 
-require $dir.'/autoload.php';
-
-use SixShop\MakerBundle\Maker;
 use Symfony\Component\Console\Application;
+use SixShop\MakerBundle\Maker;
 
-$application = new Application();
+$application = new Application('SixShop Maker Bundle', '1.0.0');
 $application->add(new Maker());
+$application->setDefaultCommand('create_extension');
 $application->run();

+ 13 - 2
composer.json

@@ -1,9 +1,20 @@
 {
     "name": "six-shop/maker-bundle",
-    "description": "这个扩展用来生成sixshop扩展代码",
+    "description": "A powerful CLI tool for generating SixShop extension boilerplate code",
     "type": "library",
+    "keywords": [
+        "sixshop",
+        "thinkphp",
+        "generator",
+        "scaffold",
+        "cli",
+        "extension",
+        "maker",
+        "boilerplate"
+    ],
     "require": {
-        "topthink/framework": "^8.1"
+        "topthink/framework": "^8.1",
+        "symfony/console": "^7.3"
     },
     "license": "MIT",
     "minimum-stability": "dev",

+ 1241 - 0
composer.lock

@@ -0,0 +1,1241 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "49590416971fccb8400fbde46c4b31f7",
+    "packages": [
+        {
+            "name": "psr/container",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/container.git",
+                "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+                "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "support": {
+                "issues": "https://github.com/php-fig/container/issues",
+                "source": "https://github.com/php-fig/container/tree/2.0.2"
+            },
+            "time": "2021-11-05T16:47:00+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-message.git",
+                "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+                "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-message/tree/1.1"
+            },
+            "time": "2023-04-04T09:50:52+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "79dff0b268932c640297f5208d6298f71855c03e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e",
+                "reference": "79dff0b268932c640297f5208d6298f71855c03e",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/log/tree/3.0.1"
+            },
+            "time": "2024-08-21T13:31:24+00:00"
+        },
+        {
+            "name": "psr/simple-cache",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/simple-cache.git",
+                "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
+                "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\SimpleCache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interfaces for simple caching",
+            "keywords": [
+                "cache",
+                "caching",
+                "psr",
+                "psr-16",
+                "simple-cache"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
+            },
+            "time": "2021-10-29T13:26:27+00:00"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v7.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/console.git",
+                "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44",
+                "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/service-contracts": "^2.5|^3",
+                "symfony/string": "^7.2"
+            },
+            "conflict": {
+                "symfony/dependency-injection": "<6.4",
+                "symfony/dotenv": "<6.4",
+                "symfony/event-dispatcher": "<6.4",
+                "symfony/lock": "<6.4",
+                "symfony/process": "<6.4"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0|2.0|3.0"
+            },
+            "require-dev": {
+                "psr/log": "^1|^2|^3",
+                "symfony/config": "^6.4|^7.0",
+                "symfony/dependency-injection": "^6.4|^7.0",
+                "symfony/event-dispatcher": "^6.4|^7.0",
+                "symfony/http-foundation": "^6.4|^7.0",
+                "symfony/http-kernel": "^6.4|^7.0",
+                "symfony/lock": "^6.4|^7.0",
+                "symfony/messenger": "^6.4|^7.0",
+                "symfony/process": "^6.4|^7.0",
+                "symfony/stopwatch": "^6.4|^7.0",
+                "symfony/var-dumper": "^6.4|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Console\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Eases the creation of beautiful and testable command line interfaces",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "cli",
+                "command-line",
+                "console",
+                "terminal"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/console/tree/v7.3.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2025-05-24T10:34:04+00:00"
+        },
+        {
+            "name": "symfony/deprecation-contracts",
+            "version": "v3.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/deprecation-contracts.git",
+                "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+                "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.1"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.5-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "function.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "A generic function and convention to trigger deprecation notices",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-25T14:20:29+00:00"
+        },
+        {
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+                "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-ctype": "*"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-grapheme",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+                "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+                "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's grapheme_* functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "grapheme",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-normalizer",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+                "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+                "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's Normalizer class and related functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "intl",
+                "normalizer",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+                "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-mbstring": "*"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-12-23T08:48:59+00:00"
+        },
+        {
+            "name": "symfony/service-contracts",
+            "version": "v3.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/service-contracts.git",
+                "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+                "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.1",
+                "psr/container": "^1.1|^2.0",
+                "symfony/deprecation-contracts": "^2.5|^3"
+            },
+            "conflict": {
+                "ext-psr": "<1.1|>=2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/contracts",
+                    "name": "symfony/contracts"
+                },
+                "branch-alias": {
+                    "dev-main": "3.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\Service\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Test/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Generic abstractions related to writing services",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/service-contracts/tree/v3.5.1"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-25T14:20:29+00:00"
+        },
+        {
+            "name": "symfony/string",
+            "version": "v7.2.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/string.git",
+                "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
+                "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.2",
+                "symfony/polyfill-ctype": "~1.8",
+                "symfony/polyfill-intl-grapheme": "~1.0",
+                "symfony/polyfill-intl-normalizer": "~1.0",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/translation-contracts": "<2.5"
+            },
+            "require-dev": {
+                "symfony/emoji": "^7.1",
+                "symfony/error-handler": "^6.4|^7.0",
+                "symfony/http-client": "^6.4|^7.0",
+                "symfony/intl": "^6.4|^7.0",
+                "symfony/translation-contracts": "^2.5|^3.0",
+                "symfony/var-exporter": "^6.4|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/functions.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\String\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "grapheme",
+                "i18n",
+                "string",
+                "unicode",
+                "utf-8",
+                "utf8"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/string/tree/v7.2.6"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2025-04-20T20:18:16+00:00"
+        },
+        {
+            "name": "topthink/framework",
+            "version": "v8.1.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/framework.git",
+                "reference": "8faec5c9b7a7f2a66ca3140a57e81bd6cd37567c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/framework/zipball/8faec5c9b7a7f2a66ca3140a57e81bd6cd37567c",
+                "reference": "8faec5c9b7a7f2a66ca3140a57e81bd6cd37567c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-ctype": "*",
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "php": ">=8.0.0",
+                "psr/http-message": "^1.0",
+                "psr/log": "^1.0|^2.0|^3.0",
+                "psr/simple-cache": "^1.0|^2.0|^3.0",
+                "topthink/think-container": "^3.0",
+                "topthink/think-helper": "^3.1",
+                "topthink/think-orm": "^3.0|^4.0",
+                "topthink/think-validate": "^3.0"
+            },
+            "require-dev": {
+                "guzzlehttp/psr7": "^2.1.0",
+                "mikey179/vfsstream": "^1.6",
+                "mockery/mockery": "^1.2",
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [],
+                "psr-4": {
+                    "think\\": "src/think/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                },
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP Framework.",
+            "homepage": "http://thinkphp.cn/",
+            "keywords": [
+                "framework",
+                "orm",
+                "thinkphp"
+            ],
+            "support": {
+                "issues": "https://github.com/top-think/framework/issues",
+                "source": "https://github.com/top-think/framework/tree/v8.1.2"
+            },
+            "time": "2025-01-14T08:04:03+00:00"
+        },
+        {
+            "name": "topthink/think-container",
+            "version": "v3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-container.git",
+                "reference": "a24d442a02fb2a4716de232ff1a4f006c178a370"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-container/zipball/a24d442a02fb2a4716de232ff1a4f006c178a370",
+                "reference": "a24d442a02fb2a4716de232ff1a4f006c178a370",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.0",
+                "psr/container": "^2.0",
+                "topthink/think-helper": "^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "PHP Container & Facade Manager",
+            "support": {
+                "issues": "https://github.com/top-think/think-container/issues",
+                "source": "https://github.com/top-think/think-container/tree/v3.0.1"
+            },
+            "time": "2025-01-07T08:19:23+00:00"
+        },
+        {
+            "name": "topthink/think-helper",
+            "version": "v3.1.11",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-helper.git",
+                "reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-helper/zipball/1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
+                "reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.1.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP6 Helper Package",
+            "support": {
+                "issues": "https://github.com/top-think/think-helper/issues",
+                "source": "https://github.com/top-think/think-helper/tree/v3.1.11"
+            },
+            "time": "2025-04-07T06:55:59+00:00"
+        },
+        {
+            "name": "topthink/think-orm",
+            "version": "v4.0.50",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-orm.git",
+                "reference": "ddae72d5ff4d953d3d8cc526fd9c50e8862ce2cc"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-orm/zipball/ddae72d5ff4d953d3d8cc526fd9c50e8862ce2cc",
+                "reference": "ddae72d5ff4d953d3d8cc526fd9c50e8862ce2cc",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-pdo": "*",
+                "php": ">=8.0.0",
+                "psr/log": ">=1.0",
+                "psr/simple-cache": "^3.0",
+                "topthink/think-helper": "^3.1",
+                "topthink/think-validate": "^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.6|^10"
+            },
+            "suggest": {
+                "ext-mongodb": "provide mongodb support"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php",
+                    "stubs/load_stubs.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "the PHP Database&ORM Framework",
+            "keywords": [
+                "database",
+                "orm"
+            ],
+            "support": {
+                "issues": "https://github.com/top-think/think-orm/issues",
+                "source": "https://github.com/top-think/think-orm/tree/v4.0.50"
+            },
+            "time": "2025-08-26T05:32:22+00:00"
+        },
+        {
+            "name": "topthink/think-validate",
+            "version": "v3.0.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-validate.git",
+                "reference": "85063f6d4ef8ed122f17a36179dc3e0949b30988"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-validate/zipball/85063f6d4ef8ed122f17a36179dc3e0949b30988",
+                "reference": "85063f6d4ef8ed122f17a36179dc3e0949b30988",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=8.0",
+                "topthink/think-container": ">=3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helper.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "think validate",
+            "support": {
+                "issues": "https://github.com/top-think/think-validate/issues",
+                "source": "https://github.com/top-think/think-validate/tree/v3.0.7"
+            },
+            "time": "2025-06-11T05:51:40+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "dev",
+    "stability-flags": {},
+    "prefer-stable": true,
+    "prefer-lowest": false,
+    "platform": {},
+    "platform-dev": {},
+    "plugin-api-version": "2.6.0"
+}

+ 140 - 14
src/Generator/ComposerGenerator.php

@@ -17,11 +17,41 @@ class ComposerGenerator
     /**
      * 获取用户输入的包信息
      */
-    public function gatherPackageInfo(SymfonyStyle $io): ?array
+    public function gatherPackageInfo(SymfonyStyle $io, ?string $targetPath = null): ?array
     {
         try {
+            // 尝试读取现有的composer.json文件以获取默认值
+            $existingInfo = $this->readExistingComposerInfo($targetPath, $io);
+            
+            // 如果找到了完整的现有信息,询问用户是否直接使用
+            if ($this->hasCompleteExistingInfo($existingInfo)) {
+                $io->section('发现现有扩展配置');
+                $io->table(
+                    ['字段', '现有值'],
+                    [
+                        ['包名', $existingInfo['name'] ?? 'N/A'],
+                        ['描述', $existingInfo['description'] ?? 'N/A'],
+                        ['命名空间', $existingInfo['namespace'] ?? 'N/A'],
+                        ['扩展ID', $existingInfo['id'] ?? 'N/A']
+                    ]
+                );
+                
+                if ($io->confirm('是否使用现有配置重新生成扩展?', true)) {
+                    return [
+                        'packageName' => $existingInfo['name'],
+                        'description' => $existingInfo['description'],
+                        'namespace' => $existingInfo['namespace'],
+                        'id' => $existingInfo['id']
+                    ];
+                }
+            }
+            
             // 获取包名
-            $packageName = $io->ask('请输入Composer包名 (例如: six-shop/hello 或sixdec/abc)');
+            $defaultPackageName = $existingInfo['name'] ?? null;
+            $packageName = $io->ask(
+                '请输入Composer包名 (例如: six-shop/hello 或sixdec/abc)',
+                $defaultPackageName
+            );
             
             if (empty($packageName)) {
                 throw new \InvalidArgumentException('包名不能为空!');
@@ -33,14 +63,18 @@ class ComposerGenerator
             }
             
             // 获取包描述
-            $description = $io->ask('请输入包描述 (可选)', 'A SixShop extension package');
+            $defaultDescription = $existingInfo['description'] ?? 'A SixShop extension package';
+            $description = $io->ask('请输入包描述 (可选)', $defaultDescription);
             
             // 获取命名空间
-            $defaultNamespace = $this->generateDefaultNamespace($packageName);
-            $namespace = $io->ask('请输入命名空间 (例如: SixShop\\\\Hello)', $defaultNamespace);
+            $defaultNamespace = $existingInfo['namespace'] ?? $this->generateDefaultNamespace($packageName);
+            // 用户界面显示单反斜杠格式,用户输入也是单反斜杠
+            $userNamespace = $io->ask('请输入命名空间 (例如: SixShop\\Hello\\)', $defaultNamespace);
+            // PHP代码内部使用单反斜杠存储
+            $namespace = rtrim($userNamespace, '\\') . '\\';
             
             // 获取扩展ID
-            $defaultId = str_replace('/', '-', $packageName);
+            $defaultId = $existingInfo['id'] ?? str_replace('/', '-', $packageName);
             $id = $io->ask('请输入扩展ID (例如: six-shop-hello)', $defaultId);
             
             return [
@@ -63,7 +97,7 @@ class ComposerGenerator
         $parts = explode('/', $packageName);
         $vendor = $this->convertToNamespace($parts[0]);
         $package = $this->convertToNamespace($parts[1]);
-        return $vendor . '\\\\' . $package;
+        return $vendor . '\\' . $package . '\\';
     }
     
     /**
@@ -75,6 +109,93 @@ class ComposerGenerator
         $parts = array_map('ucfirst', $parts);
         return implode('', $parts);
     }
+    
+    /**
+     * 读取现有的composer.json文件以获取默认值
+     */
+    private function readExistingComposerInfo(?string $targetPath, SymfonyStyle $io): array
+    {
+        $existingInfo = [];
+        
+        if ($targetPath === null) {
+            return $existingInfo;
+        }
+        
+        if (is_dir($targetPath)) {
+            // 首先检查目标目录下是否直接有composer.json文件
+            $directComposerPath = $targetPath . '/composer.json';
+            if (file_exists($directComposerPath)) {
+                $existingInfo = $this->parseComposerFile($directComposerPath, $io);
+                if (!empty($existingInfo)) {
+                    return $existingInfo;
+                }
+            }
+            
+            // 然后扫描目标目录下的所有子目录,查找composer.json文件
+            $directories = array_filter(glob($targetPath . '/*'), 'is_dir');
+            
+            foreach ($directories as $dir) {
+                $composerPath = $dir . '/composer.json';
+                if (file_exists($composerPath)) {
+                    $existingInfo = $this->parseComposerFile($composerPath, $io);
+                    if (!empty($existingInfo)) {
+                        // 只取第一个找到的文件
+                        break;
+                    }
+                }
+            }
+        }
+        
+        return $existingInfo;
+    }
+    
+    /**
+     * 解析composer.json文件并提取相关信息
+     */
+    private function parseComposerFile(string $composerPath, SymfonyStyle $io): array
+    {
+        $existingInfo = [];
+        
+        $composerContent = file_get_contents($composerPath);
+        if ($composerContent !== false) {
+            $composerData = json_decode($composerContent, true);
+            if (json_last_error() === JSON_ERROR_NONE && is_array($composerData)) {
+                $io->note('发现现有的composer.json文件: ' . $composerPath);
+                
+                // 提取相关信息
+                $existingInfo['name'] = $composerData['name'] ?? null;
+                $existingInfo['description'] = $composerData['description'] ?? null;
+                
+                // 从 autoload PSR-4 中提取命名空间
+                if (isset($composerData['autoload']['psr-4'])) {
+                    $psr4 = $composerData['autoload']['psr-4'];
+                    $namespaces = array_keys($psr4);
+                    if (!empty($namespaces)) {
+                        // 取第一个命名空间,JSON已经解析为单反斜杠,保持PHP内部单反斜杠格式
+                        $existingInfo['namespace'] = rtrim($namespaces[0], '\\') . '\\';
+                    }
+                }
+                
+                // 从 extra.sixshop 中提取ID
+                if (isset($composerData['extra']['sixshop']['id'])) {
+                    $existingInfo['id'] = $composerData['extra']['sixshop']['id'];
+                }
+            }
+        }
+        
+        return $existingInfo;
+    }
+    
+    /**
+     * 检查是否有完整的现有信息
+     */
+    private function hasCompleteExistingInfo(array $existingInfo): bool
+    {
+        return !empty($existingInfo['name']) && 
+               !empty($existingInfo['description']) && 
+               !empty($existingInfo['namespace']) && 
+               !empty($existingInfo['id']);
+    }
 
     /**
      * 生成composer.json内容
@@ -97,11 +218,9 @@ class ComposerGenerator
     /**
      * 保存composer.json文件到指定目录
      */
-    public function saveComposerFile(string $packageName, string $content, SymfonyStyle $io): bool
+    public function saveComposerFile(string $packageName, string $content, string $targetPath, SymfonyStyle $io): bool
     {
-        // 获取vendor上级目录并构建路径: runtime/extension/{package-name}/
-        $vendorDir = dirname(__DIR__, 5); // 从当前文件位置向上5级到vendor上级目录
-        $extensionDir = $vendorDir . '/runtime/extension/' . $packageName;
+        $extensionDir = $targetPath;
 
         // 确保目录存在
         if (!is_dir($extensionDir)) {
@@ -124,7 +243,7 @@ class ComposerGenerator
     /**
      * 完整的生成和保存流程
      */
-    public function createComposerJson(string $packageName, string $namespace, string $id, string $description, SymfonyStyle $io): bool
+    public function createComposerJson(string $packageName, string $namespace, string $id, string $description, string $targetPath, SymfonyStyle $io): bool
     {
         try {
             // 生成内容
@@ -136,7 +255,7 @@ class ComposerGenerator
 
             // 询问是否保存文件
             if ($io->confirm('是否将内容保存到 composer.json 文件?', true)) {
-                return $this->saveComposerFile($packageName, $content, $io);
+                return $this->saveComposerFile($packageName, $content, $targetPath, $io);
             }
 
             return true;
@@ -149,18 +268,25 @@ class ComposerGenerator
     /**
      * 完整的从用户输入到生成文件的工作流
      */
-    public function createComposerFromUserInput(SymfonyStyle $io): bool
+    public function createComposerFromUserInput(SymfonyStyle $io, ?string $targetPath = null): bool
     {
         try {
             // 获取用户输入
             $packageInfo = $this->gatherPackageInfo($io);
             
+            // 如果没有提供目标路径,使用默认路径
+            if ($targetPath === null) {
+                $vendorDir = dirname(__DIR__, 5);
+                $targetPath = $vendorDir . '/runtime/extension';
+            }
+            
             // 生成composer.json
             return $this->createComposerJson(
                 $packageInfo['packageName'],
                 $packageInfo['namespace'],
                 $packageInfo['id'],
                 $packageInfo['description'],
+                $targetPath,
                 $io
             );
         } catch (\InvalidArgumentException $e) {

+ 13 - 9
src/Generator/DirectoryGenerator.php

@@ -10,11 +10,11 @@ class DirectoryGenerator
     /**
      * 生成扩展的基础目录结构
      */
-    public function createDirectoryStructure(string $packageName, SymfonyStyle $io): bool
+    public function createDirectoryStructure(string $packageName, string $targetPath, SymfonyStyle $io): bool
     {
         try {
             // 获取基础路径
-            $basePath = $this->getBasePath($packageName);
+            $basePath = $this->getBasePath($packageName, $targetPath);
             
             // 定义需要创建的目录结构
             $directories = $this->getDirectoryStructure();
@@ -41,9 +41,13 @@ class DirectoryGenerator
     /**
      * 获取扩展基础路径
      */
-    private function getBasePath(string $packageName): string
+    private function getBasePath(string $packageName, ?string $targetPath = null): string
     {
-        // 获取vendor上级目录并构建路径: runtime/extension/{package-name}/
+        if ($targetPath !== null) {
+            return $targetPath;
+        }
+        
+        // 默认路径
         $vendorDir = dirname(__DIR__, 5); // 从当前文件位置向上5级到vendor上级目录
         return $vendorDir . '/runtime/extension/' . $packageName;
     }
@@ -96,24 +100,24 @@ class DirectoryGenerator
     /**
      * 检查目录是否已存在
      */
-    public function directoryExists(string $packageName): bool
+    public function directoryExists(string $packageName, ?string $targetPath = null): bool
     {
-        $basePath = $this->getBasePath($packageName);
+        $basePath = $this->getBasePath($packageName, $targetPath);
         return is_dir($basePath);
     }
     
     /**
      * 获取目录结构信息
      */
-    public function getDirectoryInfo(string $packageName): array
+    public function getDirectoryInfo(string $packageName, ?string $targetPath = null): array
     {
-        $basePath = $this->getBasePath($packageName);
+        $basePath = $this->getBasePath($packageName, $targetPath);
         $directories = $this->getDirectoryStructure();
         
         $info = [
             'basePath' => $basePath,
             'directories' => [],
-            'exists' => $this->directoryExists($packageName)
+            'exists' => $this->directoryExists($packageName, $targetPath)
         ];
         
         foreach ($directories as $dir) {

+ 4 - 6
src/Generator/GitignoreGenerator.php

@@ -32,11 +32,9 @@ class GitignoreGenerator
     /**
      * 保存.gitignore文件到指定目录
      */
-    public function saveGitignoreFile(string $packageName, string $content, SymfonyStyle $io): bool
+    public function saveGitignoreFile(string $packageName, string $content, string $targetPath, SymfonyStyle $io): bool
     {
-        // 获取vendor上级目录并构建路径: runtime/extension/{package-name}/
-        $vendorDir = dirname(__DIR__, 5); // 从当前文件位置向上5级到vendor上级目录
-        $extensionDir = $vendorDir . '/runtime/extension/' . $packageName;
+        $extensionDir = $targetPath;
 
         // 确保目录存在
         if (!is_dir($extensionDir)) {
@@ -59,7 +57,7 @@ class GitignoreGenerator
     /**
      * 完整的生成和保存流程
      */
-    public function createGitignore(string $packageName, SymfonyStyle $io): bool
+    public function createGitignore(string $packageName, string $targetPath, SymfonyStyle $io): bool
     {
         try {
             // 生成内容
@@ -71,7 +69,7 @@ class GitignoreGenerator
 
             // 询问是否保存文件
             if ($io->confirm('是否将内容保存到 .gitignore 文件?', true)) {
-                return $this->saveGitignoreFile($packageName, $content, $io);
+                return $this->saveGitignoreFile($packageName, $content, $targetPath, $io);
             }
 
             return true;

+ 8 - 3
src/Generator/PhpCodeGenerator.php

@@ -17,10 +17,10 @@ class PhpCodeGenerator
     /**
      * 生成PHP代码文件
      */
-    public function generatePhpFiles(string $packageName, string $namespace, string $id, string $description, SymfonyStyle $io): bool
+    public function generatePhpFiles(string $packageName, string $namespace, string $id, string $description, string $targetPath, SymfonyStyle $io): bool
     {
         try {
-            $basePath = $this->getBasePath($packageName);
+            $basePath = $this->getBasePath($packageName, $targetPath);
             
             // 准备模板变量
             $variables = [
@@ -53,8 +53,13 @@ class PhpCodeGenerator
     /**
      * 获取扩展基础路径
      */
-    private function getBasePath(string $packageName): string
+    private function getBasePath(string $packageName, ?string $targetPath = null): string
     {
+        if ($targetPath !== null) {
+            return $targetPath;
+        }
+        
+        // 默认路径
         $vendorDir = dirname(__DIR__, 5);
         return $vendorDir . '/runtime/extension/' . $packageName;
     }

+ 63 - 4
src/Maker.php

@@ -41,8 +41,14 @@ class Maker extends Command
     {
         $io = new SymfonyStyle($input, $output);
         
-        // 获取用户输入的包信息
-        $packageInfo = $this->composerGenerator->gatherPackageInfo($io);
+        // 获取用户输入的目标路径
+        $targetPath = $this->getTargetPath($io);
+        if (!$targetPath) {
+            return Command::FAILURE;
+        }
+        
+        // 获取用户输入的包信息(现在会检测目标路径下的composer.json)
+        $packageInfo = $this->composerGenerator->gatherPackageInfo($io, $targetPath);
         if (!$packageInfo) {
             return Command::FAILURE;
         }
@@ -54,6 +60,7 @@ class Maker extends Command
             $packageInfo['namespace'],
             $packageInfo['id'],
             $packageInfo['description'],
+            $targetPath,
             $io
         )) {
             return Command::FAILURE;
@@ -61,13 +68,13 @@ class Maker extends Command
         
         // 创建目录结构
         $io->section('创建目录结构');
-        if (!$this->directoryGenerator->createDirectoryStructure($packageInfo['packageName'], $io)) {
+        if (!$this->directoryGenerator->createDirectoryStructure($packageInfo['packageName'], $targetPath, $io)) {
             return Command::FAILURE;
         }
         
         // 生成 .gitignore 文件
         $io->section('生成 .gitignore 文件');
-        if (!$this->gitignoreGenerator->createGitignore($packageInfo['packageName'], $io)) {
+        if (!$this->gitignoreGenerator->createGitignore($packageInfo['packageName'], $targetPath, $io)) {
             return Command::FAILURE;
         }
         
@@ -78,6 +85,7 @@ class Maker extends Command
             $packageInfo['namespace'],
             $packageInfo['id'],
             $packageInfo['description'],
+            $targetPath,
             $io
         )) {
             return Command::FAILURE;
@@ -86,4 +94,55 @@ class Maker extends Command
         $io->success('扩展创建完成!');
         return Command::SUCCESS;
     }
+    
+    /**
+     * 获取用户输入的目标路径
+     */
+    private function getTargetPath(SymfonyStyle $io): ?string
+    {
+        try {
+            // 获取当前工作目录作为默认值
+            $defaultPath = getcwd();
+            
+            $targetPath = $io->ask(
+                '请输入扩展生成的目标路径 (绝对路径或相对路径)',
+                $defaultPath
+            );
+            
+            if (empty($targetPath)) {
+                throw new \InvalidArgumentException('目标路径不能为空!');
+            }
+            
+            // 转换为绝对路径
+            $absolutePath = realpath($targetPath);
+            if ($absolutePath === false) {
+                // 如果路径不存在,尝试创建它
+                if (!is_dir($targetPath)) {
+                    $io->note('目标路径不存在,尝试创建目录: ' . $targetPath);
+                    if (!mkdir($targetPath, 0755, true)) {
+                        throw new \InvalidArgumentException('无法创建目标路径: ' . $targetPath);
+                    }
+                }
+                $absolutePath = realpath($targetPath);
+            }
+            
+            // 检查路径是否可写
+            if (!is_writable($absolutePath)) {
+                throw new \InvalidArgumentException('目标路径不可写: ' . $absolutePath);
+            }
+            
+            $io->note('将在以下路径生成扩展: ' . $absolutePath);
+            
+            // 确认路径
+            if (!$io->confirm('确认使用此路径?', true)) {
+                return $this->getTargetPath($io); // 递归重新获取路径
+            }
+            
+            return $absolutePath;
+            
+        } catch (\InvalidArgumentException $e) {
+            $io->error($e->getMessage());
+            return null;
+        }
+    }
 }

+ 14 - 17
templates/.gitignore.tpl.php

@@ -1,39 +1,36 @@
+<?php ?>
 # Dependencies
 /vendor/
 /node_modules/
-
-# Environment files
+/.idea/
+/.vscode/
+.DS_Store
+Thumbs.db
+*.log
+*.cache
 .env
 .env.local
-.env.*.local
+/runtime/
+/temp/
+/cache/
+composer.lock
+package-lock.json
+
+# Environment files
 
 # IDE files
-.vscode/
-.idea/
-*.swp
-*.swo
 
 # OS files
-.DS_Store
-Thumbs.db
 
 # Log files
-*.log
-/logs/
 
 # Cache and temporary files
-/cache/
-/tmp/
-*.tmp
 
 # Build artifacts
 /dist/
 /build/
 
 # PHP specific
-composer.phar
-/runtime/
-*.cache
 
 # Test coverage
 /coverage/

+ 3 - 2
templates/composer.json.tpl.php

@@ -1,3 +1,4 @@
+<?php ?>
 {
   "name": "<?= $name ?>",
   "description": "<?= $description ?>",
@@ -19,13 +20,13 @@
   "license": "MIT",
   "autoload": {
     "psr-4": {
-      "<?= $namespace ?>\\": "src"
+      <?= json_encode($namespace) ?>: "src"
     }
   },
   "extra": {
     "sixshop": {
       "id": "<?= $id ?>",
-      "class": "<?= $namespace ?>\\Extension"
+      "class": <?= json_encode($namespace . 'Extension') ?>
     }
   },
   "minimum-stability": "dev",