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.

rulesmodern-constructor-promotion.md

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

Constructor Property Promotion

Constructor property promotion (PHP 8.0+) reduces boilerplate code significantly. It combines parameter declaration, property declaration, and assignment into a single statement, making classes cleaner and easier to maintain.

Bad Example

<?php

// Verbose - property declared twice, assigned manually
class User
{
    private string $id;
    private string $name;
    private string $email;
    private bool $active;
    private ?DateTimeImmutable $createdAt;

    public function __construct(
        string $id,
        string $name,
        string $email,
        bool $active = true,
        ?DateTimeImmutable $createdAt = null
    ) {
        $this->id = $id;
        $this->name = $name;
        $this->email = $email;
        $this->active = $active;
        $this->createdAt = $createdAt ?? new DateTimeImmutable();
    }
}

// Mixed styles - inconsistent
class Product
{
    private string $sku;

    public function __construct(
        private string $name,
        string $sku,
        private float $price,
    ) {
        $this->sku = $sku;
    }
}

Good Example

<?php

declare(strict_types=1);

// Constructor property promotion - clean and concise
class User
{
    public function __construct(
        private string $id,
        private string $name,
        private string $email,
        private bool $active = true,
        private ?DateTimeImmutable $createdAt = null,
    ) {
        $this->createdAt ??= new DateTimeImmutable();
    }
}

// With readonly for immutable properties (8.1+)
class ImmutableUser
{
    public function __construct(
        public readonly string $id,
        public readonly string $name,
        public readonly string $email,
        private bool $active = true,
    ) {}

    public function activate(): void
    {
        $this->active = true;
    }

    public function isActive(): bool
    {
        return $this->active;
    }
}

With Validation

<?php

class Email
{
    public function __construct(
        public readonly string $value,
    ) {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                sprintf('Invalid email address: %s', $value)
            );
        }
    }
}

class Money
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency = 'USD',
    ) {
        if ($amount < 0) {
            throw new InvalidArgumentException('Amount cannot be negative');
        }
        if (strlen($currency) !== 3) {
            throw new InvalidArgumentException('Currency must be 3 characters');
        }
    }
}

Mixed Promoted and Non-Promoted

<?php

// When you need computed properties
class Order
{
    private string $orderNumber;

    public function __construct(
        public readonly string $id,
        public readonly array $items,
        public readonly DateTimeImmutable $createdAt,
    ) {
        // Computed property - can't be promoted
        $this->orderNumber = sprintf(
            'ORD-%s-%s',
            $createdAt->format('Ymd'),
            strtoupper(substr($id, 0, 8))
        );
    }

    public function getOrderNumber(): string
    {
        return $this->orderNumber;
    }
}

Visibility Combinations

<?php

class Entity
{
    public function __construct(
        public readonly string $id,           // Public, immutable
        protected string $name,               // Protected, mutable
        private string $internalState,        // Private, mutable
        private readonly array $metadata,     // Private, immutable
    ) {}
}

Why

  • Less Boilerplate: Reduces code by ~60% for simple DTOs
  • Single Source of Truth: No separate property declaration and assignment
  • Readability: Easier to scan and maintain
  • Trailing Comma: Clean diffs when adding/removing parameters
  • Combines with Readonly: public readonly string $id for immutable promoted properties (8.1+)

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