承接 phpstan/phpstan-symfony 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

phpstan/phpstan-symfony

Composer 安装命令:

composer require --dev phpstan/phpstan-symfony

包简介

Symfony Framework extensions and rules for PHPStan

关键字:

README 文档

README

Build Latest Stable Version License

This extension provides following features:

  • Provides correct return type for ContainerInterface::get() and ::has() methods.
  • Provides correct return type for Controller::get() and ::has() methods.
  • Provides correct return type for AbstractController::get() and ::has() methods.
  • Provides correct return type for ContainerInterface::getParameter() and ::hasParameter() methods.
  • Provides correct return type for ParameterBagInterface::get() and ::has() methods.
  • Provides correct return type for Controller::getParameter() method.
  • Provides correct return type for AbstractController::getParameter() method.
  • Provides correct return type for Request::getContent() method based on the $asResource parameter.
  • Provides correct return type for HeaderBag::get() method based on the $first parameter.
  • Provides correct return type for Envelope::all() method based on the $stampFqcn parameter.
  • Provides correct return type for InputBag::get() method based on the $default parameter.
  • Provides correct return type for InputBag::all() method based on the $key parameter.
  • Provides correct return type for ResponseHeaderBag::getCookies() method based on the format argument.
  • Provides correct return types for TreeBuilder and NodeDefinition objects.
  • Provides correct return type for SerializerInterface::deserialize() and DenormalizerInterface::denormalize() methods based on the $type argument.
  • Provides correct return type for HandleTrait::handle() method based on the message handler map.
  • Provides correct return type for FormInterface::getErrors() method based on the $deep and $flatten parameters.
  • Provides correct return type for KernelInterface::locateResource() method.
  • Provides correct return type for Extension::getConfiguration() method.
  • Provides correct return type for CacheInterface::get() method based on the callback return type.
  • Provides correct return type for BrowserKitAssertionsTrait::getClient() method.
  • Provides configurable return type resolution for methods that internally use Messenger HandleTrait.
  • Notifies you when you try to get an unregistered service from the container.
  • Notifies you when you try to get a private service from the container.
  • Notifies you when you access undefined console command arguments or options.
  • Validates default values of console command arguments and options.
  • Recognizes @required annotation and #[Required] attribute for autowiring properties and methods.
  • Optionally correct return types for InputInterface::getArgument(), ::getOption(), ::getOptions(), ::hasArgument(), and ::hasOption().
  • Optionally provides correct return type for Command::getHelper() method.

Installation

To use this extension, require it in Composer:

composer require --dev phpstan/phpstan-symfony

If you also install phpstan/extension-installer then you're all set!

Manual installation

If you don't want to use phpstan/extension-installer, include extension.neon in your project's PHPStan config:

includes:
    - vendor/phpstan/phpstan-symfony/extension.neon

To perform framework-specific checks, include also this file:

includes:
    - vendor/phpstan/phpstan-symfony/rules.neon

Configuration

You have to provide a path to srcDevDebugProjectContainer.xml or similar XML file describing your container.

parameters:
    symfony:
        containerXmlPath: var/cache/dev/srcDevDebugProjectContainer.xml
        # or with Symfony 4.2+
        containerXmlPath: var/cache/dev/srcApp_KernelDevDebugContainer.xml
        # or with Symfony 5+
        containerXmlPath: var/cache/dev/App_KernelDevDebugContainer.xml
    # If you're using PHP config files for Symfony 5.3+, you also need this for auto-loading of `Symfony\Config`:
    scanDirectories:
        - var/cache/dev/Symfony/Config
    # If you're using PHP config files (including the ones under packages/*.php) for Symfony 5.3+,
    # you need this to load the helper functions (i.e. service(), env()):
    scanFiles:
        - vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php

Constant hassers

Sometimes, when you are dealing with optional dependencies, the ::has() methods can cause problems. For example, the following construct would complain that the condition is always either on or off, depending on whether you have the dependency for service installed:

if ($this->has('service')) {
    // ...
}

In that case, you can disable the ::has() method return type resolving like this:

parameters:
	symfony:
		constantHassers: false

Be aware that it may hide genuine errors in your application.

Analysis of Symfony Console Commands

You can opt in for more advanced analysis of Symfony Console Commands by providing the console application from your own application. This will allow the correct argument and option types to be inferred when accessing $input->getArgument() or $input->getOption().

parameters:
	symfony:
		consoleApplicationLoader: tests/console-application.php

Symfony 4:

// tests/console-application.php

use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;

require __DIR__ . '/../config/bootstrap.php';
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
return new Application($kernel);

Symfony 5:

// tests/console-application.php

use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Dotenv\Dotenv;

require __DIR__ . '/../vendor/autoload.php';

(new Dotenv())->bootEnv(__DIR__ . '/../.env');

$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
return new Application($kernel);

Single Command Application:

// tests/console-application.php

use App\Application; // where Application extends Symfony\Component\Console\SingleCommandApplication
use Symfony\Component\Console;

require __DIR__ . '/../vendor/autoload.php';

$application = new Console\Application();
$application->add(new Application());

return $application;

You may then encounter an error with PhpParser:

Compile Error: Cannot Declare interface PhpParser\NodeVisitor, because the name is already in use

If this is the case, you should create a new environment for your application that will disable inlining. In config/packages/phpstan_env/parameters.yaml:

parameters:
    container.dumper.inline_class_loader: false

Call the new env in your console-application.php:

$kernel = new \App\Kernel('phpstan_env', (bool) $_SERVER['APP_DEBUG']);

Messenger HandleTrait Wrappers

The extension provides advanced type inference for methods that internally use Symfony Messenger's HandleTrait. This feature is particularly useful for query bus implementations (in CQRS pattern) that use/wrap the HandleTrait::handle() method.

Configuration

parameters:
    symfony:
        messenger:
            handleTraitWrappers:
                - App\Bus\QueryBus::dispatch
                - App\Bus\QueryBus::execute
                - App\Bus\QueryBusInterface::dispatch

Message Handlers

use Symfony\Component\Messenger\Attribute\AsMessageHandler;

// Product handler that returns Product
#[AsMessageHandler]
class GetProductQueryHandler
{
    public function __invoke(GetProductQuery $query): Product
    {
        return $this->productRepository->get($query->productId);
    }
}

PHP Examples

use Symfony\Component\Messenger\HandleTrait;
use Symfony\Component\Messenger\MessageBusInterface;

// Basic query bus implementation
class QueryBus
{
    use HandleTrait;

    public function __construct(MessageBusInterface $messageBus)
    {
        $this->messageBus = $messageBus;
    }

    public function dispatch(object $query): mixed
    {
        return $this->handle($query); // Return type will be inferred in calling code as query result
    }

    // Multiple methods per class example
    public function execute(object $message): mixed
    {
        return $this->handle($message); // Return type will be inferred in calling code as query result
    }
}

// Interface-based configuration example
interface QueryBusInterface
{
    public function dispatch(object $query): mixed; // Return type will be inferred in calling code as query result
}

class QueryBusWithInterface implements QueryBusInterface
{
    use HandleTrait;

    public function __construct(MessageBusInterface $queryBus)
    {
        $this->messageBus = $queryBus;
    }

    public function dispatch(object $query): mixed
    {
        return $this->handle($query);
    }
}

// Examples of use with proper type inference
$query = new GetProductQuery($productId);
$queryBus = new QueryBus($messageBus);
$queryBusWithInterface = new QueryBusWithInterface($messageBus);

$product = $queryBus->dispatch($query); // Returns: Product
$product2 = $queryBus->execute($query); // Returns: Product
$product3 = $queryBusWithInterface->dispatch($query); // Returns: Product
// Without the feature all above query bus results would be default 'mixed'.

phpstan/phpstan-symfony 适用场景与选型建议

phpstan/phpstan-symfony 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 74.47M 次下载、GitHub Stars 达 791, 最近一次更新时间为 2018 年 05 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「static analysis」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 phpstan/phpstan-symfony 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 phpstan/phpstan-symfony 我们能提供哪些服务?
定制开发 / 二次开发

基于 phpstan/phpstan-symfony 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 74.47M
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 794
  • 点击次数: 28
  • 依赖项目数: 1530
  • 推荐数: 5

GitHub 信息

  • Stars: 791
  • Watchers: 9
  • Forks: 102
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-05-19