@cubis/foundry 0.3.71 → 0.3.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -2
- package/dist/cli/core.js +9 -22
- package/dist/cli/core.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/core.ts +13 -22
- package/workflows/powers/accessibility/POWER.md +83 -94
- package/workflows/powers/accessibility/SKILL.md +82 -94
- package/workflows/powers/agent-design/POWER.md +201 -0
- package/workflows/powers/agent-design/SKILL.md +198 -0
- package/workflows/powers/agent-design/references/clarification-patterns.md +153 -0
- package/workflows/powers/agent-design/references/skill-testing.md +164 -0
- package/workflows/powers/agent-design/references/workflow-patterns.md +226 -0
- package/workflows/powers/agentic-eval/POWER.md +62 -0
- package/workflows/powers/agentic-eval/SKILL.md +59 -0
- package/workflows/powers/agentic-eval/references/rubric-and-regression-checklist.md +11 -0
- package/workflows/powers/api-designer/POWER.md +43 -71
- package/workflows/powers/api-designer/SKILL.md +43 -71
- package/workflows/powers/api-patterns/POWER.md +42 -56
- package/workflows/powers/api-patterns/SKILL.md +42 -57
- package/workflows/powers/architecture-designer/POWER.md +43 -60
- package/workflows/powers/architecture-designer/SKILL.md +43 -60
- package/workflows/powers/ask-questions-if-underspecified/POWER.md +51 -3
- package/workflows/powers/auth-architect/POWER.md +69 -0
- package/workflows/powers/auth-architect/SKILL.md +66 -0
- package/workflows/powers/auth-architect/references/session-token-policy-checklist.md +45 -0
- package/workflows/powers/behavioral-modes/POWER.md +100 -9
- package/workflows/powers/c-pro/POWER.md +105 -0
- package/workflows/powers/c-pro/SKILL.md +102 -0
- package/workflows/powers/c-pro/references/build-systems-and-toolchains.md +148 -0
- package/workflows/powers/c-pro/references/common-ub-and-portability.md +166 -0
- package/workflows/powers/c-pro/references/debugging-with-sanitizers.md +205 -0
- package/workflows/powers/c-pro/references/memory-safety-and-build-checklist.md +60 -0
- package/workflows/powers/c-pro/references/posix-and-platform-apis.md +244 -0
- package/workflows/powers/changelog-generator/POWER.md +127 -63
- package/workflows/powers/changelog-generator/SKILL.md +126 -63
- package/workflows/powers/ci-cd-pipelines/POWER.md +156 -0
- package/workflows/powers/ci-cd-pipelines/SKILL.md +153 -0
- package/workflows/powers/ci-cd-pipelines/references/github-actions-patterns.md +160 -0
- package/workflows/powers/ci-cd-pipelines/references/pipeline-security-checklist.md +57 -0
- package/workflows/powers/cli-developer/POWER.md +152 -95
- package/workflows/powers/cli-developer/SKILL.md +152 -95
- package/workflows/powers/cpp-pro/POWER.md +111 -0
- package/workflows/powers/cpp-pro/SKILL.md +108 -0
- package/workflows/powers/cpp-pro/references/concurrency-primitives.md +266 -0
- package/workflows/powers/cpp-pro/references/move-semantics-and-value-types.md +149 -0
- package/workflows/powers/cpp-pro/references/performance-and-profiling.md +191 -0
- package/workflows/powers/cpp-pro/references/raii-and-modern-cpp-checklist.md +87 -0
- package/workflows/powers/cpp-pro/references/template-and-concepts-patterns.md +205 -0
- package/workflows/powers/csharp-pro/POWER.md +47 -22
- package/workflows/powers/csharp-pro/SKILL.md +47 -22
- package/workflows/powers/dart-pro/POWER.md +68 -0
- package/workflows/powers/dart-pro/SKILL.md +65 -0
- package/workflows/powers/dart-pro/references/isolate-and-concurrency.md +180 -0
- package/workflows/powers/dart-pro/references/null-safety-and-async-patterns.md +133 -0
- package/workflows/powers/dart-pro/references/package-structure-and-linting.md +193 -0
- package/workflows/powers/dart-pro/references/sealed-records-patterns.md +173 -0
- package/workflows/powers/dart-pro/references/testing-and-mocking.md +235 -0
- package/workflows/powers/database-design/POWER.md +47 -33
- package/workflows/powers/database-design/SKILL.md +47 -33
- package/workflows/powers/database-optimizer/POWER.md +43 -64
- package/workflows/powers/database-optimizer/SKILL.md +43 -64
- package/workflows/powers/database-skills/POWER.md +59 -93
- package/workflows/powers/database-skills/SKILL.md +59 -93
- package/workflows/powers/debugging-strategies/POWER.md +69 -0
- package/workflows/powers/debugging-strategies/SKILL.md +66 -0
- package/workflows/powers/debugging-strategies/references/reproduce-isolate-verify-checklist.md +42 -0
- package/workflows/powers/deep-research/POWER.md +67 -0
- package/workflows/powers/deep-research/SKILL.md +64 -0
- package/workflows/powers/deep-research/references/multi-round-research-loop.md +80 -0
- package/workflows/powers/design-system-builder/POWER.md +130 -116
- package/workflows/powers/design-system-builder/SKILL.md +130 -116
- package/workflows/powers/devops-engineer/POWER.md +120 -57
- package/workflows/powers/devops-engineer/SKILL.md +120 -57
- package/workflows/powers/docker-kubernetes/POWER.md +94 -0
- package/workflows/powers/docker-kubernetes/SKILL.md +91 -0
- package/workflows/powers/docker-kubernetes/references/dockerfile-optimization-checklist.md +35 -0
- package/workflows/powers/docker-kubernetes/references/kubernetes-deployment-patterns.md +59 -0
- package/workflows/powers/documentation-templates/POWER.md +158 -127
- package/workflows/powers/documentation-templates/SKILL.md +158 -127
- package/workflows/powers/drizzle-expert/POWER.md +66 -0
- package/workflows/powers/drizzle-expert/SKILL.md +63 -0
- package/workflows/powers/drizzle-expert/references/runtime-pairing-matrix.md +16 -0
- package/workflows/powers/drizzle-expert/references/schema-and-migration-playbook.md +18 -0
- package/workflows/powers/error-ux-observability/POWER.md +144 -131
- package/workflows/powers/error-ux-observability/SKILL.md +143 -131
- package/workflows/powers/fastapi-expert/POWER.md +46 -60
- package/workflows/powers/fastapi-expert/SKILL.md +46 -60
- package/workflows/powers/firebase/POWER.md +65 -0
- package/workflows/powers/firebase/SKILL.md +62 -0
- package/workflows/powers/firebase/references/platform-routing.md +16 -0
- package/workflows/powers/firebase/references/rules-and-indexes-checklist.md +11 -0
- package/workflows/powers/flutter-design-system/POWER.md +63 -0
- package/workflows/powers/flutter-design-system/SKILL.md +60 -0
- package/workflows/powers/flutter-design-system/references/shared-widgets.md +29 -0
- package/workflows/powers/flutter-design-system/references/tokens-and-theme.md +34 -0
- package/workflows/powers/flutter-drift/POWER.md +65 -0
- package/workflows/powers/flutter-drift/SKILL.md +62 -0
- package/workflows/powers/flutter-drift/references/migrations.md +22 -0
- package/workflows/powers/flutter-drift/references/query-patterns.md +26 -0
- package/workflows/powers/flutter-feature/POWER.md +65 -0
- package/workflows/powers/flutter-feature/SKILL.md +62 -0
- package/workflows/powers/flutter-feature/references/architecture-rules.md +85 -0
- package/workflows/powers/flutter-feature/references/composite-provider.md +58 -0
- package/workflows/powers/flutter-feature/references/outbox-pattern.md +87 -0
- package/workflows/powers/flutter-feature/references/testing-patterns.md +218 -0
- package/workflows/powers/flutter-go-router/POWER.md +64 -0
- package/workflows/powers/flutter-go-router/SKILL.md +61 -0
- package/workflows/powers/flutter-go-router/references/guards-and-deeplinks.md +20 -0
- package/workflows/powers/flutter-go-router/references/typed-routes.md +27 -0
- package/workflows/powers/flutter-offline-sync/POWER.md +62 -0
- package/workflows/powers/flutter-offline-sync/SKILL.md +59 -0
- package/workflows/powers/flutter-offline-sync/references/outbox-full.md +44 -0
- package/workflows/powers/flutter-repository/POWER.md +64 -0
- package/workflows/powers/flutter-repository/SKILL.md +61 -0
- package/workflows/powers/flutter-repository/references/drift-patterns.md +21 -0
- package/workflows/powers/flutter-repository/references/retrofit-patterns.md +20 -0
- package/workflows/powers/flutter-riverpod/POWER.md +70 -0
- package/workflows/powers/flutter-riverpod/SKILL.md +67 -0
- package/workflows/powers/flutter-riverpod/references/async-and-mutations.md +19 -0
- package/workflows/powers/flutter-riverpod/references/async-lifecycle.md +19 -0
- package/workflows/powers/flutter-riverpod/references/provider-selection.md +20 -0
- package/workflows/powers/flutter-riverpod/references/testing.md +21 -0
- package/workflows/powers/flutter-riverpod/references/version-matrix.md +24 -0
- package/workflows/powers/flutter-state-machine/POWER.md +62 -0
- package/workflows/powers/flutter-state-machine/SKILL.md +59 -0
- package/workflows/powers/flutter-state-machine/references/app-state-contract.md +23 -0
- package/workflows/powers/flutter-state-machine/references/ui-rendering.md +14 -0
- package/workflows/powers/flutter-testing/POWER.md +64 -0
- package/workflows/powers/flutter-testing/SKILL.md +61 -0
- package/workflows/powers/flutter-testing/references/offline-sync-tests.md +16 -0
- package/workflows/powers/flutter-testing/references/test-layers.md +33 -0
- package/workflows/powers/frontend-code-review/POWER.md +137 -0
- package/workflows/powers/frontend-code-review/SKILL.md +134 -0
- package/workflows/powers/frontend-code-review/references/common-antipatterns.md +86 -0
- package/workflows/powers/frontend-code-review/references/performance-budgets.md +56 -0
- package/workflows/powers/frontend-code-review/references/review-checklists.md +47 -0
- package/workflows/powers/frontend-design/POWER.md +163 -362
- package/workflows/powers/frontend-design/SKILL.md +163 -362
- package/workflows/powers/game-development/POWER.md +57 -140
- package/workflows/powers/game-development/SKILL.md +57 -140
- package/workflows/powers/geo-fundamentals/POWER.md +64 -126
- package/workflows/powers/geo-fundamentals/SKILL.md +64 -127
- package/workflows/powers/git-workflow/POWER.md +135 -0
- package/workflows/powers/git-workflow/SKILL.md +132 -0
- package/workflows/powers/git-workflow/references/pr-review-checklist.md +63 -0
- package/workflows/powers/golang-pro/POWER.md +46 -35
- package/workflows/powers/golang-pro/SKILL.md +46 -35
- package/workflows/powers/graphql-architect/POWER.md +44 -62
- package/workflows/powers/graphql-architect/SKILL.md +44 -62
- package/workflows/powers/i18n-localization/POWER.md +118 -103
- package/workflows/powers/i18n-localization/SKILL.md +118 -103
- package/workflows/powers/java-pro/POWER.md +47 -22
- package/workflows/powers/java-pro/SKILL.md +47 -22
- package/workflows/powers/javascript-pro/POWER.md +47 -34
- package/workflows/powers/javascript-pro/SKILL.md +47 -34
- package/workflows/powers/kotlin-pro/POWER.md +46 -23
- package/workflows/powers/kotlin-pro/SKILL.md +46 -23
- package/workflows/powers/legacy-modernizer/POWER.md +43 -60
- package/workflows/powers/legacy-modernizer/SKILL.md +43 -60
- package/workflows/powers/mcp-builder/POWER.md +65 -0
- package/workflows/powers/mcp-builder/SKILL.md +62 -0
- package/workflows/powers/mcp-builder/references/testing-and-evals.md +17 -0
- package/workflows/powers/mcp-builder/references/transport-and-tool-design.md +17 -0
- package/workflows/powers/microservices-architect/POWER.md +43 -70
- package/workflows/powers/microservices-architect/SKILL.md +43 -70
- package/workflows/powers/mobile-design/POWER.md +110 -345
- package/workflows/powers/mobile-design/SKILL.md +110 -345
- package/workflows/powers/mongodb/POWER.md +67 -0
- package/workflows/powers/mongodb/SKILL.md +64 -0
- package/workflows/powers/mongodb/references/mongodb-checklist.md +20 -0
- package/workflows/powers/mysql/POWER.md +67 -0
- package/workflows/powers/mysql/SKILL.md +64 -0
- package/workflows/powers/mysql/references/mysql-checklist.md +20 -0
- package/workflows/powers/neki/POWER.md +67 -0
- package/workflows/powers/neki/SKILL.md +64 -0
- package/workflows/powers/neki/references/neki-checklist.md +18 -0
- package/workflows/powers/nestjs-expert/POWER.md +45 -91
- package/workflows/powers/nestjs-expert/SKILL.md +45 -91
- package/workflows/powers/nextjs-developer/POWER.md +51 -44
- package/workflows/powers/nextjs-developer/SKILL.md +51 -44
- package/workflows/powers/nodejs-best-practices/POWER.md +48 -29
- package/workflows/powers/nodejs-best-practices/SKILL.md +48 -29
- package/workflows/powers/observability/POWER.md +109 -0
- package/workflows/powers/observability/SKILL.md +106 -0
- package/workflows/powers/observability/references/alerting-and-slo-checklist.md +87 -0
- package/workflows/powers/observability/references/opentelemetry-setup-guide.md +121 -0
- package/workflows/powers/openai-docs/POWER.md +61 -0
- package/workflows/powers/openai-docs/SKILL.md +58 -0
- package/workflows/powers/openai-docs/references/official-source-playbook.md +10 -0
- package/workflows/powers/performance-profiling/POWER.md +61 -114
- package/workflows/powers/performance-profiling/SKILL.md +61 -114
- package/workflows/powers/php-pro/POWER.md +116 -0
- package/workflows/powers/php-pro/SKILL.md +113 -0
- package/workflows/powers/php-pro/references/architecture-and-di.md +239 -0
- package/workflows/powers/php-pro/references/modern-php-features.md +189 -0
- package/workflows/powers/php-pro/references/performance-and-deployment.md +197 -0
- package/workflows/powers/php-pro/references/php84-strict-typing-checklist.md +161 -0
- package/workflows/powers/php-pro/references/testing-and-static-analysis.md +235 -0
- package/workflows/powers/playwright-e2e/POWER.md +85 -0
- package/workflows/powers/playwright-e2e/SKILL.md +82 -0
- package/workflows/powers/playwright-e2e/references/locator-trace-flake-checklist.md +80 -0
- package/workflows/powers/postgres/POWER.md +67 -0
- package/workflows/powers/postgres/SKILL.md +64 -0
- package/workflows/powers/postgres/references/postgres-checklist.md +20 -0
- package/workflows/powers/prompt-engineer/POWER.md +47 -30
- package/workflows/powers/prompt-engineer/SKILL.md +47 -30
- package/workflows/powers/python-pro/POWER.md +47 -36
- package/workflows/powers/python-pro/SKILL.md +47 -36
- package/workflows/powers/react-best-practices/POWER.md +56 -33
- package/workflows/powers/react-best-practices/SKILL.md +56 -33
- package/workflows/powers/react-expert/POWER.md +47 -37
- package/workflows/powers/react-expert/SKILL.md +47 -37
- package/workflows/powers/redis/POWER.md +67 -0
- package/workflows/powers/redis/SKILL.md +64 -0
- package/workflows/powers/redis/references/redis-checklist.md +19 -0
- package/workflows/powers/ruby-pro/POWER.md +118 -0
- package/workflows/powers/ruby-pro/SKILL.md +115 -0
- package/workflows/powers/ruby-pro/references/modern-ruby-features.md +189 -0
- package/workflows/powers/ruby-pro/references/object-design-patterns.md +220 -0
- package/workflows/powers/ruby-pro/references/performance-and-profiling.md +224 -0
- package/workflows/powers/ruby-pro/references/ruby-concurrency-and-testing.md +190 -0
- package/workflows/powers/ruby-pro/references/testing-and-rspec.md +236 -0
- package/workflows/powers/rust-pro/POWER.md +45 -31
- package/workflows/powers/rust-pro/SKILL.md +45 -31
- package/workflows/powers/security-engineer/POWER.md +129 -0
- package/workflows/powers/security-engineer/SKILL.md +126 -0
- package/workflows/powers/seo-fundamentals/POWER.md +59 -102
- package/workflows/powers/seo-fundamentals/SKILL.md +59 -102
- package/workflows/powers/serverless-patterns/POWER.md +171 -0
- package/workflows/powers/serverless-patterns/SKILL.md +168 -0
- package/workflows/powers/skill-creator/POWER.md +90 -0
- package/workflows/powers/skill-creator/SKILL.md +87 -0
- package/workflows/powers/skill-creator/references/platform-formats.md +181 -0
- package/workflows/powers/skill-creator/references/schemas.md +430 -0
- package/workflows/powers/spec-miner/POWER.md +49 -57
- package/workflows/powers/spec-miner/SKILL.md +49 -57
- package/workflows/powers/sqlite/POWER.md +67 -0
- package/workflows/powers/sqlite/SKILL.md +64 -0
- package/workflows/powers/sqlite/references/sqlite-checklist.md +19 -0
- package/workflows/powers/sre-engineer/POWER.md +123 -64
- package/workflows/powers/sre-engineer/SKILL.md +123 -64
- package/workflows/powers/static-analysis/POWER.md +121 -77
- package/workflows/powers/static-analysis/SKILL.md +121 -77
- package/workflows/powers/stripe-best-practices/POWER.md +140 -17
- package/workflows/powers/stripe-best-practices/SKILL.md +139 -17
- package/workflows/powers/supabase/POWER.md +67 -0
- package/workflows/powers/supabase/SKILL.md +64 -0
- package/workflows/powers/supabase/references/supabase-checklist.md +19 -0
- package/workflows/powers/swift-pro/POWER.md +118 -0
- package/workflows/powers/swift-pro/SKILL.md +115 -0
- package/workflows/powers/swift-pro/references/concurrency-patterns.md +165 -0
- package/workflows/powers/swift-pro/references/protocol-and-generics.md +172 -0
- package/workflows/powers/swift-pro/references/sendable-and-isolation.md +116 -0
- package/workflows/powers/swift-pro/references/swift-concurrency-and-protocols.md +260 -0
- package/workflows/powers/swift-pro/references/testing-and-packages.md +192 -0
- package/workflows/powers/tailwind-patterns/POWER.md +71 -240
- package/workflows/powers/tailwind-patterns/SKILL.md +71 -240
- package/workflows/powers/testing-patterns/POWER.md +155 -10
- package/workflows/powers/testing-patterns/SKILL.md +155 -10
- package/workflows/powers/typescript-pro/POWER.md +47 -38
- package/workflows/powers/typescript-pro/SKILL.md +47 -38
- package/workflows/powers/vitess/POWER.md +67 -0
- package/workflows/powers/vitess/SKILL.md +64 -0
- package/workflows/powers/vitess/references/vitess-checklist.md +19 -0
- package/workflows/powers/vulnerability-scanner/POWER.md +146 -10
- package/workflows/powers/vulnerability-scanner/SKILL.md +146 -10
- package/workflows/powers/web-perf/POWER.md +43 -170
- package/workflows/powers/web-perf/SKILL.md +43 -170
- package/workflows/powers/webapp-testing/POWER.md +43 -164
- package/workflows/powers/webapp-testing/SKILL.md +43 -164
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/rules/GEMINI.md +65 -42
- package/workflows/workflows/agent-environment-setup/platforms/claude/rules/CLAUDE.md +8 -6
- package/workflows/workflows/agent-environment-setup/platforms/codex/rules/AGENTS.md +65 -41
- package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/copilot-instructions.md +8 -6
- package/workflows/workflows/agent-environment-setup/shared/rules/STEERING.md +9 -8
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/codex.md +1 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Modern PHP Features
|
|
2
|
+
|
|
3
|
+
## Enums (PHP 8.1+)
|
|
4
|
+
|
|
5
|
+
```php
|
|
6
|
+
// Pure enum — no backing value
|
|
7
|
+
enum Status {
|
|
8
|
+
case Active;
|
|
9
|
+
case Inactive;
|
|
10
|
+
case Suspended;
|
|
11
|
+
|
|
12
|
+
public function label(): string {
|
|
13
|
+
return match($this) {
|
|
14
|
+
self::Active => 'Active',
|
|
15
|
+
self::Inactive => 'Inactive',
|
|
16
|
+
self::Suspended => 'Suspended',
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Backed enum — string or int backing type
|
|
22
|
+
enum Role: string {
|
|
23
|
+
case Admin = 'admin';
|
|
24
|
+
case Editor = 'editor';
|
|
25
|
+
case Viewer = 'viewer';
|
|
26
|
+
|
|
27
|
+
// Create from string (throws ValueError if invalid)
|
|
28
|
+
// Role::from('admin') → Role::Admin
|
|
29
|
+
// Role::tryFrom('unknown') → null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Enum implementing interface
|
|
33
|
+
interface HasPermissions {
|
|
34
|
+
public function permissions(): array;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
enum Role: string implements HasPermissions {
|
|
38
|
+
case Admin = 'admin';
|
|
39
|
+
case Editor = 'editor';
|
|
40
|
+
|
|
41
|
+
public function permissions(): array {
|
|
42
|
+
return match($this) {
|
|
43
|
+
self::Admin => ['read', 'write', 'delete', 'manage'],
|
|
44
|
+
self::Editor => ['read', 'write'],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Readonly Properties and Classes (PHP 8.2+)
|
|
51
|
+
|
|
52
|
+
```php
|
|
53
|
+
// Readonly properties — set once, never modified
|
|
54
|
+
class User {
|
|
55
|
+
public function __construct(
|
|
56
|
+
public readonly int $id,
|
|
57
|
+
public readonly string $name,
|
|
58
|
+
public readonly Email $email,
|
|
59
|
+
public readonly \DateTimeImmutable $createdAt = new \DateTimeImmutable(),
|
|
60
|
+
) {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Readonly class — all properties are implicitly readonly
|
|
64
|
+
readonly class Money {
|
|
65
|
+
public function __construct(
|
|
66
|
+
public int $amount,
|
|
67
|
+
public string $currency,
|
|
68
|
+
) {}
|
|
69
|
+
|
|
70
|
+
public function add(Money $other): self {
|
|
71
|
+
if ($this->currency !== $other->currency) {
|
|
72
|
+
throw new \DomainException('Cannot add different currencies');
|
|
73
|
+
}
|
|
74
|
+
return new self($this->amount + $other->amount, $this->currency);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Match Expression (PHP 8.0+)
|
|
80
|
+
|
|
81
|
+
```php
|
|
82
|
+
// match is strict (===), returns a value, no fall-through
|
|
83
|
+
$result = match($status) {
|
|
84
|
+
200, 201 => 'success',
|
|
85
|
+
301, 302 => 'redirect',
|
|
86
|
+
404 => 'not found',
|
|
87
|
+
500 => 'server error',
|
|
88
|
+
default => 'unknown',
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// match with no subject — replaces if/elseif chains
|
|
92
|
+
$tier = match(true) {
|
|
93
|
+
$points >= 1000 => 'gold',
|
|
94
|
+
$points >= 500 => 'silver',
|
|
95
|
+
$points >= 100 => 'bronze',
|
|
96
|
+
default => 'standard',
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Named Arguments (PHP 8.0+)
|
|
101
|
+
|
|
102
|
+
```php
|
|
103
|
+
// Skip optional parameters, improve readability
|
|
104
|
+
$response = new JsonResponse(
|
|
105
|
+
data: $payload,
|
|
106
|
+
status: 201,
|
|
107
|
+
headers: ['X-Request-Id' => $requestId],
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// Useful with functions that have many options
|
|
111
|
+
str_contains(haystack: $input, needle: 'search');
|
|
112
|
+
|
|
113
|
+
// Named arguments work with arrays using spread
|
|
114
|
+
$args = ['data' => $payload, 'status' => 200];
|
|
115
|
+
$response = new JsonResponse(...$args);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Fibers (PHP 8.1+)
|
|
119
|
+
|
|
120
|
+
```php
|
|
121
|
+
// Fibers provide cooperative multitasking — used by frameworks, not typically by userland
|
|
122
|
+
$fiber = new Fiber(function (): void {
|
|
123
|
+
$value = Fiber::suspend('first');
|
|
124
|
+
echo "Resumed with: $value\n";
|
|
125
|
+
Fiber::suspend('second');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
$result1 = $fiber->start(); // 'first'
|
|
129
|
+
$result2 = $fiber->resume('hello'); // prints "Resumed with: hello", returns 'second'
|
|
130
|
+
|
|
131
|
+
// Real-world: async frameworks (ReactPHP, Amp, Revolt) use fibers internally
|
|
132
|
+
// You typically use the framework's async API, not raw fibers
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## First-Class Callable Syntax (PHP 8.1+)
|
|
136
|
+
|
|
137
|
+
```php
|
|
138
|
+
// Create closures from existing functions/methods
|
|
139
|
+
$users = array_filter($users, strlen(...)); // passes strlen as callable
|
|
140
|
+
$names = array_map($user->getName(...), $users);
|
|
141
|
+
|
|
142
|
+
// Method references
|
|
143
|
+
$validator = $this->validate(...);
|
|
144
|
+
$formatter = NumberFormatter::format(...);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Intersection and Union Types
|
|
148
|
+
|
|
149
|
+
```php
|
|
150
|
+
// Union types (PHP 8.0) — value is one of the types
|
|
151
|
+
function process(string|int $value): string|false {
|
|
152
|
+
// ...
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Intersection types (PHP 8.1) — value satisfies all types
|
|
156
|
+
function countAndIterate(Countable&Iterator $items): void {
|
|
157
|
+
echo count($items);
|
|
158
|
+
foreach ($items as $item) { /* ... */ }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Disjunctive Normal Form types (PHP 8.2)
|
|
162
|
+
function handle((Countable&Iterator)|null $items): void {
|
|
163
|
+
// nullable intersection type
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Property Hooks (PHP 8.4)
|
|
168
|
+
|
|
169
|
+
```php
|
|
170
|
+
// Virtual properties with get/set hooks
|
|
171
|
+
class Temperature {
|
|
172
|
+
public float $celsius {
|
|
173
|
+
get => ($this->fahrenheit - 32) * 5 / 9;
|
|
174
|
+
set => $this->fahrenheit = $value * 9 / 5 + 32;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public function __construct(
|
|
178
|
+
public float $fahrenheit,
|
|
179
|
+
) {}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Asymmetric visibility (PHP 8.4)
|
|
183
|
+
class User {
|
|
184
|
+
public function __construct(
|
|
185
|
+
public private(set) string $name, // readable publicly, writable only internally
|
|
186
|
+
public protected(set) int $age,
|
|
187
|
+
) {}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Performance and Deployment
|
|
2
|
+
|
|
3
|
+
## OPcache Configuration
|
|
4
|
+
|
|
5
|
+
```ini
|
|
6
|
+
; php.ini — production OPcache settings
|
|
7
|
+
opcache.enable=1
|
|
8
|
+
opcache.memory_consumption=256 ; MB, adjust per app size
|
|
9
|
+
opcache.max_accelerated_files=20000 ; must be prime, covers most projects
|
|
10
|
+
opcache.validate_timestamps=0 ; NEVER check file changes in production
|
|
11
|
+
opcache.revalidate_freq=0 ; irrelevant when validate_timestamps=0
|
|
12
|
+
|
|
13
|
+
; JIT compilation (PHP 8.0+)
|
|
14
|
+
opcache.jit_buffer_size=128M
|
|
15
|
+
opcache.jit=1255 ; tracing JIT — best for long-running
|
|
16
|
+
; Use 1205 for function-level JIT if tracing JIT causes issues
|
|
17
|
+
|
|
18
|
+
; File cache for faster restarts
|
|
19
|
+
opcache.file_cache='/tmp/opcache'
|
|
20
|
+
opcache.file_cache_consistency_checks=0 ; skip in production
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Preloading (PHP 7.4+)
|
|
24
|
+
|
|
25
|
+
```php
|
|
26
|
+
// preload.php — loaded once at server startup, shared across all requests
|
|
27
|
+
// Set in php.ini: opcache.preload=/app/preload.php
|
|
28
|
+
// opcache.preload_user=www-data
|
|
29
|
+
|
|
30
|
+
$files = [
|
|
31
|
+
// Framework core classes
|
|
32
|
+
__DIR__ . '/vendor/autoload.php',
|
|
33
|
+
// Heavily used domain classes
|
|
34
|
+
__DIR__ . '/src/Domain/Order.php',
|
|
35
|
+
__DIR__ . '/src/Domain/User.php',
|
|
36
|
+
__DIR__ . '/src/Service/OrderService.php',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
foreach ($files as $file) {
|
|
40
|
+
if (file_exists($file)) {
|
|
41
|
+
opcache_compile_file($file);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Composer autoload preloading (Laravel example)
|
|
46
|
+
// require __DIR__ . '/vendor/autoload.php';
|
|
47
|
+
// (new Illuminate\Foundation\PackageManifest(...))->preload();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Profiling with Xdebug
|
|
51
|
+
|
|
52
|
+
```ini
|
|
53
|
+
; php.ini — profiling mode
|
|
54
|
+
xdebug.mode=profile
|
|
55
|
+
xdebug.output_dir=/tmp/xdebug-profiles
|
|
56
|
+
xdebug.profiler_output_name=cachegrind.out.%R.%t
|
|
57
|
+
|
|
58
|
+
; Trigger-based profiling (don't profile every request)
|
|
59
|
+
xdebug.start_with_request=trigger
|
|
60
|
+
; Add ?XDEBUG_PROFILE=1 to URL or set cookie
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Analyze with KCachegrind/QCachegrind
|
|
65
|
+
kcachegrind /tmp/xdebug-profiles/cachegrind.out.*.1234567890
|
|
66
|
+
|
|
67
|
+
# Or use webgrind for browser-based analysis
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Profiling with Blackfire
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Install Blackfire probe + agent
|
|
74
|
+
# Profile a specific request
|
|
75
|
+
blackfire run php artisan my:command
|
|
76
|
+
blackfire curl https://myapp.test/api/orders
|
|
77
|
+
|
|
78
|
+
# Compare two profiles
|
|
79
|
+
blackfire diff profile-1-uuid profile-2-uuid
|
|
80
|
+
|
|
81
|
+
# Assertions in CI
|
|
82
|
+
blackfire-player run scenarios.bkf --endpoint=https://staging.myapp.com
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Database Query Optimization
|
|
86
|
+
|
|
87
|
+
```php
|
|
88
|
+
// Avoid N+1 queries — eager load relations
|
|
89
|
+
// BAD — N+1 queries
|
|
90
|
+
$orders = Order::all();
|
|
91
|
+
foreach ($orders as $order) {
|
|
92
|
+
echo $order->customer->name; // 1 query per order
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// GOOD — eager loading
|
|
96
|
+
$orders = Order::with('customer')->get(); // 2 queries total
|
|
97
|
+
|
|
98
|
+
// Use query scope for reusable filters
|
|
99
|
+
class Order extends Model
|
|
100
|
+
{
|
|
101
|
+
public function scopeRecent(Builder $query): Builder
|
|
102
|
+
{
|
|
103
|
+
return $query->where('created_at', '>', now()->subDays(30));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public function scopeForCustomer(Builder $query, int $customerId): Builder
|
|
107
|
+
{
|
|
108
|
+
return $query->where('customer_id', $customerId);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Usage: Order::recent()->forCustomer(42)->get();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Caching Patterns
|
|
116
|
+
|
|
117
|
+
```php
|
|
118
|
+
// Cache-aside pattern
|
|
119
|
+
public function getProduct(int $id): Product
|
|
120
|
+
{
|
|
121
|
+
$cacheKey = "product:{$id}";
|
|
122
|
+
|
|
123
|
+
return Cache::remember($cacheKey, ttl: 3600, callback: function () use ($id) {
|
|
124
|
+
return $this->repository->findById($id)
|
|
125
|
+
?? throw new ProductNotFoundException($id);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Cache invalidation on write
|
|
130
|
+
public function updateProduct(int $id, UpdateProductDto $dto): Product
|
|
131
|
+
{
|
|
132
|
+
$product = $this->repository->update($id, $dto);
|
|
133
|
+
Cache::forget("product:{$id}");
|
|
134
|
+
Cache::tags(['products'])->flush(); // tag-based invalidation
|
|
135
|
+
return $product;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## FrankenPHP / Swoole / RoadRunner
|
|
140
|
+
|
|
141
|
+
```php
|
|
142
|
+
// FrankenPHP worker mode — keep application in memory
|
|
143
|
+
// frankenphp.yaml
|
|
144
|
+
worker:
|
|
145
|
+
cmd: ["frankenphp", "php-server", "--worker", "public/index.php"]
|
|
146
|
+
watch:
|
|
147
|
+
- src/**/*.php
|
|
148
|
+
|
|
149
|
+
// Swoole HTTP server (Laravel Octane)
|
|
150
|
+
// Long-running process — beware of:
|
|
151
|
+
// 1. Static/global state leaking between requests
|
|
152
|
+
// 2. Memory leaks from uncollected references
|
|
153
|
+
// 3. Database connections staying open
|
|
154
|
+
|
|
155
|
+
// Reset state between requests
|
|
156
|
+
protected function resetState(): void
|
|
157
|
+
{
|
|
158
|
+
// Clear request-scoped caches
|
|
159
|
+
// Reset singleton instances that hold request state
|
|
160
|
+
// Flush buffered output
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Deployment Checklist
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# 1. Install production dependencies
|
|
168
|
+
composer install --no-dev --optimize-autoloader --classmap-authoritative
|
|
169
|
+
|
|
170
|
+
# 2. Clear and warm caches
|
|
171
|
+
php artisan config:cache # Laravel
|
|
172
|
+
php artisan route:cache
|
|
173
|
+
php artisan view:cache
|
|
174
|
+
php artisan event:cache
|
|
175
|
+
|
|
176
|
+
# 3. Run migrations
|
|
177
|
+
php artisan migrate --force
|
|
178
|
+
|
|
179
|
+
# 4. OPcache reset (after deploying new code)
|
|
180
|
+
# Via SIGUSR2 to PHP-FPM, or cachetool:
|
|
181
|
+
cachetool opcache:reset
|
|
182
|
+
|
|
183
|
+
# 5. Verify
|
|
184
|
+
php artisan about # check config
|
|
185
|
+
php artisan queue:monitor # check workers
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Common Performance Anti-Patterns
|
|
189
|
+
|
|
190
|
+
| Anti-pattern | Impact | Fix |
|
|
191
|
+
| ---------------------------- | --------------------------- | ----------------------------------- |
|
|
192
|
+
| N+1 queries | O(n) DB calls per list | Eager loading, joins |
|
|
193
|
+
| No OPcache | Parses PHP on every request | Enable with `validate_timestamps=0` |
|
|
194
|
+
| Synchronous email sending | Blocks request for 1-5s | Queue with jobs/workers |
|
|
195
|
+
| `file_get_contents` for HTTP | No timeout, no retry | Use Guzzle/Symfony HttpClient |
|
|
196
|
+
| Storing sessions in files | Lock contention under load | Redis/database sessions |
|
|
197
|
+
| Loading entire table | Memory exhaustion | Cursor/chunk processing |
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# PHP 8.4 Strict Typing Checklist
|
|
2
|
+
|
|
3
|
+
## Strict types enforcement
|
|
4
|
+
|
|
5
|
+
### File header
|
|
6
|
+
|
|
7
|
+
Every PHP file must start with:
|
|
8
|
+
|
|
9
|
+
```php
|
|
10
|
+
<?php
|
|
11
|
+
|
|
12
|
+
declare(strict_types=1);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Without this declaration, PHP silently coerces types (e.g., `"123abc"` becomes `123`).
|
|
16
|
+
- With strict types, type mismatches throw `TypeError` immediately.
|
|
17
|
+
|
|
18
|
+
### Method signatures
|
|
19
|
+
|
|
20
|
+
```php
|
|
21
|
+
public function createUser(
|
|
22
|
+
string $name,
|
|
23
|
+
string $email,
|
|
24
|
+
?int $teamId = null,
|
|
25
|
+
): User {
|
|
26
|
+
// ...
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- Type every parameter, return value, and property. No untyped public APIs.
|
|
31
|
+
- Use `?Type` for nullable parameters. Use `mixed` only when genuinely any type is accepted.
|
|
32
|
+
- Use `void` return type when the function returns nothing.
|
|
33
|
+
|
|
34
|
+
## PHP 8.4 type features
|
|
35
|
+
|
|
36
|
+
### Enums
|
|
37
|
+
|
|
38
|
+
```php
|
|
39
|
+
enum Status: string {
|
|
40
|
+
case Active = 'active';
|
|
41
|
+
case Inactive = 'inactive';
|
|
42
|
+
case Suspended = 'suspended';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Usage
|
|
46
|
+
function setStatus(Status $status): void { /* ... */ }
|
|
47
|
+
setStatus(Status::Active);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- Use backed enums (`string` or `int`) for values stored in databases or APIs.
|
|
51
|
+
- Use pure enums when the enum is only used for type discrimination.
|
|
52
|
+
- Enums can implement interfaces and use traits (without properties).
|
|
53
|
+
|
|
54
|
+
### Readonly properties and classes
|
|
55
|
+
|
|
56
|
+
```php
|
|
57
|
+
readonly class UserDTO {
|
|
58
|
+
public function __construct(
|
|
59
|
+
public string $name,
|
|
60
|
+
public string $email,
|
|
61
|
+
public int $age,
|
|
62
|
+
) {}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- Use `readonly` for immutable data transfer objects and value objects.
|
|
67
|
+
- Readonly properties can only be initialized once (in constructor or declaration).
|
|
68
|
+
- Readonly classes make all properties implicitly readonly.
|
|
69
|
+
|
|
70
|
+
### Union and intersection types
|
|
71
|
+
|
|
72
|
+
```php
|
|
73
|
+
function process(string|Stringable $input): int|float { /* ... */ }
|
|
74
|
+
|
|
75
|
+
function handle(Countable&Iterator $collection): void { /* ... */ }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- Union types (`A|B`): value can be any of the listed types.
|
|
79
|
+
- Intersection types (`A&B`): value must satisfy all listed types. Useful for requiring multiple interfaces.
|
|
80
|
+
- DNF types (PHP 8.2+): combine union and intersection: `(A&B)|C`.
|
|
81
|
+
|
|
82
|
+
## PHPStan configuration
|
|
83
|
+
|
|
84
|
+
### Recommended `phpstan.neon`
|
|
85
|
+
|
|
86
|
+
```neon
|
|
87
|
+
parameters:
|
|
88
|
+
level: 8
|
|
89
|
+
paths:
|
|
90
|
+
- src
|
|
91
|
+
- tests
|
|
92
|
+
excludePaths:
|
|
93
|
+
- src/legacy/*
|
|
94
|
+
checkGenericClassInNonGenericObjectType: true
|
|
95
|
+
treatPhpDocTypesAsCertain: false
|
|
96
|
+
reportUnmatchedIgnoredErrors: true
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- Start at level 5 for legacy codebases, target level 8+ for new code.
|
|
100
|
+
- Use baseline file (`phpstan-baseline.neon`) to track pre-existing errors without blocking CI.
|
|
101
|
+
- Run `phpstan analyze` in CI on every PR. Block merge on new errors.
|
|
102
|
+
|
|
103
|
+
### PHPStan generics
|
|
104
|
+
|
|
105
|
+
```php
|
|
106
|
+
/**
|
|
107
|
+
* @template T
|
|
108
|
+
* @param class-string<T> $className
|
|
109
|
+
* @return T
|
|
110
|
+
*/
|
|
111
|
+
function create(string $className): object { /* ... */ }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- Use `@template` annotations for generic types until PHP has native generics.
|
|
115
|
+
- Annotate collections: `@var array<string, User>` instead of `@var array`.
|
|
116
|
+
|
|
117
|
+
## Composer security audit
|
|
118
|
+
|
|
119
|
+
### CI pipeline
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
steps:
|
|
123
|
+
- run: composer install --no-dev --prefer-dist
|
|
124
|
+
- run: composer audit --format=json
|
|
125
|
+
- run: composer outdated --direct --format=json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
- `composer audit` checks installed packages against known vulnerabilities (Packagist advisory database).
|
|
129
|
+
- Run on every CI build. Block deploys on critical/high severity findings.
|
|
130
|
+
- `composer outdated --direct` shows only direct dependency updates needed.
|
|
131
|
+
|
|
132
|
+
### Lock file hygiene
|
|
133
|
+
|
|
134
|
+
- Always commit `composer.lock` for applications. Never commit it for libraries.
|
|
135
|
+
- Run `composer validate --strict` in CI to catch manifest issues.
|
|
136
|
+
- Update dependencies in small batches with test verification between updates.
|
|
137
|
+
- Pin PHP version requirement in `composer.json`: `"php": ">=8.4 <8.5"`.
|
|
138
|
+
|
|
139
|
+
## Error pattern: typed results
|
|
140
|
+
|
|
141
|
+
```php
|
|
142
|
+
readonly class Result {
|
|
143
|
+
private function __construct(
|
|
144
|
+
public readonly bool $ok,
|
|
145
|
+
public readonly mixed $value = null,
|
|
146
|
+
public readonly ?string $error = null,
|
|
147
|
+
) {}
|
|
148
|
+
|
|
149
|
+
public static function success(mixed $value): self {
|
|
150
|
+
return new self(ok: true, value: $value);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public static function failure(string $error): self {
|
|
154
|
+
return new self(ok: false, error: $error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
- Use result objects for expected failures (validation, not-found) instead of exceptions.
|
|
160
|
+
- Exceptions remain for truly exceptional conditions (database down, file system errors).
|
|
161
|
+
- This pattern works well with PHPStan generics: `Result<User>`.
|