AgentStack
SKILL verified MIT Self-run

Php

skill-xobotyi-cc-foundry-php · by xobotyi

>-

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

Install

$ agentstack add skill-xobotyi-cc-foundry-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 No
  • 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

Strict types, explicit contracts, no magic. If a class needs a docblock to explain what its properties do, the properties are named wrong.

PHP 8.5+ is the baseline. Use modern syntax unconditionally — union types, enums, readonly classes, property hooks, named arguments, match, pipe operator. No backward compatibility with older PHP versions unless the project explicitly requires it.

Every PHP file starts with declare(strict_types=1).

References

  • Type system${CLAUDE_SKILL_DIR}/references/typing.md — Union/intersection/DNF types, nullable patterns, typed

properties and constants, coercion rules, variance

  • OOP patterns${CLAUDE_SKILL_DIR}/references/oop.md — Interfaces, traits, readonly, property hooks, enums,

constructor promotion, lazy objects, magic methods

  • Concurrency${CLAUDE_SKILL_DIR}/references/concurrency.md — Fiber API, generator coroutines, comparison table,

async library guidance

  • Packaging${CLAUDE_SKILL_DIR}/references/packaging.md — composer.json templates, version constraints, project

layouts, namespace conventions

Naming

  • Classes, interfaces, traits, enums — PascalCase: UserService, Renderable, Status
  • Methods, functions — camelCase: findById, getFullName
  • Properties, variables — camelCase: $userName, $isActive
  • Constants (class and global) — UPPERSNAKECASE: MAX_RETRIES, DEFAULT_LOCALE
  • Namespaces — PascalCase segments: App\Http\Controller
  • Enum cases — PascalCase: Status::Active, Suit::Hearts
  • Descriptive names. $userCount not $n. Short names ($i, $k, $v) only in tiny scopes (loops, array

operations).

  • No redundant context. $car->make not $car->carMake.
  • Boolean names: is/has/can/should prefix: $isValid, $hasAccess.
  • Abbreviations as words. HttpClient not HTTPClient, JsonParser not JSONParser. Treat abbreviations and

acronyms as regular words — uppercase first letter only (PER-CS).

  • No underscore prefix for protected/private visibility. Visibility modifiers exist for that.

Type Declarations

PHP 8.5+ provides a complete type system. Use it everywhere.

Core Rules

  • Type all public API boundaries — function parameters, return types, class properties, class constants.

Internal/private code benefits from types too.

  • declare(strict_types=1) in every file. No exceptions.
  • Short type names: bool, int, float, string. Never boolean, integer, double.
  • Union types with |: string|int, Foo|null. Prefer ?T for single-type nullable.
  • Intersection types with &: Countable&Traversable. Class/interface types only.
  • DNF types: array|(ArrayAccess&Traversable) — union of intersections in parentheses.
  • void return: annotate on functions that return nothing.
  • never return: functions that always throw or exit.
  • Avoid mixed — it disables type safety. Use object when you mean "any object." Use mixed only at true interop

boundaries with untyped code.

  • null last in unions: string|int|null, not null|string|int.

Typed Properties

  • Every class property gets a type declaration.
  • Typed properties must be initialized before access — use constructor promotion, default values, or constructor

assignment.

  • callable cannot be used as a property type. Use Closure instead.

Typed Constants (8.3+)

class Config
{
    public const int MAX_RETRIES = 3;
    public const string DEFAULT_LOCALE = 'en';
    protected const float TAX_RATE = 0.21;
}
  • Type all class constants. Interface constants especially — they enforce the contract at compile time.

Variance

  • Parameters are contravariant — child class can accept wider types.
  • Return types are covariant — child class can return narrower types.
  • mixed return can be narrowed to any type in a subclass.

See ${CLAUDE_SKILL_DIR}/references/typing.md for the complete type system reference.

Enumerations

  • Use enums for categorical constants. Never bare strings or ints as pseudo-enums.
  • Backed enums (string or int) when the value must interoperate with external systems (JSON, database, API).
  • from() throws on invalid value; tryFrom() returns null. Choose based on whether invalid input is a caller

error or expected.

  • Enums can implement interfaces and define methods. Use this for behavior tied to the enum's domain.
  • Enums cannot have state (no properties), cannot be extended, cannot be new'd.
  • Dynamic access: Status::{$name} (8.3+) for variable-based case resolution.
enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';
    case Suspended = 'suspended';

    public function label(): string
    {
        return match ($this) {
            self::Active => 'Active',
            self::Inactive => 'Inactive',
            self::Suspended => 'Suspended',
        };
    }
}

Classes

Properties and Visibility

  • Explicit visibility on everything — properties, methods, constants.
  • Constructor promotion for data-carrying classes:

``php class User { public function __construct( public readonly string $name, private string $email, protected int $age = 0, ) {} } ``

  • Readonly properties (8.1+) for immutable state. Must have a type declaration.
  • Readonly classes (8.2+) — all properties implicitly readonly, no dynamic properties.
  • Asymmetric visibility (8.4+) — public protected(set) for publicly readable, internally writable properties.
  • Property hooks (8.4+) — get/set logic on properties. Use instead of trivial getter/setter methods.

Incompatible with readonly.

Inheritance and Composition

  • Composition over inheritance. Use inheritance only for true "is-a" relationships.
  • Interfaces for contracts. All interface methods are public. As of 8.4, interfaces can declare property

requirements.

  • Abstract classes when you need shared implementation alongside a contract.
  • Traits for horizontal reuse. Never use traits as a substitute for interfaces. One use statement per trait, each

on its own line.

  • #[Override] (8.3+) on every method that overrides a parent or implements an interface method. Catches signature

drift at compile time.

  • super() equivalent: always use parent::method(). Never hardcode grandparent class names.

Magic Methods

  • Avoid property overloading (__get, __set) in new code. Typed properties with hooks are strictly better.
  • __toString() — define when string conversion has meaningful semantics.
  • __invoke() — for single-method objects that act as callables.
  • __serialize() / __unserialize() — prefer over __sleep() / __wakeup().

Object Patterns

  • Value objectsreadonly class with constructor promotion. Immutable by default.
  • DTOs — readonly classes with public properties. No behavior.
  • Service classes — constructor injection for dependencies, no public state.
  • Lazy objects (8.4+) — defer initialization via ReflectionClass::newLazyGhost().

Functions

  • Early return. Guard clauses first, happy path flat. Reduce nesting.
  • One function, one job. If the name contains "and", split it.
  • Type all parameters and return types on public functions.
  • Named arguments for functions with boolean flags or many optional parameters:

createUser(name: 'John', admin: true).

  • match over switchmatch is an expression, uses strict comparison, and does not fall through.
  • Pipe operator (8.5+) for functional chaining:

``php $result = $input |> trim(...) |> strtolower(...) |> ucfirst(...); ``

  • First-class callables with ... syntax: array_map(strlen(...), $strings).
  • Arrow functions for short closures: fn($x) => $x * 2. Arrow functions capture by value, not by reference.
  • Closures for multi-statement callbacks. Use use to capture outer variables. Prefer static function /

static fn when $this is not needed.

  • Closures in constants (8.5+) — static closures and first-class callables are valid in constant expressions,

default values, and attributes.

Error Handling

  • Be specific. Catch the narrowest exception type: catch (InvalidArgumentException) not catch (Exception).
  • Never bare catch (\Throwable) at arbitrary depths. Use at application boundaries only (controllers, CLI entry

points, queue workers).

  • throw is an expression (8.0+): $value ?? throw new InvalidArgumentException().
  • Chain exceptions. throw new AppException('context', previous: $e) preserves the original cause.
  • Custom exception hierarchy:

``php class AppException extends \RuntimeException {} class NotFoundException extends AppException {} class ValidationException extends AppException {} ``

  • Prefer \RuntimeException subtree for application errors. \LogicException subtree for programming errors (wrong

arguments, unimplemented methods).

  • Error strings: lowercase, no trailing punctuation. They compose in chains: "user not found: invalid ID format".
  • #[Deprecated] attribute (8.4+) on functions, methods, and constants to emit E_USER_DEPRECATED when called.
  • #[NoDiscard] attribute (8.5+) on functions whose return value must be consumed. Use (void) cast to

intentionally suppress.

  • finally for unconditional cleanup. But prefer RAII-style patterns (destructors, resource wrappers) when

possible.

Strings

  • Double-quoted interpolation for simple variables: "Hello, {$name}".
  • sprintf() for complex formatting: sprintf('Item %d: %s', $id, $name).
  • Heredoc for multiline strings. Nowdoc ( $value] = $assoc.

Match Expression

$result = match ($status) {
    Status::Active => 'active',
    Status::Inactive, Status::Suspended => 'inactive',
    default => throw new \UnexpectedValueException("Unknown status: {$status->value}"),
};
  • match is an expression — it returns a value. Use instead of switch.
  • Strict comparison (===) — no type coercion.
  • No fallthrough — each arm is isolated.
  • Multiple conditions per arm with commas.
  • Exhaustiveness — always include default unless provably exhaustive. Unmatched value throws

UnhandledMatchError.

Closures and Callables

  • First-class callable syntax (8.1+): strlen(...), $obj->method(...), ClassName::method(...).
  • Arrow functions (fn) for single-expression closures — auto-captures by value.
  • Static closures (static fn, static function) when $this is not needed — saves memory, prevents accidental

binding.

  • Closure::bind() and Closure::fromCallable() for advanced callable manipulation.
  • Type hint callables as Closure in property types (not callable).

Packaging and Toolchain

Composer

  • composer.json is the single source of truth for project metadata, dependencies, autoloading, and scripts.
  • Caret ^ constraints for dependencies: "vendor/package": "^2.0".
  • Lock file: commit for applications, skip for libraries.
  • PSR-4 autoloading: map namespace prefixes to directories.
  • Separate autoload-dev for test namespaces.

Project Structure

my-project/
├── composer.json
├── composer.lock
├── src/
│   └── ...            (PSR-4: App\)
├── tests/
│   ├── Unit/
│   ├── Integration/
│   └── bootstrap.php
├── config/
├── public/
│   └── index.php
└── var/
    ├── cache/
    └── log/
  • src/ — application code, one class per file, PSR-4 mapped.
  • tests/ — mirrors src/ structure with Unit/ and Integration/ separation.
  • public/ — web root, single entry point (index.php).
  • var/ — generated files (cache, logs). Git-ignored.
  • vendor/ — Composer dependencies. Git-ignored.

File Header

method()`.
- **Compound types:** no spaces around `|` and `&`. Parentheses for DNF without internal spaces.
- **Empty exception classes** on one line: `class NotFoundException extends AppException {}`

## Application

When **writing** PHP code: apply all conventions silently — don't narrate each rule. If an existing codebase contradicts
a convention, follow the codebase and flag the divergence once.

When **reviewing** PHP code: cite the specific violation and show the fix inline. Don't lecture — state what's wrong and
how to fix it.

Bad: "According to PHP best practices, you should use stricttypes declaration at the top of every file..." Good: "Missing declare(stricttypes=1)."


## Code Navigation — LSP Required

An Intelephense LSP server is configured for `.php` and `.phtml` files. **Always use LSP tools for code navigation
instead of Grep or Glob.** LSP understands PHP's namespace system, type inference, scope rules, and Composer autoload
boundaries — text search does not.

### Tool Routing

- **Find where a function/class is defined** → `goToDefinition` — resolves `use` statements, aliases, namespace paths
- **Find all usages of a symbol** → `findReferences` — scope-aware, no false positives from string matches
- **Get type signature or docs** → `hover` — instant type info without reading source files
- **List all symbols in a file** → `documentSymbol` — structured output: classes, methods, constants
- **Find a symbol by name across project** → `workspaceSymbol` — searches all namespaces and Composer dependencies
- **Find concrete classes implementing an interface** → `goToImplementation` — knows the type hierarchy
- **Find what calls a function** → `incomingCalls` — precise call graph across namespace boundaries
- **Find what a function calls** → `outgoingCalls` — structured dependency map

**Grep/Glob remain appropriate for:** text in comments, string literals, log messages, TODO markers, config values, env
vars, file name patterns, URLs, error message text — anything that isn't a PHP identifier.

When spawning subagents for PHP codebase exploration, instruct them to use LSP tools. Subagents have access to the same
LSP server.

## Integration

The **coding** skill governs workflow (discovery, planning, verification); this skill governs PHP implementation
choices. The **phpunit** skill governs testing conventions — both are active simultaneously when writing PHP tests.

**Strict types everywhere. Types on everything. If PHP can check it at compile time, make it do so.**

## Source & license

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

- **Author:** [xobotyi](https://github.com/xobotyi)
- **Source:** [xobotyi/cc-foundry](https://github.com/xobotyi/cc-foundry)
- **License:** MIT

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.