承接 rector/swiss-knife 相关项目开发

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

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

rector/swiss-knife

Composer 安装命令:

composer require rector/swiss-knife

包简介

Swiss knife in pocket of every upgrade architect

README 文档

README

Downloads total

Swiss knife in pocket of every upgrade architect!


Install

composer require rector/swiss-knife --dev


Usage


1. Check your Code for Git Merge Conflicts

Do you use Git? Then merge conflicts is not what you want in your code ever to see in pushed code:

<<<<<<< HEAD

Add this command to CI to spot these:

vendor/bin/swiss-knife check-conflicts .

You can skip paths with the --exclude option:

vendor/bin/swiss-knife check-conflicts . --exclude vendor --exclude tests/fixtures

2. Detect Commented Code

Have you ever forgot commented code in your code?

//      foreach ($matches as $match) {
//           $content = str_replace($match[0], $match[2], $content);
//      }

No more! Add this command to CI to spot these:

vendor/bin/swiss-knife check-commented-code <directory>
vendor/bin/swiss-knife check-commented-code packages --line-limit 5 --skip-file '*Controller.php'

3. Reach full PSR-4

Find multiple classes in single file

To make PSR-4 work properly, each class must be in its own file. This command makes it easy to spot multiple classes in single file:

vendor/bin/swiss-knife find-multi-classes src

Update Namespace to match PSR-4 Root

Is your class in wrong namespace? Make it match your PSR-4 root:

vendor/bin/swiss-knife namespace-to-psr-4 src --namespace-root "App\\"

This will update all files in your /src directory, to starts with App\\ and follow full PSR-4 path:

 # file path: src/Repository/TalkRepository.php

-namespace Model;
+namespace App\Repository;

 ...

4. Finalize classes without children

Do you want to finalize all classes that don't have children?

vendor/bin/swiss-knife finalize-classes src tests

Do you use mocks but not bypass final yet?

vendor/bin/swiss-knife finalize-classes src tests --skip-mocked

This will keep mocked classes non-final, so PHPUnit can extend them internally.


Do you want to skip file or two?

vendor/bin/swiss-knife finalize-classes src tests --skip-file src/SpecialProxy.php

Skip is also support with fnmatch() patterns:

vendor/bin/swiss-knife finalize-classes src tests --skip-file '*Controller.php'

5. Privatize local class constants

PHPStan can report unused private class constants, but it skips all the public ones. Do you have lots of class constants, all of them public but want to narrow scope to privates?

vendor/bin/swiss-knife privatize-constants src test

This command will:

  • find all class constant usages
  • scans classes and constants
  • makes those constant used locally private

That way all the constants not used outside will be made private safely.


6. Mock only constructor param you need with MockWire

Imagine there is a service that has 6 dependencies in __construct():

final class RealClass
{
    public function __construct(
        private readonly FirstService $firstService,
        private readonly SecondService $secondService,
        private readonly ThirdService $thirdService,
        private readonly FourthService $fourthService,
        private readonly FifthService $fifthService,
        private readonly SixthService $sixthService
    ) {
    }
}

But we want to mock only one of them:

use Rector\SwissKnife\Testing\MockWire;

// pass a mock
$thirdDependencyMock = $this->createMock(ThirdDependency::class);
$thirdDependencyMock->method('someMethod')->willReturn('some value');

$realClass = MockWire::create(RealClass::class, [
    $thirdDependencyMock
]);

Or pass direct instance:

$realClass = MockWire::create(RealClass::class, [
    new ThirdDependency()
]);

The rest of argument will be mocked automatically.

This way we:

  • can easily change the class constructor, without having burden of changing all the tests.
  • see what is really being used in the constructor
  • avoid any mock-mess clutter properties all over our test

7. Quick search PHP files with regex

Data beats guess. Do you need a quick idea how many files contain $this->get('...') calls? Or another anti-pattern you want to remove?

PhpStorm helps with similar search, but stops counting at 100+. To get exact data about your codebase, use this command:

vendor/bin/swiss-knife search-regex "#this->get\((.*)\)#"

Going through 1053 *.php files
Searching for regex: #this->get\((.*)\)#

 1053/1053 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 * src/Controller/ProjectController.php: 15
 * src/Controller/OrderController.php: 5


 [OK] Found 20 cases in 2 files

8. Convert Alice fixtures from YAML to PHP

The nelmio/alice package allows to use PHP for test fixture definitions. It's much better format, because Rector and PHPStan can understand it.

But what if we have 100+ YAML files in our project?

vendor/bin/swiss-knife convert-alice-yaml-to-php fixtures

That's it!


9. Spots Fake Traits

What is trait has 5 lines and used in single service? We know it's better to be inlined, to empower IDE, Rector and PHPStan. But don't have time to worry about these details.

We made a command to automate this process and spot the traits most likely to be inlined:

vendor/bin/swiss-knife spot-lazy-traits src

By default, the commands look for traits used max 2-times. To change that:

vendor/bin/swiss-knife spot-lazy-traits src --max-used 4

That's it! Run this command once upon a time or run it in CI to eliminate traits with low value to exists. Your code will be more robust and easier to work with.


10. Split huge Symfony config to per-package in directory

Do you have a huge Symfony config file that is hard to navigate? Do you want to split it to per-package files?

Before - one huge config/config_dev.php with many extensions in a single file:

<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $containerConfigurator->extension('framework', [
        'secret' => '%env(APP_SECRET)%',
        'test' => true,
    ]);

    $containerConfigurator->extension('doctrine', [
        'dbal' => [
            'url' => '%env(DATABASE_URL)%',
        ],
    ]);

    $containerConfigurator->extension('monolog', [
        'handlers' => [
            'main' => [
                'type' => 'stream',
                'path' => '%kernel.logs_dir%/%kernel.environment%.log',
            ],
        ],
    ]);
};

Run the command:

vendor/bin/swiss-knife split-config-per-package config/config_dev.php --output-dir config/packages/dev

After - the original config only imports the per-package files:

<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $containerConfigurator->import(__DIR__ . '/packages/dev/*');
};

And each extension lives in its own file, e.g. config/packages/dev/doctrine.php:

<?php

declare(strict_types=1);

return static function (Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator): void {
    $containerConfigurator->extension('doctrine', [
        'dbal' => [
            'url' => '%env(DATABASE_URL)%',
        ],
    ]);
};

All the extensions will be extracted to separate files in config/packages/dev directory, making them much more readable.


11. Generate Symfony Smoke Tests

Cover your Symfony app with smoke tests in seconds. This command scans your composer.json, picks the matching test templates, and drops them under tests/Unit/Smoke (or your project's equivalent unit-tests directory).

vendor/bin/swiss-knife generate-symfony-smoke-tests

The command will:

  • detect your unit tests directory and create a Smoke sub-directory
  • generate a ServiceContainerTest that boots the kernel and instantiates every service to catch container misconfiguration early
  • add a shared AbstractContainerTestCase with a typed getService() helper
  • adjust the namespace and Kernel class in the templates to match your project (uses App\Kernel, AppKernel, or Kernel, whichever exists)

Existing files are never overwritten, so the command is safe to re-run.

The generated ServiceContainerTest boots the kernel and asserts every service can be instantiated:

<?php

declare(strict_types=1);

namespace App\Tests\Unit\Smoke;

use Throwable;

final class ServiceContainerTest extends AbstractContainerTestCase
{
    public function testServiceConstruction(): void
    {
        $serviceIds = self::$container->getServiceIds();

        $checkedServiceCount = 0;

        foreach ($serviceIds as $serviceId) {
            if ($this->isDynamicService($serviceId)) {
                continue;
            }

            try {
                self::$container->get($serviceId);
            } catch (Throwable $throwable) {
                $this->fail(sprintf('Service "%s" could not be created because:%s%s', $serviceId, PHP_EOL, $throwable->getMessage()));
            }

            ++$checkedServiceCount;
        }

        // @todo update this number to match your service count
        $this->assertSame(100000, $checkedServiceCount);
    }

    private function isDynamicService(string $serviceId): bool
    {
        if (str_contains($serviceId, 'session')) {
            return true;
        }

        if (str_starts_with($serviceId, 'doctrine.')) {
            return true;
        }

        return in_array(
            $serviceId,
            ['kernel', 'database_connection', 'event_dispatcher'],
            true
        );
    }
}

That's it!


Happy coding!

rector/swiss-knife 适用场景与选型建议

rector/swiss-knife 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.21M 次下载、GitHub Stars 达 208, 最近一次更新时间为 2024 年 02 月 08 日, 在 PHP 生态内属于活跃度较高的组件。

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

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

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

  • 总下载量: 2.21M
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 209
  • 点击次数: 29
  • 依赖项目数: 58
  • 推荐数: 1

GitHub 信息

  • Stars: 208
  • Watchers: 4
  • Forks: 16
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-02-08