Spiral 框架 3.0 版本的发布带来了对 2.x 系列的重大增强和改变,包括对 Symfony 6.x 和 7.x 组件的支持,各种错误修复和可用性改进。
Spiral 框架 3.x 要求最低 PHP 版本为 8.1。
现在,Spiral 中的所有类和接口都包含了类型化的参数、属性和返回类型。如果你的应用程序或包扩展了任何 Spiral 的核心类并重写了这些方法或属性,则需要在你的代码中引入类型声明。
最初,请关注
InjectableConfig::$config
属性,该属性现在必须被类型化为数组。
请注意,许多类属性在最新版本中已被标记为 readonly
。如果你的代码涉及直接设置 Spiral 核心对象中的值,你需要验证这些属性是否仍然可以被覆盖。此更改要求你调整与 Spiral 核心对象的交互方式,可能需要使用构造函数参数或专用方法来设置这些值。
更新应用程序的 composer.json
文件中的依赖项以确保与 Spiral 框架 3.x 兼容至关重要。请按照以下说明更新并添加必要的包。
修改你的 composer.json
以更新以下包:
symfony/console
更新到 ^6.0
spiral/framework
更新到 ^3.0
spiral/cycle-bridge
更新到 ^2.0
spiral/roadrunner-bridge
更新到 ^3.0
spiral/nyholm-bridge
更新到 ^1.3
spiral/testing
更新到 ^2.0
更新并添加这些依赖项后,运行 composer update
以安装新版本,并确保你的项目已准备好用于 Spiral 3.x。
Environment
类不再覆盖现有的环境变量(ENV)。
现在,在你的 .env
文件中定义的变量可以被外部环境变量覆盖。这意味着在服务器级别或作为系统级环境变量设置的变量将具有优先权。此更改还允许你专门为 PHPUnit 设置环境变量。
要恢复到之前的行为,即 .env
文件变量可以覆盖外部环境变量,你需要使用 overwrite 参数设置为 true
来实例化 \Spiral\Boot\Environment
对象。
App::create(
directories: ['root' => __DIR__]
)->run(new \Spiral\Boot\Environment(overwrite: true));
关于如何处理环境变量的更多信息
Bootloader 不再自动在应用程序中注册中间件。
以下列表包括以前通过特定 Bootloader 注册的中间件。在更新后,这些中间件需要根据你的应用程序需求和所需的执行顺序手动注册:
Spiral\Broadcasting\Bootloader\WebsocketsBootloader
-> Spiral\Broadcasting\Middleware\AuthorizationMiddleware
Spiral\Bootloader\Auth\HttpAuthBootloader
-> Spiral\Auth\Middleware\AuthMiddleware
Spiral\Bootloader\Debug\HttpCollectorBootloader
-> Spiral\Debug\StateCollector\HttpCollector
Spiral\Bootloader\Http\CookiesBootloader
-> Spiral\Cookies\Middleware\CookiesMiddleware
Spiral\Bootloader\Http\CsrfBootloader
-> Spiral\Csrf\Middleware\CsrfMiddleware
Spiral\Bootloader\Http\ErrorHandlerBootloader
-> Spiral\Http\Middleware\ErrorHandlerMiddleware
Spiral\Bootloader\Http\JsonPayloadsBootloader
-> Spiral\Http\Middleware\JsonPayloadMiddleware
Spiral\Bootloader\Http\SessionBootloader
-> Spiral\Session\Middleware\SessionMiddleware
此更改使你能够灵活地选择对你的应用程序至关重要的中间件以及它们应该被集成的顺序。
关于 HTTP 中间件的更多信息
<?php
declare(strict_types=1);
namespace App\Bootloader;
use App\Controller\AuthController;
use App\Controller\HomeController;
use App\Controller\PageController;
use Spiral\Auth\Middleware\AuthMiddleware;
use Spiral\Bootloader\Http\RoutesBootloader as BaseRoutesBootloader;
use Spiral\Cookies\Middleware\CookiesMiddleware;
use Spiral\Csrf\Middleware\CsrfMiddleware;
use Spiral\Debug\StateCollector\HttpCollector;
use Spiral\Http\Middleware\ErrorHandlerMiddleware;
use Spiral\Http\Middleware\JsonPayloadMiddleware;
use Spiral\Router\Loader\Configurator\RoutingConfigurator;
use Spiral\Session\Middleware\SessionMiddleware;
final class RoutesBootloader extends BaseRoutesBootloader
{
protected function globalMiddleware(): array
{
return [
ErrorHandlerMiddleware::class,
JsonPayloadMiddleware::class,
HttpCollector::class
];
}
protected function middlewareGroups(): array
{
return [
'web' => [
CookiesMiddleware::class,
SessionMiddleware::class,
CsrfMiddleware::class,
AuthMiddleware::class,
],
'api' => [
//
]
];
}
}
Spiral 的 HTTP 组件不再开箱即用默认实现 Spiral\Http\EmitterInterface
。
要在你的应用程序中使用 HTTP 时包含一个 emitter 实现,例如,如果你想将 Spiral 与 nginx
一起使用,你可以通过运行以下命令添加一个特定的包:
composer require spiral/sapi-bridge
之后,确保在你的应用程序的引导过程中注册必要的 bootloader。这可以通过在你的应用程序的 bootloader 配置中的 LOAD 数组中包含 Spiral\Sapi\Bootloader\SapiBootloader
类来完成:
protected const LOAD = [
// ...
\Spiral\Sapi\Bootloader\SapiBootloader::class,
];
关于如何在文档中安装和配置 RoadRunner bridge 的[更多信息]。
Spiral 已停止使用其自己的 PSR-7 接口实现,而是选择集成 nyholm/psr7
包。
由于此更改,以下类已从框架中删除:
Spiral\Bootloader\Http\DiactorosBootloader
Spiral\Http\Diactoros\ResponseFactory
Spiral\Http\Diactoros\ServerRequestFactory
Spiral\Http\Diactoros\StreamFactory
Spiral\Http\Diactoros\UploadedFileFactory
Spiral\Http\Diactoros\UriFactory
为了适应此更改,你应该切换到使用 nyholm/psr7
用于 PSR-7 HTTP 消息接口。这涉及更新你的应用程序的依赖项,并可能调整先前依赖于现已删除的 Spiral 类的任何自定义实现。这种转变使 Spiral 与广泛采用的且社区支持的 PSR-7 实现保持一致,从而促进了互操作性和标准化。
Spiral 对用于错误处理的 RendererInterface
进行了重大更改。具体来说,Spiral\Http\ErrorHandler\RendererInterface
中 renderException
方法的第三个参数已被修改。以前接受字符串作为错误消息,现在需要一个 \Throwable
作为异常本身。
更新后的方法签名如下:
interface RendererInterface
{
public function renderException(Request $request, int $code, \Throwable $exception): Response;
}
此更改意味着在实现 RendererInterface
时,你的方法现在必须处理一个 \Throwable
对象,而不是一个简单的字符串消息。此调整允许更详细的错误处理和报告,因为整个异常对象,包括其堆栈跟踪和其他详细信息,可以在 renderException 方法中使用。
我们不再使用 laminas/diactoros
包。将其替换为 nyholm/psr7
Spiral 现在支持自定义输入包的定义,在处理不同类型的输入数据方面提供了更大的灵活性。
以下示例说明了如何定义一个自定义输入包,以使用 Symfony 的 FilesBag 处理文件上传。
<?php
declare(strict_types=1);
namespace App\Bootloader;
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Bootloader\Http\HttpBootloader;
use Spiral\Validation\Symfony\Http\Request\FilesBag;
class SampleBootloader extends Bootloader
{
public function init(HttpBootloader $http): void
{
$http->addInputBag('symfonyFiles', [
'class' => FilesBag::class,
'source' => 'getUploadedFiles',
'alias' => 'symfony-file'
]);
}
}
要通过自定义输入包访问文件,你可以使用以下方法:
$container->get(\Spiral\Http\Request\InputManager::class)->symfonyFiles('avatar');
此功能增强了 Spiral 内输入处理的模块化和可扩展性,使开发人员能够根据其应用程序的特定需求定制框架的请求处理能力。
关于 HTTP 输入管理器的更多信息
InputBag
类的默认行为已更改,涉及其如何处理具有 null
值的键。此调整会影响你检查 InputBag
实例中键的存在及其值的方式。
以前,人们可能隐式地期望 has
和 isset
的行为保持一致。然而,在更新后的行为中,存在区别:
use Spiral\Http\Request\InputBag;
$bag = new InputBag([4 => null]);
$bag->has(4); // true
isset($bag[4]); // false
此更改强调了检查包中键的存在(has
方法)与检查键是否存在且具有非空值(isset
)之间的区别。has
方法只是验证键的存在,而不考虑它的值,而 isset
检查键,并确保该值不为 null。
作为 Spiral 不断发展的一部分,几个 bootloader 已被重新定位到它们各自的组件命名空间中。此重组旨在改进模块化,并使管理框架内的特定功能更容易。下面是已移动的 bootloader 及其新位置的列表:
Spiral\Bootloader\TokenizerBootloader
-> Spiral\Tokenizer\Bootloader\TokenizerBootloader
Spiral\Bootloader\AttributesBootloader
-> Spiral\Attributes\Bootloader\AttributesBootloader
Spiral\Bootloader\Distribution\DistributionBootloader
-> Spiral\Distribution\Bootloader\DistributionBootloader
Spiral\Bootloader\Distribution\DistributionConfig
-> Spiral\Distribution\Config\DistributionConfig
Spiral\Bootloader\Storage\StorageBootloader
-> Spiral\Storage\Bootloader\StorageBootloader
Spiral\Bootloader\Storage\StorageConfig
-> Spiral\Storage\Config\StorageConfig
Spiral\Bootloader\Security\ValidationBootloader
-> Spiral\Validation\Bootloader\ValidationBootloader
Spiral\Bootloader\Views\ViewsBootloader
-> Spiral\Views\Bootloader\ViewsBootloader
Spiral\Bootloader\Http\DiactorosBootloade
-> Spiral\Http\Bootloader\DiactorosBootloader
Spiral 的 bootloading 过程中已经进行了重要的重命名方法,以更好地反映它们的目的和功能:
boot
方法已重命名为 init
。start
方法已重命名为 boot
。此更改旨在阐明 bootloader 的生命周期阶段。现在,init
方法用于初始设置和配置,而 boot
方法用于启动或启用 bootloader 提供的功能。
Spiral 现在自动 bootload 在 bootloader 的 init
和 boot
方法中声明的所有依赖项。这意味着你不再需要在 DEPENDENCIES
常量中显式列出 bootloader,以便框架识别和加载它们。
例如,直接将 bootloader 注入到 boot 或 init 方法中:
public function boot(AttributesBootloader $bootloader)
// or
public function init(AttributesBootloader $bootloader)
在功能上等同于声明依赖项的先前方法:
protected const DEPENDENCIES = [
AttributesBootloader::class,
];
此增强通过减少冗余并使过程更直观来简化 bootloader 的配置。
关于 bootloader 的更多信息
Spiral\Boot\AbstractKernel::init
方法已被删除。为了初始化应用程序,应该使用 create
方法作为替代。此更改简化了设置和运行 Spiral 应用程序的过程。
要初始化并运行你的应用程序,现在应该使用以下方法:
App::create(
directories: ['root' => __DIR__]
)->run();
Spiral\Boot\AbstractKernel
的 create
方法已被标记为 final。此修改表明该方法不能被覆盖。
Spiral\Boot\AbstractKernel
内的方法命名已更新,以更好地反映其功能:
starting
方法已重命名为 booting
。started
方法已重命名为 booted
。Spiral 增强了 InjectableConfig
类,以自动合并在 InjectableConfig
子类的 $config
属性中指定的预定义配置,以及从外部配置文件加载的配置。这种改进通过允许预定义的默认值通过外部配置文件轻松覆盖或扩展,从而促进了更灵活和动态的配置管理。
考虑以下示例,其中自定义配置类扩展了 InjectableConfig
类。该类中的预定义配置将与外部配置文件的内容合并:
class SomeConfig extends \Spiral\Core\InjectableConfig
{
// 预定义的默认配置
protected array $config = [ // <=== 将与 some-config.php 中的数据合并
'default' => 'sync',
'aliases' => []
];
}
假设你有一个外部配置文件 app/config/some-config.php
,其中包含附加或覆盖设置:
// app/config/some-config.php
return [
'aliases' => [...]
];
当实例化并从容器中获取 SomeConfig
类时,生成的配置将是预定义的 $config
数组和 some-config.php
文件内容的合并版本。
var_dump($container->get(SomeConfig::class)->default); // sync
这种机制确保了可以在代码中直接指定默认设置,同时允许通过外部配置文件进行灵活的覆盖或添加,从而结合了两种方法管理应用程序配置的优点。
关于可注入配置的更多信息
spiral/data-grid 包不再默认与 Spiral 框架捆绑在一起。如果你的应用程序依赖于数据网格组件,你现在需要将其显式包含为依赖项。
要将数据网格组件添加到你的项目中,请执行以下命令:
composer require spiral/data-grid
有关如何将数据网格组件作为独立包安装和使用的详细说明,包括其设置和配置,请参阅文档。
Spiral 对其队列系统进行了重大更改,从 Spiral\Queue\QueueTrait
中删除了 pushCallable
方法。这意味着默认情况下不再支持将对象和 callable 直接推入队列,因为框架已停止开箱即用地使用 opis/closure
。
Spiral 框架已经演进其验证方法,不再将其核心包中提供默认的验证器。此决定使开发人员能够选择最适合其项目需求的验证工具,从而确保在应用程序开发中更大的灵活性和适应性。
现在,开发人员有机会在几个验证选项中进行选择,包括:
或创建他们自己的验证器
目前,框架中没有 Spiral\Validation\ValidationInterface
的默认实现。要在你的 Spiral 项目中集成验证,你应该从上面提供的选项或其他首选验证器中选择一个验证器,然后通过 Composer 安装它。例如,要使用 Spiral 自己的验证包:
composer require spiral/validatior
选择并安装验证器后,你必须在应用程序的 bootloader 中将 ValidationInterface
与你选择的实现绑定。
use Spiral\Validation\ValidationInterface;
use Spiral\Validation\ValidationProviderInterface;
use Spiral\Validator\FilterDefinition;
class AppBootloader extends Bootloader
{
protected const SINGLETONS = [
ValidationInterface::class => [self::class, 'initValidation'],
];
// ...
public function initValidation(ValidationProviderInterface $provider): ValidationInterface
{
return $provider->getValidation(FilterDefinition::class);
}
}
常量 Spiral\Monolog\LogFactory::DEFAULT
已在 Spiral 框架的 2.x 版本中被弃用,并在 3.x 版本中被删除。作为替代方案,请使用 Spiral\Monolog\Config\MonologConfig::DEFAULT_CHANNEL
来引用默认的日志记录通道。
此更改需要在你的应用程序的日志记录配置或先前依赖于 LogFactory::DEFAULT
的任何代码引用中进行更新。应进行调整以使用 MonologConfig::DEFAULT_CHANNEL
以确保与 Spiral 框架 3.x 兼容。
要配置默认的 Monolog 通道,你可以如下设置一个环境变量:
# ...
MONOLOG_DEFAULT_CHANNEL=stderr
此外,你可以在应用程序的配置文件中直接在 Monolog 配置数组中指定此默认通道并配置处理程序和处理器:
[
'default' => env('MONOLOG_DEFAULT_CHANNEL', 'stderr'),
'handlers' => [
'default' => [
// ...
],
'stderr' => [
// ...
],
'stdout' => [
// ...
],
],
'processors' => [
'default' => [
// ...
],
'stdout' => [
// ...
],
],
]
参见 pull request
在 Spiral 框架 3.x 中,内置的 RoadRunner 集成已被删除,以简化核心框架并在选择服务器解决方案时提供更大的灵活性。对于需要 RoadRunner 集成的项目:
以下组件也已被删除并替换为其各自的替代方案:
spiral/jobs
不再是 Spiral 框架的一部分。相反,请使用 spiral/queue 组件进行作业队列管理。spiral/broadcast
已被 spiral/broadcasting 组件替换,提供增强的事件广播功能。Spiral 框架 3.x 已将其与 cycle/orm
、cycle/database
和 cycle/migrations
的直接集成解耦,从而允许更模块化的架构。要将 CycleORM 集成到你的 Spiral 项目中:
Spiral 框架现在通过 Spiral\Exceptions\ExceptionHandler
集中了所有异常处理,消除了在代码库中进行异常管理时对额外的 snapshotter 和 logger 组件的需求。
更新后的 ExceptionHandler
支持为特定环境注册自定义异常渲染器和报告器,从而增强了对异常处理和报告的灵活性和控制。
关于异常处理的更多信息
添加了一个新方法 Spiral\Filters\InputInterface::hasValue
Filters 组件经历了完全的重新设计。要在 3.0 环境中使用 Spiral 版本 2.x 中的过滤器,请包含 spiral/filters-bridge 包。
spiral/validation
组件的验证器。以下示例演示了重新设计的过滤器的使用:
use Spiral\Filters\Attribute\Input;
use Spiral\Filters\Attribute\NestedArray;
use Spiral\Filters\Attribute\NestedFilter;
use Spiral\Filters\Attribute\Setter;
class CreateUserFilter extends SymfonyFilter
{
#[Asset\NotBlank]
#[Asset\Length(['min' => 30])]
#[Input\Post]
public string $username;
#[Asset\NotBlank]
#[Asset\Length(['min' => 30])]
#[Input\Post(key: 'first_name')]
public string $name;
#[Asset\NotBlank]
#[Asset\Length(['min' => 30])]
#[Input\Query(key: 'last_name')]
public string $lastName;
#[Input\Query(key: 'page_num')]
public int $page;
#[Asset\NotBlank]
#[Input\Attribute]
private string $wsPath;
#[Asset\NotBlank]
#[Input\BearerToken]
public string $token;
#[Input\Cookie(key: 'utm_source')]
public string $utmSource;
#[Input\Cookie]
public string $utmId;
#[NestedArray(
class: UserTagsFilter::class,
input: new Inout\Post('tags')
)]
public array $tags = [];
#[NestedFilter(class: UtmFilter::class)]
public UtmFilter $utm;
#[Input\Post]
#[Setter(filter: 'md5')]
public string $password;
}
class UserController
{
public function createUser(CreateUserFilter $filter): array
{
$user = new User(
$filter->username,
$filter->firstName,
$filter->lastName
);
$user->setUtmData(
$filter->utm->id,
$filter->utm->source,
...
);
foreach($filter->tags as $tag) {
$user->addTag($tag->role);
}
$this->em->persist($user);
}
}
关于过滤器的更多信息
假设你需要确定你的应用程序是否正在生产模式下运行。一个简单的方法是检查 $env->get('APP_ENV') === 'production'
。但是,枚举提供了更方便和类型安全的选择。
enum AppEnvironment: string
{
case Production = 'prod';
case Stage = 'stage';
case Testing = 'testing';
case Local = 'local';
public function isProduction(): bool
{
return $this === self::Production;
}
}
当容器解析枚举类时,它将提供一个枚举对象,其中包含在环境中定义的值。
class MigrateCommand extends Command
{
const NAME = '...';
// 解析并检测当前环境
public function perform(AppEnvironment $appEnv): int
{
if ($appEnv->isProduction()) {
// 拒绝
return 0;
}
// ...
return 1;
}
}
要使用此功能,请实现 Spiral\Boot\Injector\InjectableEnumInterface
并使用 Spiral\Boot\Injector\ProvideFrom
属性来指定一个返回特定枚举对象的方法。
<?php
declare(strict_types=1);
namespace Spiral\Boot\Environment;
use Spiral\Boot\EnvironmentInterface;
use Spiral\Boot\Injector\ProvideFrom;
use Spiral\Boot\Injector\InjectableEnumInterface;
#[ProvideFrom(method: 'detect')]
enum DebugMode implements InjectableEnumInterface
{
case Enabled;
case Disabled;
public function isEnabled(): bool
{
return $this === self::Enabled;
}
public static function detect(EnvironmentInterface $environment): self
{
return \filter_var($environment->get('DEBUG'), \FILTER_VALIDATE_BOOL) ? self::Enabled : self::Disabled;
}
}
}
这种方法通过利用枚举进行特定于环境的逻辑来增强类型安全性和代码清晰度。
关于可注入枚举的更多信息
Spiral 框架引入了一个新组件 spiral/serializer
,用于有效载荷的序列化和反序列化。此组件具有灵活性,支持用于各种序列化格式的自定义驱动程序。
要配置序列化程序组件,你需要在 app/config/serializer.php
文件中定义你喜欢的序列化程序:
// app/config/serializer.php
use Spiral\Core\Container\Autowire;
return [
'default' => env('DEFAULT_SERIALIZER_FORMAT', 'json'),
'serializers' => [
'json' => JsonSerializer::class,
'yaml' => new YamlSerializer(),
'custom' => new Autowire(CustomSerializer::class),
],
];
下面是一个使用序列化程序组件在将有效负载推送到管道之前对其进行序列化的 Queue
类的示例:
class Queue
{
public function __construct(
private readonly PipelineInterface $pipeline,
private readonly \Spiral\Serializer\SerializerInterface $serializer,
) {}
public function push(array $payload): void
{
$this->pipeline->push(
$this-serializer->serialize($payload),
);
}
}
在需要动态选择序列化格式的情况下,你可以使用 SerializerManager
根据运行时提供的选项检索合适的序列化程序:
class Queue
{
public function __construct(
private readonly PipelineInterface $pipeline,
private readonly \Spiral\Serializer\SerializerManager $manager
) {}
public function push(array $payload, Options $options): void
{
// $options->format = 'json'
// $options->format = 'xml'
// ...
$this->pipeline->push(
$this-manager
->getSerializer($options->format)
->serialize($payload)
);
}
}
关于序列化程序组件的更多信息
自 3.6 版本发布以来,Spiral 提供了使用 PHP 属性定义控制台命令的功能。这允许使用更直观和简化的方法定义具有明确关注点分离的命令。
以下是使用属性定义控制台命令的示例:
namespace App\Api\Cli\Command;
use Spiral\Console\Attribute\Argument;
use Spiral\Console\Attribute\AsCommand;
use Spiral\Console\Attribute\Option;
use Spiral\Console\Attribute\Question;
use Spiral\Console\Command;
use Symfony\Component\Console\Input\InputOption;
#[AsCommand(
name: 'app:create:user',
description: 'Creates a user with the given data')
]
final class CreateUser extends Command
{
#[Argument]
private string $email;
#[Argument(description: 'User password')]
private string $password;
#[Argument(name: 'username', description: 'The user name')]
private string $userName;
#[Option(shortcut: 'a', name: 'admin', description: 'Set the user as admin')]
private bool $isAdmin = false;
public function __invoke(): int
{
$user = new User(
email: $this->email,
password: $this->password,
);
$user->setIsAdmin($this->isAdmin);
// Save user to database...
return self::SUCCESS;
}
}
Spiral 现在支持创建命名序列,允许组织和重用命令序列。
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Console\Bootloader\ConsoleBootloader;
class MyPackageAssetsBootloader extends Bootloader
{
public function init(ConsoleBootloader $console): void
{
$console->addSequence('publish:assets', PublishCssFilesCommand::class);
$console->addSequence('publish:assets', PublishJsFilesCommand::class);
}
}
使用命名序列:
use Spiral\Console\Command\SequenceCommand;
use Psr\Container\ContainerInterface;
use Spiral\Console\Config\ConsoleConfig;
class PublishAssetsCommand extends SequenceCommand
{
public function perform(ConsoleConfig $config, ContainerInterface $container): int
{
$this->info("Publishing assets:");
$this->newLine();
return $this->runSequence(
$config->getSequence('publish:assets'),
$container
);
}
}
__invoke
方法命令现在可以使用 __invoke
方法作为 perform
方法的替代方案,从而简化了命令定义。
class CheckHttpCommand extends Command
{
// ...
public function __invoke(): int
{
// ...
}
}
一项新功能确保在生产环境中尝试执行敏感操作时显示确认提示。
use Spiral\Console\Confirmation\ApplicationInProduction;
final class MigrateCommand extends Command
{
protected const NAME = 'db:migrate';
protected const DESCRIPTION = '...';
public function perform(ApplicationInProduction $confirmation): int
{
if (!$confirmation->confirmToProceed()) {
return self::FAILURE;
}
// run migrations...
}
}
引入了一套辅助方法,以促进各种命令行交互:
class SomeCommand extends Command
{
// ...
public function perform(): int
{
// 确定是否存在输入选项。
$this->hasOption(...);
// 确定是否存在输入参数。
$this->hasArgument(...);
// 询问确认。
$status = $this->confirm('Are you sure?', default: false): bool;
// 提问。
$status = $this->ask('Are you sure?', default: 'no'): mixed;
// 提示用户输入,但将答案隐藏在控制台中。
$status = $this->secret('User password'): string;
// 将消息写入信息输出。
$this->info(...);
// 将消息写入注释输出。
$this->comment(...);
// 将消息写入问题输出。
$this->question(...);
// 将消息写入错误输出。
$this->error(...);
// 将消息写入警告输出。
$this->warning(...);
// 将消息写入警报输出。
$this->alert(...);
// 将消息写入标准输出。
$this->line(..., 'error');
// 写入一个空白行。
$this->newLine();
$this->newLine(count: 5);
}
}
开发人员现在可以为控制台命令注册自定义拦截器,从而增强对命令执行和生命周期的控制。
关于控制台拦截器的更多信息
现在可以在控制台命令中替换输出对象,从而允许自定义输出处理。
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
abstract class MyCommand extends \Spiral\Console\Command
{
protected function prepareOutput(InputInterface $input, OutputInterface $output): OutputInterface
{
return new \App\Console\MyOutput($input, $output);
}
}
Spiral 框架的容器系统经历了重大的重构,增强了其灵活性和功能。下面是一个详细说明这些改进的综合指南。
关于容器的更多信息
容器现在在模块化的基础上运行,允许在容器初始化之前用自定义实现替换各个模块。此更改引入了更大的灵活性,以使容器适应特定的项目需求。
// 初始化共享容器,绑定,目录等。
$app = App::create(
directories: ['root' => __DIR__],
container: new Spiral\Core\Container(
config: new Spiral\Core\Config(
resolver: App\CustomResolver::class
)
)
)->run();
已添加对 PHP 8.0 联合类型的支持,从而允许在应用程序的代码库中进行更具表现力的类型声明。
容器现在支持可变参数,从而在将参数传递给方法和函数方面提供了更大的灵活性: