#601

Globales Ranking · von 601 Skills

php-modernization AI Agent Skill

Quellcode ansehen: dirnbauer/webconsulting-skills

Safe

Installation

npx skills add dirnbauer/webconsulting-skills --skill php-modernization

65

Installationen

PHP Modernization Skill

Modernize PHP applications to PHP 8.x with type safety, PSR compliance, and static analysis.

Expertise Areas

  • PHP 8.x: Constructor promotion, readonly, enums, match, attributes, union types
  • PSR/PER Compliance: Active PHP-FIG standards
  • Static Analysis: PHPStan (level 9+), PHPat, Rector, PHP-CS-Fixer
  • Type Safety: DTOs/VOs over arrays, generics via PHPDoc

PHP 8.x Features

Constructor Property Promotion (PHP 8.0+)

// ❌ OLD
class UserService
{
    private UserRepository $userRepository;
    private LoggerInterface $logger;

    public function __construct(
        UserRepository $userRepository,
        LoggerInterface $logger
    ) {
        $this->userRepository = $userRepository;
        $this->logger = $logger;
    }
}

// ✅ NEW
final class UserService
{
    public function __construct(
        private readonly UserRepository $userRepository,
        private readonly LoggerInterface $logger,
    ) {}
}

Readonly Classes (PHP 8.2+)

// ✅ All properties are implicitly readonly
final readonly class UserDTO
{
    public function __construct(
        public int $id,
        public string $name,
        public string $email,
    ) {}
}

Enums (PHP 8.1+)

// ❌ OLD - String constants
class Status
{
    public const DRAFT = 'draft';
    public const PUBLISHED = 'published';
    public const ARCHIVED = 'archived';
}

// ✅ NEW - Backed enum
enum Status: string
{
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';

    public function label(): string
    {
        return match($this) {
            self::Draft => 'Draft',
            self::Published => 'Published',
            self::Archived => 'Archived',
        };
    }
}

// Usage
public function setStatus(Status $status): void
{
    $this->status = $status;
}

$item->setStatus(Status::Published);

Match Expression (PHP 8.0+)

// ❌ OLD - Switch
switch ($type) {
    case 'a':
        $result = 'Type A';
        break;
    case 'b':
        $result = 'Type B';
        break;
    default:
        $result = 'Unknown';
}

// ✅ NEW - Match
$result = match($type) {
    'a' => 'Type A',
    'b' => 'Type B',
    default => 'Unknown',
};

Named Arguments (PHP 8.0+)

// ✅ Clearer and order-independent
$this->doSomething(
    name: 'value',
    options: ['key' => 'value'],
    enabled: true,
);

Null Safe Operator (PHP 8.0+)

// ❌ OLD
$country = null;
if ($user !== null && $user->getAddress() !== null) {
    $country = $user->getAddress()->getCountry();
}

// ✅ NEW
$country = $user?->getAddress()?->getCountry();

Union Types (PHP 8.0+)

public function process(string|int $value): string|null
{
    // ...
}

Intersection Types (PHP 8.1+)

public function handle(Countable&Iterator $collection): void
{
    // $collection must implement both interfaces
}

Attributes (PHP 8.0+)

use TYPO3\CMS\Core\Attribute\AsEventListener;

#[AsEventListener(identifier: 'myext/my-listener')]
final class MyListener
{
    public function __invoke(SomeEvent $event): void
    {
        // Handle event
    }
}

DTOs and Value Objects

Never Use Arrays for Structured Data

// ❌ BAD - Array passing
public function createUser(array $data): array
{
    // What fields are expected? What types?
}

// ✅ GOOD - DTO pattern
public function createUser(CreateUserDTO $dto): UserDTO
{
    // Type-safe, documented, IDE-friendly
}

Data Transfer Object

<?php

declare(strict_types=1);

namespace Vendor\MyExtension\DTO;

final readonly class CreateUserDTO
{
    public function __construct(
        public string $name,
        public string $email,
        public ?string $phone = null,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            name: $data['name'] ?? throw new \InvalidArgumentException('Name required'),
            email: $data['email'] ?? throw new \InvalidArgumentException('Email required'),
            phone: $data['phone'] ?? null,
        );
    }
}

Value Object

<?php

declare(strict_types=1);

namespace Vendor\MyExtension\ValueObject;

final readonly class EmailAddress
{
    private function __construct(
        public string $value,
    ) {}

    public static function fromString(string $email): self
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException('Invalid email address');
        }

        return new self($email);
    }

    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}

PSR/PER Compliance

Active Standards

Standard Purpose Status
PSR-1 Basic Coding Required
PSR-4 Autoloading Required
PER CS Coding Style Required (supersedes PSR-12)
PSR-3 Logger Interface Use for logging
PSR-6/16 Cache Use for caching
PSR-7/17/18 HTTP Use for HTTP clients
PSR-11 Container Use for DI
PSR-14 Events Use for event dispatching
PSR-15 Middleware Use for HTTP middleware
PSR-20 Clock Use for time-dependent code

PER Coding Style

<?php

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\SomeClass;

final class MyClass
{
    public function __construct(
        private readonly SomeClass $dependency,
    ) {}

    public function doSomething(
        string $param1,
        int $param2,
    ): string {
        return match ($param2) {
            1 => $param1,
            2 => $param1 . $param1,
            default => '',
        };
    }
}

Static Analysis Tools

PHPStan (Level 9+)

# phpstan.neon
includes:
    - vendor/phpstan/phpstan-strict-rules/rules.neon
    - vendor/saschaegerer/phpstan-typo3/extension.neon

parameters:
    level: 10
    paths:
        - Classes
        - Tests
    excludePaths:
        - Classes/Domain/Model/*

Level Guide:

  • Level 0-5: Basic checks
  • Level 6-8: Type checking
  • Level 9: Strict mixed handling
  • Level 10: Maximum strictness (recommended)

PHP-CS-Fixer

<?php
// .php-cs-fixer.dist.php
$config = new PhpCsFixer\Config();

return $config
    ->setRules([
        '@PER-CS' => true,
        '@PER-CS:risky' => true,
        'declare_strict_types' => true,
        'no_unused_imports' => true,
        'ordered_imports' => ['sort_algorithm' => 'alpha'],
        'single_line_empty_body' => true,
        'trailing_comma_in_multiline' => [
            'elements' => ['arguments', 'arrays', 'match', 'parameters'],
        ],
    ])
    ->setRiskyAllowed(true)
    ->setFinder(
        PhpCsFixer\Finder::create()
            ->in(__DIR__ . '/Classes')
            ->in(__DIR__ . '/Tests')
    );

Rector

<?php
// rector.php
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return RectorConfig::configure()
    ->withPaths([
        __DIR__ . '/Classes',
        __DIR__ . '/Tests',
    ])
    ->withSets([
        LevelSetList::UP_TO_PHP_83,
        SetList::CODE_QUALITY,
        SetList::TYPE_DECLARATION,
        SetList::DEAD_CODE,
    ]);

PHPat (Architecture Testing)

<?php

declare(strict_types=1);

namespace Vendor\MyExtension\Tests\Architecture;

use PHPat\Selector\Selector;
use PHPat\Test\Builder\Rule;
use PHPat\Test\PHPat;

final class ArchitectureTest
{
    public function testDomainDoesNotDependOnInfrastructure(): Rule
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('Vendor\MyExtension\Domain'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('Vendor\MyExtension\Infrastructure'));
    }
}

Type Safety Patterns

Typed Arrays with PHPDoc Generics

/**
 * @return array<int, User>
 */
public function getUsers(): array
{
    return $this->users;
}

/**
 * @param array<string, mixed> $config
 */
public function configure(array $config): void
{
    // ...
}

/**
 * @return \Generator<int, Item, mixed, void>
 */
public function iterateItems(): \Generator
{
    foreach ($this->items as $item) {
        yield $item;
    }
}

Strict Comparison

// ❌ Loose comparison
if ($value == '1') {}

// ✅ Strict comparison
if ($value === '1') {}
if ($value === 1) {}

Early Returns

// ❌ Nested conditions
public function process(?User $user): ?Result
{
    if ($user !== null) {
        if ($user->isActive()) {
            return $this->doProcess($user);
        }
    }
    return null;
}

// ✅ Early returns
public function process(?User $user): ?Result
{
    if ($user === null) {
        return null;
    }

    if (!$user->isActive()) {
        return null;
    }

    return $this->doProcess($user);
}

Appendix

For the migration checklist, tooling links, and attribution details, see references/additional-resources.md.

Credits & Attribution

This skill is based on the excellent work by
Netresearch DTT GmbH.

Original repository: https://github.com/netresearch/php-modernization-skill

Copyright (c) Netresearch DTT GmbH — Methodology and best practices (MIT / CC-BY-SA-4.0)
Adapted by webconsulting.at for this skill collection

Installationen

Installationen 65
Globales Ranking #601 von 601

Sicherheitsprüfung

ath Safe
socket Safe
Warnungen: 0 Bewertung: 90
snyk Low
EU EU-Hosted Inference API

Power your AI Agents with the best open-source models.

Drop-in OpenAI-compatible API. No data leaves Europe.

Explore Inference API

GLM

GLM 5

$1.00 / $3.20

per M tokens

Kimi

Kimi K2.5

$0.60 / $2.80

per M tokens

MiniMax

MiniMax M2.5

$0.30 / $1.20

per M tokens

Qwen

Qwen3.5 122B

$0.40 / $3.00

per M tokens

So verwenden Sie diesen Skill

1

Install php-modernization by running npx skills add dirnbauer/webconsulting-skills --skill php-modernization in your project directory. Führen Sie den obigen Installationsbefehl in Ihrem Projektverzeichnis aus. Die Skill-Datei wird von GitHub heruntergeladen und in Ihrem Projekt platziert.

2

Keine Konfiguration erforderlich. Ihr KI-Agent (Claude Code, Cursor, Windsurf usw.) erkennt installierte Skills automatisch und nutzt sie als Kontext bei der Code-Generierung.

3

Der Skill verbessert das Verständnis Ihres Agenten für php-modernization, und hilft ihm, etablierte Muster zu befolgen, häufige Fehler zu vermeiden und produktionsreifen Code zu erzeugen.

Was Sie erhalten

Skills sind Klartext-Anweisungsdateien — kein ausführbarer Code. Sie kodieren Expertenwissen über Frameworks, Sprachen oder Tools, das Ihr KI-Agent liest, um seine Ausgabe zu verbessern. Das bedeutet null Laufzeit-Overhead, keine Abhängigkeitskonflikte und volle Transparenz: Sie können jede Anweisung vor der Installation lesen und prüfen.

Kompatibilität

Dieser Skill funktioniert mit jedem KI-Coding-Agenten, der das skills.sh-Format unterstützt, einschließlich Claude Code (Anthropic), Cursor, Windsurf, Cline, Aider und anderen Tools, die projektbezogene Kontextdateien lesen. Skills sind auf Transportebene framework-agnostisch — der Inhalt bestimmt, für welche Sprache oder welches Framework er gilt.

Data sourced from the skills.sh registry and GitHub. Install counts and security audits are updated regularly.

EU Made in Europe

Chat with 100+ AI Models in one App.

Use Claude, ChatGPT, Gemini alongside with EU-Hosted Models like Deepseek, GLM-5, Kimi K2.5 and many more.

Kundensupport