cc-codeconductor 0.4.3 → 0.5.0

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.
Files changed (141) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +2642 -226
  3. package/package.json +1 -1
  4. package/presets/agy/skills/evaluation/SKILL.md +6 -0
  5. package/presets/agy/skills/openspec/SKILL.md +32 -0
  6. package/presets/agy/workflows/cc-openspec.md +62 -0
  7. package/presets/agy/workflows/cc-scorecard.md +17 -0
  8. package/presets/claude/commands/cc/openspec.md +144 -0
  9. package/presets/claude/commands/cc/review.md +13 -2
  10. package/presets/claude/commands/cc/scorecard.md +65 -0
  11. package/presets/claude/skills/evaluation/SKILL.md +42 -0
  12. package/presets/claude/skills/openspec/SKILL.md +54 -0
  13. package/presets/codex/AGENTS.md +57 -0
  14. package/presets/cursor/.cursorignore +15 -0
  15. package/presets/cursor/AGENTS.md +504 -0
  16. package/presets/cursor/agents/architect.md +211 -0
  17. package/presets/cursor/agents/complexity-auditor.md +76 -0
  18. package/presets/cursor/agents/contract-builder.md +75 -0
  19. package/presets/cursor/agents/docs.md +180 -0
  20. package/presets/cursor/agents/goal-planner.md +71 -0
  21. package/presets/cursor/agents/implementer.md +161 -0
  22. package/presets/cursor/agents/orchestrator.md +377 -0
  23. package/presets/cursor/agents/repo-explorer.md +100 -0
  24. package/presets/cursor/agents/reviewer.md +237 -0
  25. package/presets/cursor/agents/security-reviewer.md +113 -0
  26. package/presets/cursor/agents/task-coach.md +145 -0
  27. package/presets/cursor/agents/tester.md +241 -0
  28. package/presets/cursor/commands/cc/api-contract.md +58 -0
  29. package/presets/cursor/commands/cc/db-migration.md +58 -0
  30. package/presets/cursor/commands/cc/feature.md +115 -0
  31. package/presets/cursor/commands/cc/fix.md +121 -0
  32. package/presets/cursor/commands/cc/openspec.md +144 -0
  33. package/presets/cursor/commands/cc/pagespeed.md +103 -0
  34. package/presets/cursor/commands/cc/refactor.md +148 -0
  35. package/presets/cursor/commands/cc/review.md +137 -0
  36. package/presets/cursor/commands/cc/scorecard.md +65 -0
  37. package/presets/cursor/commands/cc/tdd-cycle.md +226 -0
  38. package/presets/cursor/commands/cc/test-plan.md +138 -0
  39. package/presets/cursor/rules/behavioral-discipline.mdc +14 -0
  40. package/presets/cursor/rules/context-budget.mdc +12 -0
  41. package/presets/cursor/rules/orchestration.mdc +12 -0
  42. package/presets/cursor/rules/yagni-stdlib.mdc +11 -0
  43. package/presets/cursor/skills/android/SKILL.md +122 -0
  44. package/presets/cursor/skills/api-versioning/SKILL.md +394 -0
  45. package/presets/cursor/skills/astro/SKILL.md +322 -0
  46. package/presets/cursor/skills/auth-token-inspector/SKILL.md +33 -0
  47. package/presets/cursor/skills/code-review/SKILL.md +208 -0
  48. package/presets/cursor/skills/conductor-setup/SKILL.md +127 -0
  49. package/presets/cursor/skills/django-orm/SKILL.md +463 -0
  50. package/presets/cursor/skills/django-testing/SKILL.md +417 -0
  51. package/presets/cursor/skills/django-uv/SKILL.md +409 -0
  52. package/presets/cursor/skills/drizzle-schema-architect/SKILL.md +54 -0
  53. package/presets/cursor/skills/evaluation/SKILL.md +8 -0
  54. package/presets/cursor/skills/fastapi-pydantic-strict/SKILL.md +46 -0
  55. package/presets/cursor/skills/find-skills/SKILL.md +144 -0
  56. package/presets/cursor/skills/jpa-nplusone-detector/SKILL.md +49 -0
  57. package/presets/cursor/skills/jpa-postgres/SKILL.md +626 -0
  58. package/presets/cursor/skills/laravel-specialist/SKILL.md +267 -0
  59. package/presets/cursor/skills/laravel-specialist/references/eloquent.md +351 -0
  60. package/presets/cursor/skills/laravel-specialist/references/livewire.md +512 -0
  61. package/presets/cursor/skills/laravel-specialist/references/queues.md +423 -0
  62. package/presets/cursor/skills/laravel-specialist/references/routing.md +362 -0
  63. package/presets/cursor/skills/laravel-specialist/references/testing.md +522 -0
  64. package/presets/cursor/skills/livewire-alpine-bridge/SKILL.md +39 -0
  65. package/presets/cursor/skills/multi-agent-orchestration/README.md +144 -0
  66. package/presets/cursor/skills/multi-agent-orchestration/SKILL.md +579 -0
  67. package/presets/cursor/skills/multi-agent-orchestration/examples/framework_implementations.py +362 -0
  68. package/presets/cursor/skills/multi-agent-orchestration/examples/orchestration_patterns.py +411 -0
  69. package/presets/cursor/skills/multi-agent-orchestration/scripts/agent_communication.py +334 -0
  70. package/presets/cursor/skills/multi-agent-orchestration/scripts/benchmarking.py +341 -0
  71. package/presets/cursor/skills/multi-agent-orchestration/scripts/workflow_management.py +334 -0
  72. package/presets/cursor/skills/nextjs-typescript/SKILL.md +394 -0
  73. package/presets/cursor/skills/openspec/SKILL.md +52 -0
  74. package/presets/cursor/skills/pagespeed-insights/SKILL.md +445 -0
  75. package/presets/cursor/skills/pagespeed-insights/reference.md +50 -0
  76. package/presets/cursor/skills/pagespeed-perf/SKILL.md +281 -0
  77. package/presets/cursor/skills/php-pro/SKILL.md +210 -0
  78. package/presets/cursor/skills/php-pro/references/async-patterns.md +412 -0
  79. package/presets/cursor/skills/php-pro/references/laravel-patterns.md +377 -0
  80. package/presets/cursor/skills/php-pro/references/modern-php-features.md +323 -0
  81. package/presets/cursor/skills/php-pro/references/symfony-patterns.md +466 -0
  82. package/presets/cursor/skills/php-pro/references/testing-quality.md +466 -0
  83. package/presets/cursor/skills/python/SKILL.md +613 -0
  84. package/presets/cursor/skills/python-django-stack/SKILL.md +500 -0
  85. package/presets/cursor/skills/python-fastapi-stack/SKILL.md +464 -0
  86. package/presets/cursor/skills/security/SKILL.md +384 -0
  87. package/presets/cursor/skills/seo-analytics-injector/SKILL.md +44 -0
  88. package/presets/cursor/skills/spring-auth-auditor/SKILL.md +33 -0
  89. package/presets/cursor/skills/spring-boot-feature/SKILL.md +566 -0
  90. package/presets/cursor/skills/spring-boot-kotlin/SKILL.md +408 -0
  91. package/presets/cursor/skills/spring-boot-testing-strategy/SKILL.md +479 -0
  92. package/presets/cursor/skills/sqlalchemy/SKILL.md +473 -0
  93. package/presets/cursor/skills/tailwind-responsive-auditor/SKILL.md +32 -0
  94. package/presets/cursor/skills/tdd-mutation-tester/SKILL.md +28 -0
  95. package/presets/cursor/skills/testing-tdd/SKILL.md +592 -0
  96. package/presets/cursor/skills/workflow-orchestration-patterns/SKILL.md +98 -0
  97. package/presets/cursor/skills/workflow-orchestration-patterns/references/details.md +223 -0
  98. package/presets/opencode/agents/architect.md +1 -2
  99. package/presets/opencode/agents/complexity-auditor.md +1 -0
  100. package/presets/opencode/agents/contract-builder.md +93 -0
  101. package/presets/opencode/agents/docs.md +1 -2
  102. package/presets/opencode/agents/goal-planner.md +82 -0
  103. package/presets/opencode/agents/implementer.md +9 -2
  104. package/presets/opencode/agents/orchestrator.md +50 -12
  105. package/presets/opencode/agents/repo-explorer.md +0 -1
  106. package/presets/opencode/agents/reviewer.md +23 -2
  107. package/presets/opencode/agents/security-reviewer.md +129 -0
  108. package/presets/opencode/agents/task-coach.md +1 -2
  109. package/presets/opencode/agents/tester.md +1 -2
  110. package/presets/opencode/commands/cc-openspec.md +61 -0
  111. package/presets/opencode/commands/cc-scorecard.md +16 -0
  112. package/presets/opencode/prompts/v0.5.0/architect.md +222 -0
  113. package/presets/opencode/prompts/v0.5.0/complexity-auditor.md +91 -0
  114. package/presets/opencode/prompts/v0.5.0/contract-builder.md +84 -0
  115. package/presets/opencode/prompts/v0.5.0/docs.md +190 -0
  116. package/presets/opencode/prompts/v0.5.0/goal-planner.md +80 -0
  117. package/presets/opencode/prompts/v0.5.0/implementer.md +171 -0
  118. package/presets/opencode/prompts/v0.5.0/orchestrator.md +388 -0
  119. package/presets/opencode/prompts/v0.5.0/repo-explorer.md +111 -0
  120. package/presets/opencode/prompts/v0.5.0/reviewer.md +248 -0
  121. package/presets/opencode/prompts/v0.5.0/security-reviewer.md +123 -0
  122. package/presets/opencode/prompts/v0.5.0/task-coach.md +156 -0
  123. package/presets/opencode/prompts/v0.5.0/tester.md +252 -0
  124. package/presets/opencode/skills/evaluation/SKILL.md +6 -0
  125. package/presets/opencode/skills/openspec/SKILL.md +50 -0
  126. package/presets/templates/BACKLOG.md +33 -0
  127. package/presets/templates/execution-profile.yml +6 -0
  128. package/presets/templates/model-comparison.md +11 -0
  129. package/presets/templates/regression-checklist.yml +10 -0
  130. package/src/presets/manifests/agy.yml +2 -2
  131. package/src/presets/manifests/claude.yml +2 -2
  132. package/src/presets/manifests/codex.yml +2 -2
  133. package/src/presets/manifests/cursor.yml +19 -3
  134. package/src/presets/manifests/gemini.yml +2 -2
  135. package/src/presets/manifests/opencode.yml +2 -2
  136. package/src/presets/models/agy.yml +21 -0
  137. package/src/presets/models/claude.yml +18 -0
  138. package/src/presets/models/codex.yml +18 -0
  139. package/src/presets/models/cursor.yml +39 -9
  140. package/src/presets/models/gemini.yml +18 -0
  141. package/src/presets/models/opencode.yml +18 -0
@@ -0,0 +1,267 @@
1
+ ---
2
+ name: laravel-specialist
3
+ description: Build and configure Laravel 10+ applications, including creating Eloquent models and relationships, implementing Sanctum authentication, configuring Horizon queues, designing RESTful APIs with API resources, and building reactive interfaces with Livewire. Use when creating Laravel models, setting up queue workers, implementing Sanctum auth flows, building Livewire components, optimising Eloquent queries, or writing Pest/PHPUnit tests for Laravel features.
4
+ license: MIT
5
+ metadata:
6
+ author: https://github.com/Jeffallan
7
+ version: "1.1.0"
8
+ domain: backend
9
+ triggers: Laravel, Eloquent, PHP framework, Laravel API, Artisan, Blade templates, Laravel queues, Livewire, Laravel testing, Sanctum, Horizon
10
+ role: specialist
11
+ scope: implementation
12
+ output-format: code
13
+ related-skills: fullstack-guardian, test-master, devops-engineer, security-reviewer
14
+ paths:
15
+ - "**/*.php"
16
+ - "**/artisan"
17
+ ---
18
+
19
+ # Laravel Specialist
20
+
21
+ Senior Laravel specialist with deep expertise in Laravel 10+, Eloquent ORM, and modern PHP 8.2+ development.
22
+
23
+ ## Core Workflow
24
+
25
+ 1. **Analyse requirements** — Identify models, relationships, APIs, and queue needs
26
+ 2. **Design architecture** — Plan database schema, service layers, and job queues
27
+ 3. **Implement models** — Create Eloquent models with relationships, scopes, and casts; run `php artisan make:model` and verify with `php artisan migrate:status`
28
+ 4. **Build features** — Develop controllers, services, API resources, and jobs; run `php artisan route:list` to verify routing
29
+ 5. **Test thoroughly** — Write feature and unit tests; run `php artisan test` before considering any step complete (target >85% coverage)
30
+
31
+ ## Reference Guide
32
+
33
+ Load detailed guidance based on context:
34
+
35
+ | Topic | Reference | Load When |
36
+ |-------|-----------|-----------|
37
+ | Eloquent ORM | `references/eloquent.md` | Models, relationships, scopes, query optimization |
38
+ | Routing & APIs | `references/routing.md` | Routes, controllers, middleware, API resources |
39
+ | Queue System | `references/queues.md` | Jobs, workers, Horizon, failed jobs, batching |
40
+ | Livewire | `references/livewire.md` | Components, wire:model, actions, real-time |
41
+ | Testing | `references/testing.md` | Feature tests, factories, mocking, Pest PHP |
42
+
43
+ ## Constraints
44
+
45
+ ### MUST DO
46
+ - Use PHP 8.2+ features (readonly, enums, typed properties)
47
+ - Type hint all method parameters and return types
48
+ - Use Eloquent relationships properly (avoid N+1 with eager loading)
49
+ - Implement API resources for transforming data
50
+ - Queue long-running tasks
51
+ - Write comprehensive tests (>85% coverage)
52
+ - Use service containers and dependency injection
53
+ - Follow PSR-12 coding standards
54
+
55
+ ### MUST NOT DO
56
+ - Use raw queries without protection (SQL injection)
57
+ - Skip eager loading (causes N+1 problems)
58
+ - Store sensitive data unencrypted
59
+ - Mix business logic in controllers
60
+ - Hardcode configuration values
61
+ - Skip validation on user input
62
+ - Use deprecated Laravel features
63
+ - Ignore queue failures
64
+
65
+ ## Code Templates
66
+
67
+ Use these as starting points for every implementation.
68
+
69
+ ### Eloquent Model
70
+
71
+ ```php
72
+ <?php
73
+
74
+ declare(strict_types=1);
75
+
76
+ namespace App\Models;
77
+
78
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
79
+ use Illuminate\Database\Eloquent\Model;
80
+ use Illuminate\Database\Eloquent\Relations\BelongsTo;
81
+ use Illuminate\Database\Eloquent\Relations\HasMany;
82
+ use Illuminate\Database\Eloquent\SoftDeletes;
83
+
84
+ final class Post extends Model
85
+ {
86
+ use HasFactory, SoftDeletes;
87
+
88
+ protected $fillable = ['title', 'body', 'status', 'user_id'];
89
+
90
+ protected $casts = [
91
+ 'status' => PostStatus::class, // backed enum
92
+ 'published_at' => 'immutable_datetime',
93
+ ];
94
+
95
+ // Relationships — always eager-load via ::with() at call site
96
+ public function author(): BelongsTo
97
+ {
98
+ return $this->belongsTo(User::class, 'user_id');
99
+ }
100
+
101
+ public function comments(): HasMany
102
+ {
103
+ return $this->hasMany(Comment::class);
104
+ }
105
+
106
+ // Local scope
107
+ public function scopePublished(Builder $query): Builder
108
+ {
109
+ return $query->where('status', PostStatus::Published);
110
+ }
111
+ }
112
+ ```
113
+
114
+ ### Migration
115
+
116
+ ```php
117
+ <?php
118
+
119
+ use Illuminate\Database\Migrations\Migration;
120
+ use Illuminate\Database\Schema\Blueprint;
121
+ use Illuminate\Support\Facades\Schema;
122
+
123
+ return new class extends Migration
124
+ {
125
+ public function up(): void
126
+ {
127
+ Schema::create('posts', function (Blueprint $table): void {
128
+ $table->id();
129
+ $table->foreignId('user_id')->constrained()->cascadeOnDelete();
130
+ $table->string('title');
131
+ $table->text('body');
132
+ $table->string('status')->default('draft');
133
+ $table->timestamp('published_at')->nullable();
134
+ $table->softDeletes();
135
+ $table->timestamps();
136
+ });
137
+ }
138
+
139
+ public function down(): void
140
+ {
141
+ Schema::dropIfExists('posts');
142
+ }
143
+ };
144
+ ```
145
+
146
+ ### API Resource
147
+
148
+ ```php
149
+ <?php
150
+
151
+ declare(strict_types=1);
152
+
153
+ namespace App\Http\Resources;
154
+
155
+ use Illuminate\Http\Request;
156
+ use Illuminate\Http\Resources\Json\JsonResource;
157
+
158
+ final class PostResource extends JsonResource
159
+ {
160
+ public function toArray(Request $request): array
161
+ {
162
+ return [
163
+ 'id' => $this->id,
164
+ 'title' => $this->title,
165
+ 'body' => $this->body,
166
+ 'status' => $this->status->value,
167
+ 'published_at' => $this->published_at?->toIso8601String(),
168
+ 'author' => new UserResource($this->whenLoaded('author')),
169
+ 'comments' => CommentResource::collection($this->whenLoaded('comments')),
170
+ ];
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### Queued Job
176
+
177
+ ```php
178
+ <?php
179
+
180
+ declare(strict_types=1);
181
+
182
+ namespace App\Jobs;
183
+
184
+ use App\Models\Post;
185
+ use Illuminate\Bus\Queueable;
186
+ use Illuminate\Contracts\Queue\ShouldQueue;
187
+ use Illuminate\Foundation\Bus\Dispatchable;
188
+ use Illuminate\Queue\InteractsWithQueue;
189
+ use Illuminate\Queue\SerializesModels;
190
+
191
+ final class PublishPost implements ShouldQueue
192
+ {
193
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
194
+
195
+ public int $tries = 3;
196
+ public int $backoff = 60;
197
+
198
+ public function __construct(
199
+ private readonly Post $post,
200
+ ) {}
201
+
202
+ public function handle(): void
203
+ {
204
+ $this->post->update([
205
+ 'status' => PostStatus::Published,
206
+ 'published_at' => now(),
207
+ ]);
208
+ }
209
+
210
+ public function failed(\Throwable $e): void
211
+ {
212
+ // Log or notify — never silently swallow failures
213
+ logger()->error('PublishPost failed', ['post' => $this->post->id, 'error' => $e->getMessage()]);
214
+ }
215
+ }
216
+ ```
217
+
218
+ ### Feature Test (Pest)
219
+
220
+ ```php
221
+ <?php
222
+
223
+ use App\Models\Post;
224
+ use App\Models\User;
225
+
226
+ it('returns a published post for authenticated users', function (): void {
227
+ $user = User::factory()->create();
228
+ $post = Post::factory()->published()->for($user, 'author')->create();
229
+
230
+ $response = $this->actingAs($user)
231
+ ->getJson("/api/posts/{$post->id}");
232
+
233
+ $response->assertOk()
234
+ ->assertJsonPath('data.status', 'published')
235
+ ->assertJsonPath('data.author.id', $user->id);
236
+ });
237
+
238
+ it('queues a publish job when a draft is submitted', function (): void {
239
+ Queue::fake();
240
+ $user = User::factory()->create();
241
+ $post = Post::factory()->draft()->for($user, 'author')->create();
242
+
243
+ $this->actingAs($user)
244
+ ->postJson("/api/posts/{$post->id}/publish")
245
+ ->assertAccepted();
246
+
247
+ Queue::assertPushed(PublishPost::class, fn ($job) => $job->post->is($post));
248
+ });
249
+ ```
250
+
251
+ ## Validation Checkpoints
252
+
253
+ Run these at each workflow stage to confirm correctness before proceeding:
254
+
255
+ | Stage | Command | Expected Result |
256
+ |-------|---------|-----------------|
257
+ | After migration | `php artisan migrate:status` | All migrations show `Ran` |
258
+ | After routing | `php artisan route:list --path=api` | New routes appear with correct verbs |
259
+ | After job dispatch | `php artisan queue:work --once` | Job processes without exception |
260
+ | After implementation | `php artisan test --coverage` | >85% coverage, 0 failures |
261
+ | Before PR | `./vendor/bin/pint --test` | PSR-12 linting passes |
262
+
263
+ ## Knowledge Reference
264
+
265
+ Laravel 10+, Eloquent ORM, PHP 8.2+, API resources, Sanctum/Passport, queues, Horizon, Livewire, Inertia, Octane, Pest/PHPUnit, Redis, broadcasting, events/listeners, notifications, task scheduling
266
+
267
+ [Documentation](https://jeffallan.github.io/claude-skills/skills/backend/laravel-specialist/)
@@ -0,0 +1,351 @@
1
+ # Eloquent ORM
2
+
3
+ ## Model Patterns
4
+
5
+ ```php
6
+ <?php
7
+
8
+ namespace App\Models;
9
+
10
+ use Illuminate\Database\Eloquent\Model;
11
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
12
+ use Illuminate\Database\Eloquent\SoftDeletes;
13
+ use Illuminate\Database\Eloquent\Casts\Attribute;
14
+
15
+ class Post extends Model
16
+ {
17
+ use HasFactory, SoftDeletes;
18
+
19
+ protected $fillable = [
20
+ 'title',
21
+ 'slug',
22
+ 'content',
23
+ 'published_at',
24
+ 'user_id',
25
+ ];
26
+
27
+ protected $casts = [
28
+ 'published_at' => 'datetime',
29
+ 'metadata' => 'array',
30
+ 'is_featured' => 'boolean',
31
+ ];
32
+
33
+ // Accessor using new Attribute syntax (Laravel 9+)
34
+ protected function title(): Attribute
35
+ {
36
+ return Attribute::make(
37
+ get: fn (string $value) => ucfirst($value),
38
+ set: fn (string $value) => strtolower($value),
39
+ );
40
+ }
41
+
42
+ // Mutator for computed property
43
+ protected function excerpt(): Attribute
44
+ {
45
+ return Attribute::make(
46
+ get: fn () => str($this->content)->limit(100),
47
+ );
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## Relationships
53
+
54
+ ```php
55
+ // One-to-Many
56
+ class User extends Model
57
+ {
58
+ public function posts(): HasMany
59
+ {
60
+ return $this->hasMany(Post::class);
61
+ }
62
+
63
+ public function latestPost(): HasOne
64
+ {
65
+ return $this->hasOne(Post::class)->latestOfMany();
66
+ }
67
+
68
+ public function oldestPost(): HasOne
69
+ {
70
+ return $this->hasOne(Post::class)->oldestOfMany();
71
+ }
72
+ }
73
+
74
+ class Post extends Model
75
+ {
76
+ public function user(): BelongsTo
77
+ {
78
+ return $this->belongsTo(User::class);
79
+ }
80
+
81
+ // Inverse relationship
82
+ public function comments(): HasMany
83
+ {
84
+ return $this->hasMany(Comment::class);
85
+ }
86
+ }
87
+
88
+ // Many-to-Many with Pivot
89
+ class User extends Model
90
+ {
91
+ public function roles(): BelongsToMany
92
+ {
93
+ return $this->belongsToMany(Role::class)
94
+ ->withPivot('expires_at', 'assigned_by')
95
+ ->withTimestamps()
96
+ ->using(RoleUser::class); // Custom pivot model
97
+ }
98
+ }
99
+
100
+ // Has Many Through
101
+ class Country extends Model
102
+ {
103
+ public function posts(): HasManyThrough
104
+ {
105
+ return $this->hasManyThrough(Post::class, User::class);
106
+ }
107
+ }
108
+
109
+ // Polymorphic Relations
110
+ class Image extends Model
111
+ {
112
+ public function imageable(): MorphTo
113
+ {
114
+ return $this->morphTo();
115
+ }
116
+ }
117
+
118
+ class Post extends Model
119
+ {
120
+ public function images(): MorphMany
121
+ {
122
+ return $this->morphMany(Image::class, 'imageable');
123
+ }
124
+ }
125
+
126
+ // Many-to-Many Polymorphic
127
+ class Tag extends Model
128
+ {
129
+ public function posts(): MorphToMany
130
+ {
131
+ return $this->morphedByMany(Post::class, 'taggable');
132
+ }
133
+
134
+ public function videos(): MorphToMany
135
+ {
136
+ return $this->morphedByMany(Video::class, 'taggable');
137
+ }
138
+ }
139
+ ```
140
+
141
+ ## Query Scopes
142
+
143
+ ```php
144
+ class Post extends Model
145
+ {
146
+ // Local scope
147
+ public function scopePublished($query): void
148
+ {
149
+ $query->whereNotNull('published_at')
150
+ ->where('published_at', '<=', now());
151
+ }
152
+
153
+ public function scopePopular($query, int $threshold = 100): void
154
+ {
155
+ $query->where('views', '>=', $threshold);
156
+ }
157
+
158
+ // Global scope
159
+ protected static function booted(): void
160
+ {
161
+ static::addGlobalScope('active', function ($query) {
162
+ $query->where('status', 'active');
163
+ });
164
+ }
165
+ }
166
+
167
+ // Usage
168
+ $posts = Post::published()->popular(500)->get();
169
+
170
+ // Custom Scope Class
171
+ namespace App\Models\Scopes;
172
+
173
+ use Illuminate\Database\Eloquent\Builder;
174
+ use Illuminate\Database\Eloquent\Model;
175
+ use Illuminate\Database\Eloquent\Scope;
176
+
177
+ class AncientScope implements Scope
178
+ {
179
+ public function apply(Builder $builder, Model $model): void
180
+ {
181
+ $builder->where('created_at', '<', now()->subYears(10));
182
+ }
183
+ }
184
+
185
+ // Apply in model
186
+ protected static function booted(): void
187
+ {
188
+ static::addGlobalScope(new AncientScope);
189
+ }
190
+ ```
191
+
192
+ ## Custom Casts
193
+
194
+ ```php
195
+ namespace App\Casts;
196
+
197
+ use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
198
+
199
+ class Money implements CastsAttributes
200
+ {
201
+ public function get($model, string $key, $value, array $attributes): float
202
+ {
203
+ return $value / 100; // Store cents, return dollars
204
+ }
205
+
206
+ public function set($model, string $key, $value, array $attributes): int
207
+ {
208
+ return (int) ($value * 100);
209
+ }
210
+ }
211
+
212
+ // In model
213
+ protected $casts = [
214
+ 'price' => Money::class,
215
+ ];
216
+ ```
217
+
218
+ ## Query Optimization
219
+
220
+ ```php
221
+ // Eager Loading (prevent N+1)
222
+ $posts = Post::with(['user', 'comments.user'])->get();
223
+
224
+ // Lazy Eager Loading
225
+ $posts = Post::all();
226
+ $posts->load('user');
227
+
228
+ // Eager Load with Constraints
229
+ $users = User::with(['posts' => function ($query) {
230
+ $query->where('published', true)->orderBy('created_at', 'desc');
231
+ }])->get();
232
+
233
+ // Count relationships efficiently
234
+ $posts = Post::withCount('comments')->get();
235
+ foreach ($posts as $post) {
236
+ echo $post->comments_count;
237
+ }
238
+
239
+ // Exists checks
240
+ $users = User::withExists('posts')->get();
241
+
242
+ // Chunk for large datasets
243
+ Post::chunk(100, function ($posts) {
244
+ foreach ($posts as $post) {
245
+ // Process post
246
+ }
247
+ });
248
+
249
+ // Lazy collection for memory efficiency
250
+ Post::lazy()->each(function ($post) {
251
+ // Process one at a time
252
+ });
253
+ ```
254
+
255
+ ## Model Events
256
+
257
+ ```php
258
+ class Post extends Model
259
+ {
260
+ protected static function booted(): void
261
+ {
262
+ static::creating(function ($post) {
263
+ $post->slug = str($post->title)->slug();
264
+ });
265
+
266
+ static::updating(function ($post) {
267
+ if ($post->isDirty('title')) {
268
+ $post->slug = str($post->title)->slug();
269
+ }
270
+ });
271
+
272
+ static::deleted(function ($post) {
273
+ $post->images()->delete();
274
+ });
275
+ }
276
+ }
277
+
278
+ // Using Observers
279
+ namespace App\Observers;
280
+
281
+ class PostObserver
282
+ {
283
+ public function creating(Post $post): void
284
+ {
285
+ $post->user_id = auth()->id();
286
+ }
287
+
288
+ public function updated(Post $post): void
289
+ {
290
+ cache()->forget("post.{$post->id}");
291
+ }
292
+ }
293
+
294
+ // Register in AppServiceProvider
295
+ use App\Models\Post;
296
+ use App\Observers\PostObserver;
297
+
298
+ public function boot(): void
299
+ {
300
+ Post::observe(PostObserver::class);
301
+ }
302
+ ```
303
+
304
+ ## Advanced Queries
305
+
306
+ ```php
307
+ // Subqueries
308
+ $users = User::select(['id', 'name'])
309
+ ->addSelect(['latest_post_title' => Post::select('title')
310
+ ->whereColumn('user_id', 'users.id')
311
+ ->latest()
312
+ ->limit(1)
313
+ ])->get();
314
+
315
+ // When conditional queries
316
+ $posts = Post::query()
317
+ ->when($search, fn ($query) => $query->where('title', 'like', "%{$search}%"))
318
+ ->when($category, fn ($query) => $query->where('category_id', $category))
319
+ ->get();
320
+
321
+ // Database transactions
322
+ DB::transaction(function () {
323
+ $user = User::create([...]);
324
+ $user->profile()->create([...]);
325
+ $user->assignRole('member');
326
+ });
327
+
328
+ // Pessimistic locking
329
+ $user = User::where('id', 1)->lockForUpdate()->first();
330
+
331
+ // Upserts
332
+ User::upsert(
333
+ [
334
+ ['email' => 'john@example.com', 'name' => 'John'],
335
+ ['email' => 'jane@example.com', 'name' => 'Jane'],
336
+ ],
337
+ ['email'], // Unique columns
338
+ ['name'] // Columns to update
339
+ );
340
+ ```
341
+
342
+ ## Performance Tips
343
+
344
+ 1. **Always eager load relationships** - Avoid N+1 queries
345
+ 2. **Use chunking for large datasets** - Prevent memory exhaustion
346
+ 3. **Index foreign keys** - Speed up joins
347
+ 4. **Use select() to limit columns** - Reduce data transfer
348
+ 5. **Cache expensive queries** - Use Redis/Memcached
349
+ 6. **Use database indexing** - Add indexes in migrations
350
+ 7. **Avoid using model events for heavy operations** - Use queues instead
351
+ 8. **Use lazy collections** - For processing large datasets