AgentStack
SKILL verified MIT Self-run

Php

skill-miles990-claude-software-skills-php · by miles990

Modern PHP programming patterns

No reviews yet
0 installs
18 views
0.0% view→install

Install

$ agentstack add skill-miles990-claude-software-skills-php

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Php? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

PHP

Overview

Modern PHP (7.4+/8.x) patterns including typed properties, attributes, and modern OOP features.


Modern PHP Features

Type System

id = uniqid();
        $this->createdAt = new DateTimeImmutable();
    }
}

// Union types (PHP 8.0+)
function process(string|int $value): string|int
{
    return is_string($value) ? strtoupper($value) : $value * 2;
}

// Intersection types (PHP 8.1+)
function processIterable(Countable&Iterator $items): int
{
    return count($items);
}

// Return types
function findUser(string $id): ?User
{
    return $this->repository->find($id);
}

function getUsers(): array
{
    return $this->repository->findAll();
}

// Never return type (PHP 8.1+)
function fail(string $message): never
{
    throw new RuntimeException($message);
}

// Nullable types
function setName(?string $name): void
{
    $this->name = $name;
}

Attributes (PHP 8.0+)

userService->getAll();
    }

    #[Route(path: '/users/{id}', method: 'GET')]
    public function show(string $id): User
    {
        return $this->userService->find($id);
    }
}

// Reading attributes
$reflection = new ReflectionClass(User::class);
$attributes = $reflection->getAttributes(Entity::class);

foreach ($attributes as $attribute) {
    $instance = $attribute->newInstance();
    echo $instance->table; // 'users'
}

Enums (PHP 8.1+)

 'Pending Review',
            self::Active => 'Active',
            self::Inactive => 'Inactive',
        };
    }
}

// Backed enum (with values)
enum Role: string
{
    case Admin = 'admin';
    case Moderator = 'moderator';
    case User = 'user';

    public function permissions(): array
    {
        return match ($this) {
            self::Admin => ['read', 'write', 'delete', 'admin'],
            self::Moderator => ['read', 'write', 'delete'],
            self::User => ['read', 'write'],
        };
    }

    public static function fromString(string $value): self
    {
        return self::from($value);
    }

    public static function tryFromString(string $value): ?self
    {
        return self::tryFrom($value);
    }
}

// Usage
$status = Status::Active;
echo $status->label(); // "Active"

$role = Role::Admin;
echo $role->value; // "admin"

$userRole = Role::from('user');
$permissions = $userRole->permissions();

Object-Oriented Patterns

Traits

createdAt;
    }

    public function getUpdatedAt(): ?DateTimeImmutable
    {
        return $this->updatedAt;
    }

    public function touch(): void
    {
        $now = new DateTimeImmutable();
        $this->createdAt ??= $now;
        $this->updatedAt = $now;
    }
}

trait SoftDeletable
{
    protected ?DateTimeImmutable $deletedAt = null;

    public function delete(): void
    {
        $this->deletedAt = new DateTimeImmutable();
    }

    public function restore(): void
    {
        $this->deletedAt = null;
    }

    public function isDeleted(): bool
    {
        return $this->deletedAt !== null;
    }
}

// Using traits
class Document
{
    use Timestampable;
    use SoftDeletable;

    public function __construct(
        public string $title,
        public string $content
    ) {
        $this->touch();
    }
}

// Trait conflict resolution
trait A
{
    public function hello(): string
    {
        return 'Hello from A';
    }
}

trait B
{
    public function hello(): string
    {
        return 'Hello from B';
    }
}

class MyClass
{
    use A, B {
        A::hello insteadof B;
        B::hello as helloFromB;
    }
}

Interfaces and Abstract Classes

pdo->prepare(
            "SELECT * FROM {$this->table} WHERE id = :id"
        );
        $stmt->execute(['id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        return $row ? $this->hydrate($row) : null;
    }

    public function findAll(): array
    {
        $stmt = $this->pdo->query("SELECT * FROM {$this->table}");
        return array_map(
            fn(array $row) => $this->hydrate($row),
            $stmt->fetchAll(PDO::FETCH_ASSOC)
        );
    }
}

// Concrete implementation
class UserRepository extends BaseRepository
{
    public function __construct(PDO $pdo)
    {
        parent::__construct($pdo, 'users');
    }

    protected function hydrate(array $row): User
    {
        return new User(
            id: $row['id'],
            email: $row['email'],
            name: $row['name']
        );
    }

    public function findByEmail(string $email): ?User
    {
        // Custom method
    }
}

Error Handling

 $errors],
            $previous
        );
    }
}

class NotFoundException extends AppException
{
    public function __construct(
        string $resource,
        string $id,
        ?Throwable $previous = null
    ) {
        parent::__construct(
            "{$resource} not found: {$id}",
            'NOT_FOUND',
            ['resource' => $resource, 'id' => $id],
            $previous
        );
    }
}

// Result pattern
readonly class Result
{
    private function __construct(
        public mixed $value,
        public ?string $error,
        public bool $success
    ) {}

    public static function success(mixed $value): self
    {
        return new self($value, null, true);
    }

    public static function failure(string $error): self
    {
        return new self(null, $error, false);
    }

    public function map(callable $fn): self
    {
        if (!$this->success) {
            return $this;
        }
        return self::success($fn($this->value));
    }

    public function flatMap(callable $fn): self
    {
        if (!$this->success) {
            return $this;
        }
        return $fn($this->value);
    }
}

// Usage
function createUser(array $data): Result
{
    if (empty($data['email'])) {
        return Result::failure('Email is required');
    }

    try {
        $user = new User($data['email'], $data['name'] ?? '');
        $this->repository->save($user);
        return Result::success($user);
    } catch (Exception $e) {
        return Result::failure($e->getMessage());
    }
}

Collections and Arrays

 'Alice', 'age' => 30],
    ['name' => 'Bob', 'age' => 25],
    ['name' => 'Charlie', 'age' => 35],
];

// Filter
$adults = array_filter($users, fn($u) => $u['age'] >= 30);

// Map
$names = array_map(fn($u) => $u['name'], $users);

// Reduce
$totalAge = array_reduce($users, fn($sum, $u) => $sum + $u['age'], 0);

// Find
$bob = array_filter($users, fn($u) => $u['name'] === 'Bob');
$bob = current($bob); // Get first match

// Sort
usort($users, fn($a, $b) => $a['age']  $b['age']);

// Group by (custom)
function groupBy(array $items, string $key): array
{
    return array_reduce($items, function ($groups, $item) use ($key) {
        $groups[$item[$key]][] = $item;
        return $groups;
    }, []);
}

// Collection class
class Collection implements Countable, IteratorAggregate
{
    public function __construct(private array $items = []) {}

    public static function from(array $items): self
    {
        return new self($items);
    }

    public function map(callable $fn): self
    {
        return new self(array_map($fn, $this->items));
    }

    public function filter(callable $fn): self
    {
        return new self(array_filter($this->items, $fn));
    }

    public function reduce(callable $fn, mixed $initial = null): mixed
    {
        return array_reduce($this->items, $fn, $initial);
    }

    public function first(): mixed
    {
        return $this->items[array_key_first($this->items)] ?? null;
    }

    public function count(): int
    {
        return count($this->items);
    }

    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->items);
    }

    public function toArray(): array
    {
        return $this->items;
    }
}

// Usage
$result = Collection::from($users)
    ->filter(fn($u) => $u['age'] >= 30)
    ->map(fn($u) => $u['name'])
    ->toArray();

Dependency Injection

logger->info('Creating user', ['email' => $email]);

        $user = new User($email, $name);
        $this->repository->save($user);

        $this->events->dispatch(new UserCreated($user));

        return $user;
    }
}

// Simple container
class Container
{
    private array $bindings = [];
    private array $instances = [];

    public function bind(string $abstract, callable $concrete): void
    {
        $this->bindings[$abstract] = $concrete;
    }

    public function singleton(string $abstract, callable $concrete): void
    {
        $this->bindings[$abstract] = function ($c) use ($abstract, $concrete) {
            if (!isset($this->instances[$abstract])) {
                $this->instances[$abstract] = $concrete($c);
            }
            return $this->instances[$abstract];
        };
    }

    public function get(string $abstract): mixed
    {
        if (isset($this->bindings[$abstract])) {
            return $this->bindings[$abstract]($this);
        }

        return $this->resolve($abstract);
    }

    private function resolve(string $class): object
    {
        $reflection = new ReflectionClass($class);
        $constructor = $reflection->getConstructor();

        if (!$constructor) {
            return new $class();
        }

        $params = array_map(
            fn(ReflectionParameter $p) => $this->get($p->getType()->getName()),
            $constructor->getParameters()
        );

        return $reflection->newInstanceArgs($params);
    }
}

Related Skills

  • [[backend]] - Laravel, Symfony
  • [[database]] - Doctrine, Eloquent
  • [[testing]] - PHPUnit, Pest

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.