dist/cursor/magento2-commerce/skills/php-modern/SKILL.md
Write modern PHP 8.x code — typed properties, enums, readonly classes, match expressions, named arguments, union/intersection types, fibers, attributes, and constructor promotion. Use when writing PHP for Magento or any PHP 8.x project.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins php-modernInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs: Web-search site:php.net manual migration for the latest PHP migration guide and new features. Check https://www.php.net/releases/ for current supported versions.
Declare and assign properties directly in the constructor signature — eliminates boilerplate. Heavily used in Magento service classes.
Call functions with parameter names: array_slice(array: $arr, offset: 2). Improves readability for functions with many parameters.
Type-safe switch replacement that returns a value. No fall-through, strict comparison. Better than switch for value mapping.
int|string in parameter and return types. Allows multiple type declarations.
$obj?->method()?->property — short-circuits to null if any part is null. Replaces nested null checks.
Native metadata annotations: #[Route('/path')], #[Override]. Replace docblock annotations with first-class language support.
First-class enumerations — backed (string/int) and unit enums. Perfect for status codes, types, categories. Use backed enums for database/API values.
public readonly string $name — can only be set once (usually in constructor). Enforces immutability.
Lightweight concurrency primitives — PHP-level coroutines. Foundation for async frameworks. Limited direct usage in Magento.
TypeA&TypeB — value must satisfy ALL types. Useful for ensuring a parameter implements multiple interfaces.
strlen(...) creates a Closure from a function. Cleaner than Closure::fromCallable('strlen').
readonly class Dto { ... } — all properties are implicitly readonly. Perfect for Data Transfer Objects and value objects.
Creating properties not declared in the class is deprecated. Magento core addressed this throughout — always declare properties.
true, false, null as standalone types in declarations.
Traits can now define constants.
const string NAME = 'value'; — type-safe constants. Strengthens contract enforcement.
#[\Override] AttributeDocuments that a method intentionally overrides a parent method. Compiler error if the parent method doesn't exist.
json_validate() FunctionValidate JSON without decoding — faster than json_decode + error check.
$class::{$constant} — dynamic constant access.
Define get/set behavior directly on properties:
public string $name {
set => strtolower($value);
get => ucfirst($this->name);
}
public private(set) string $name — readable publicly, writable only privately.
declare(strict_types=1); in all files?string or string|nullUse readonly classes for DTOs and value objects — common in service layers.
Replace string/int constants with backed enums for order statuses, product types, etc.
Magento uses constructor injection extensively — promotion reduces boilerplate significantly.
declare(strict_types=1);#[\Override] when overriding parent methodsFetch php.net docs for exact syntax and behavior of new features before using them.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.