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.

rulestype-strict-mode.md

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

Strict Types Declaration

declare(strict_types=1) enforces strict type checking for function arguments and return values. Without it, PHP silently coerces types, hiding bugs. Strict mode catches type errors early, improving code reliability.

Bad Example

<?php

// No strict types - silent coercion
function calculateTotal(int $price, int $quantity): int
{
    return $price * $quantity;
}

// These hide problems:
calculateTotal("10", "5");   // Returns 50 - numeric strings coerced to int
calculateTotal(10.99, 2);    // Returns 20 - float truncated to int (deprecated in 8.1)
// calculateTotal("abc", 2); // TypeError in PHP 8.0+ (non-numeric string)

// Missing from file
namespace App\Services;

class Calculator
{
    // ...
}

Good Example

<?php

declare(strict_types=1);

// Strict types - TypeError on wrong types
function calculateTotal(int $price, int $quantity): int
{
    return $price * $quantity;
}

calculateTotal(10, 5);       // Returns 50
calculateTotal("10", "5");   // TypeError
calculateTotal(10.99, 2);    // TypeError

Declaration Rules

<?php

// MUST be the first statement in the file
declare(strict_types=1);

namespace App\Services;

use App\Models\User;

class UserService
{
    // ...
}
<?php

namespace App\Services; // Wrong - declare must come first

declare(strict_types=1);

class UserService
{
    // ...
}

Scope

<?php

declare(strict_types=1);

// Strict mode applies to function CALLS in this file
function addNumbers(int $a, int $b): int
{
    return $a + $b;
}

// This call is in strict mode
addNumbers(1, 2);     //
addNumbers("1", "2"); // TypeError

// Strict mode also applies to internal PHP function calls
strlen("hello");      // Works
// strlen(12345);     // TypeError - int given, string expected

File-by-File Basis

<?php
// file: src/Strict.php
declare(strict_types=1);

function strictFunction(int $n): int
{
    return $n * 2;
}
<?php
// file: src/NonStrict.php
// No declare - weak mode

require_once 'Strict.php';

// Calls from weak mode file still coerce
strictFunction("5"); // Returns 10 - coercion happens at call site

Return Type Enforcement

<?php

declare(strict_types=1);

// Return type strictly enforced
function getPrice(): float
{
    return 99.99; // Must return float
}

function getCount(): int
{
    return 42; // Must return int
}

// This would cause TypeError
function broken(): int
{
    return "42"; // TypeError - can't return string as int
}

With Nullable Types

<?php

declare(strict_types=1);

function findUser(int $id): ?User
{
    // Must return User or null, nothing else
    return User::find($id);
}

function process(?string $data): void
{
    // $data must be string or null
}

process("hello"); //
process(null);    //
process(123);     // TypeError

With Union Types

<?php

declare(strict_types=1);

function format(string|int $value): string
{
    return (string) $value;
}

format("hello"); //
format(42);      //
format(3.14);    // TypeError - float not in union

Best Practice Template

<?php

declare(strict_types=1);

namespace App\Services;

use App\Contracts\RepositoryInterface;
use App\Models\User;
use App\Exceptions\UserNotFoundException;

final class UserService
{
    public function __construct(
        private readonly RepositoryInterface $repository,
    ) {}

    public function findById(int $id): User
    {
        $user = $this->repository->find($id);

        if ($user === null) {
            throw new UserNotFoundException($id);
        }

        return $user;
    }

    public function create(array $data): User
    {
        return $this->repository->create($data);
    }

    /**
     * @param array<int> $ids
     * @return array<User>
     */
    public function findMany(array $ids): array
    {
        return $this->repository->findMany($ids);
    }
}

IDE/Static Analysis

<?php

declare(strict_types=1);

// PHPStan/Psalm will catch type errors even more strictly
// Combined with strict_types, you get maximum type safety

/** @var positive-int $count */
$count = getCount();

/** @var non-empty-string $name */
$name = getName();

Why

  • Type Safety: Catches type bugs at runtime immediately
  • No Surprises: No silent type coercion
  • Static Analysis: Works with PHPStan/Psalm for maximum safety
  • Self-Documenting: Code intent is explicit and enforced
  • Industry Standard: Required for reliable modern PHP

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