All skills
asyrafhussin avatar

/php-best-practices

@e7ea05d

PHP 8.x modern patterns, PSR standards, and SOLID principles. Use when reviewing PHP code, checking type safety, auditing code quality, or ensuring PHP best practices. Triggers on "review PHP", "check PHP code", "audit PHP", or "PHP best practices".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/php-best-practices

This session only. Nothing lands on disk.

rulessolid-ocp.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Open/Closed Principle (OCP)

Classes should be open for extension but closed for modification.

Bad Example

<?php

declare(strict_types=1);

// Must modify this class every time a new payment method is added
class PaymentProcessor
{
    public function process(string $type, float $amount): PaymentResult
    {
        // Adding new payment type requires modifying this method
        if ($type === 'credit_card') {
            // Credit card processing logic
            $fee = $amount * 0.029;
            return new PaymentResult($amount + $fee, 'credit_card');
        }

        if ($type === 'paypal') {
            // PayPal processing logic
            $fee = $amount * 0.035;
            return new PaymentResult($amount + $fee, 'paypal');
        }

        if ($type === 'bank_transfer') {
            // Bank transfer logic
            $fee = 1.00;
            return new PaymentResult($amount + $fee, 'bank_transfer');
        }

        // Adding crypto? Must modify this class again!
        if ($type === 'crypto') {
            $fee = $amount * 0.01;
            return new PaymentResult($amount + $fee, 'crypto');
        }

        throw new InvalidArgumentException("Unknown payment type: {$type}");
    }
}

// Same problem with discount calculation
class DiscountCalculator
{
    public function calculate(string $type, float $amount): float
    {
        return match ($type) {
            'percentage' => $amount * 0.10,
            'fixed' => 5.00,
            'buy_one_get_one' => $amount / 2,
            // Adding new discount type = modifying this class
            default => 0.0,
        };
    }
}

Good Example

<?php

declare(strict_types=1);

// Define contract for payment methods
interface PaymentMethod
{
    public function process(Money $amount): PaymentResult;
    public function calculateFee(Money $amount): Money;
    public function getName(): string;
}

// Each payment method is a separate class - closed for modification
class CreditCardPayment implements PaymentMethod
{
    private const FEE_PERCENTAGE = 0.029;

    public function __construct(
        private PaymentGateway $gateway,
    ) {}

    public function process(Money $amount): PaymentResult
    {
        $totalAmount = $amount->add($this->calculateFee($amount));
        return $this->gateway->charge($totalAmount);
    }

    public function calculateFee(Money $amount): Money
    {
        return $amount->multiply(self::FEE_PERCENTAGE);
    }

    public function getName(): string
    {
        return 'credit_card';
    }
}

class PayPalPayment implements PaymentMethod
{
    private const FEE_PERCENTAGE = 0.035;

    public function __construct(
        private PayPalClient $client,
    ) {}

    public function process(Money $amount): PaymentResult
    {
        $totalAmount = $amount->add($this->calculateFee($amount));
        return $this->client->createPayment($totalAmount);
    }

    public function calculateFee(Money $amount): Money
    {
        return $amount->multiply(self::FEE_PERCENTAGE);
    }

    public function getName(): string
    {
        return 'paypal';
    }
}

// New payment method - extend without modifying existing code
class CryptoPayment implements PaymentMethod
{
    private const FEE_PERCENTAGE = 0.01;

    public function __construct(
        private CryptoGateway $gateway,
    ) {}

    public function process(Money $amount): PaymentResult
    {
        $totalAmount = $amount->add($this->calculateFee($amount));
        return $this->gateway->processPayment($totalAmount);
    }

    public function calculateFee(Money $amount): Money
    {
        return $amount->multiply(self::FEE_PERCENTAGE);
    }

    public function getName(): string
    {
        return 'crypto';
    }
}

// Payment processor is closed for modification
class PaymentProcessor
{
    /** @var array<string, PaymentMethod> */
    private array $methods = [];

    public function registerMethod(PaymentMethod $method): void
    {
        $this->methods[$method->getName()] = $method;
    }

    public function process(string $methodName, Money $amount): PaymentResult
    {
        if (!isset($this->methods[$methodName])) {
            throw new UnsupportedPaymentMethodException($methodName);
        }

        return $this->methods[$methodName]->process($amount);
    }
}

// Usage with dependency injection
class PaymentServiceProvider
{
    public function register(Container $container): void
    {
        $container->singleton(PaymentProcessor::class, function ($c) {
            $processor = new PaymentProcessor();
            $processor->registerMethod($c->make(CreditCardPayment::class));
            $processor->registerMethod($c->make(PayPalPayment::class));
            $processor->registerMethod($c->make(CryptoPayment::class));
            return $processor;
        });
    }
}

Strategy Pattern Example

<?php

declare(strict_types=1);

// Discount strategy interface
interface DiscountStrategy
{
    public function calculate(Money $amount): Money;
    public function getDescription(): string;
}

class PercentageDiscount implements DiscountStrategy
{
    public function __construct(
        private float $percentage,
    ) {}

    public function calculate(Money $amount): Money
    {
        return $amount->multiply($this->percentage);
    }

    public function getDescription(): string
    {
        return sprintf('%d%% off', $this->percentage * 100);
    }
}

class FixedAmountDiscount implements DiscountStrategy
{
    public function __construct(
        private Money $discountAmount,
    ) {}

    public function calculate(Money $amount): Money
    {
        return $this->discountAmount->min($amount);
    }

    public function getDescription(): string
    {
        return sprintf('%s off', $this->discountAmount->format());
    }
}

class BuyOneGetOneFreeDiscount implements DiscountStrategy
{
    public function calculate(Money $amount): Money
    {
        return $amount->divide(2);
    }

    public function getDescription(): string
    {
        return 'Buy one get one free';
    }
}

// Closed for modification, open for new discount strategies
class DiscountCalculator
{
    public function apply(Money $amount, DiscountStrategy $strategy): Money
    {
        $discount = $strategy->calculate($amount);
        return $amount->subtract($discount);
    }
}

Why

  • No Regression Risk: Existing code isn't modified when adding features
  • Easy Extension: New functionality via new classes, not changes
  • Better Testing: Existing tests remain valid
  • Plugin Architecture: Easy to add new behaviors at runtime
  • Team Parallelism: Different team members add features independently
  • Framework Integration: Works well with DI containers

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill is a comprehensive and safe resource for PHP 8.x best practices. It provides structured guidance on type safety, modern PHP syntax, PSR standards, and secure coding practices (such as prepared statements and password hashing). The agent is instructed to use standard environment detection commands (php -v, grep) to tailor its advice. No malicious patterns or security risks were identified.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    39 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at e7ea05d. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
Other metadata
metadata
{
  "author": "php-community",
  "version": "2.1.0",
  "phpVersion": "8.0 - 8.5"
}

README badge

README badge for asyrafhussin/agent-skills/php-best-practices