detect-unnecessary-loops

Detects unnecessary loop patterns in PHP code. Finds nested loop inefficiency, redundant iterations, in-loop operations that could be batched, loop invariant code.

59 stars

Best use case

detect-unnecessary-loops is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Detects unnecessary loop patterns in PHP code. Finds nested loop inefficiency, redundant iterations, in-loop operations that could be batched, loop invariant code.

Teams using detect-unnecessary-loops should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/detect-unnecessary-loops/SKILL.md --create-dirs "https://raw.githubusercontent.com/dykyi-roman/awesome-claude-code/main/skills/detect-unnecessary-loops/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/detect-unnecessary-loops/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How detect-unnecessary-loops Compares

Feature / Agentdetect-unnecessary-loopsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Detects unnecessary loop patterns in PHP code. Finds nested loop inefficiency, redundant iterations, in-loop operations that could be batched, loop invariant code.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Unnecessary Loop Detection

Analyze PHP code for inefficient loop patterns.

## Detection Patterns

### 1. Nested Loop Inefficiency

```php
// O(n*m): Nested search
foreach ($users as $user) {
    foreach ($orders as $order) {
        if ($order->getUserId() === $user->getId()) {
            // Found order for user
        }
    }
}

// O(n): Use indexed lookup
$ordersByUser = [];
foreach ($orders as $order) {
    $ordersByUser[$order->getUserId()][] = $order;
}
foreach ($users as $user) {
    $userOrders = $ordersByUser[$user->getId()] ?? [];
}
```

### 2. Redundant Iterations

```php
// REDUNDANT: Multiple passes
$filtered = [];
foreach ($items as $item) {
    if ($item->isActive()) {
        $filtered[] = $item;
    }
}
$transformed = [];
foreach ($filtered as $item) {
    $transformed[] = $item->toArray();
}
$sorted = usort($transformed, fn($a, $b) => $a['name'] <=> $b['name']);

// BETTER: Single pass + built-in sort
$result = [];
foreach ($items as $item) {
    if ($item->isActive()) {
        $result[] = $item->toArray();
    }
}
usort($result, fn($a, $b) => $a['name'] <=> $b['name']);
```

### 3. In-Loop Operations That Could Be Batched

```php
// SLOW: Individual inserts
foreach ($users as $user) {
    $this->repository->save($user);
    $this->em->flush(); // Flush each iteration
}

// FAST: Batch insert
foreach ($users as $user) {
    $this->em->persist($user);
}
$this->em->flush(); // Single flush

// SLOW: Individual API calls
foreach ($items as $item) {
    $this->api->update($item); // HTTP call per item
}

// FAST: Batch API call
$this->api->updateBatch($items);
```

### 4. Loop Invariant Code

```php
// INEFFICIENT: Repeated computation
foreach ($items as $item) {
    $config = $this->loadConfig(); // Same result each iteration
    $now = new DateTime(); // Same time each iteration
    $taxRate = $this->getTaxRate($country); // Constant
    process($item, $config, $now, $taxRate);
}

// FIXED: Hoist invariants
$config = $this->loadConfig();
$now = new DateTime();
$taxRate = $this->getTaxRate($country);
foreach ($items as $item) {
    process($item, $config, $now, $taxRate);
}
```

### 5. Array Functions vs Loops

```php
// VERBOSE: Manual filter
$active = [];
foreach ($users as $user) {
    if ($user->isActive()) {
        $active[] = $user;
    }
}

// CLEANER: array_filter
$active = array_filter($users, fn($u) => $u->isActive());

// VERBOSE: Manual map
$names = [];
foreach ($users as $user) {
    $names[] = $user->getName();
}

// CLEANER: array_map
$names = array_map(fn($u) => $u->getName(), $users);

// VERBOSE: Manual reduce
$total = 0;
foreach ($orders as $order) {
    $total += $order->getAmount();
}

// CLEANER: array_reduce
$total = array_reduce($orders, fn($sum, $o) => $sum + $o->getAmount(), 0);
```

### 6. Early Exit Missing

```php
// INEFFICIENT: Continues after finding
foreach ($users as $user) {
    if ($user->getId() === $targetId) {
        $found = $user;
    }
}

// EFFICIENT: Break when found
foreach ($users as $user) {
    if ($user->getId() === $targetId) {
        $found = $user;
        break;
    }
}

// BETTER: Use array_filter/first or collection method
$found = $collection->first(fn($u) => $u->getId() === $targetId);
```

### 7. Counting in Loop

```php
// SLOW: strlen in loop condition
for ($i = 0; $i < strlen($string); $i++) {
    // strlen called each iteration
}

// FAST: Cache length
$len = strlen($string);
for ($i = 0; $i < $len; $i++) {
    // ...
}

// SLOW: count() in loop
for ($i = 0; $i < count($array); $i++) {
    // count called each iteration
}
```

### 8. Unnecessary array_merge

```php
// SLOW: array_merge in loop creates new array each time
$result = [];
foreach ($batches as $batch) {
    $result = array_merge($result, $batch);
}

// FAST: Spread operator
$result = array_merge(...$batches);

// FAST: Direct append
$result = [];
foreach ($batches as $batch) {
    foreach ($batch as $item) {
        $result[] = $item;
    }
}
```

## Grep Patterns

```bash
# Nested foreach
Grep: "foreach.*foreach" --glob "**/*.php"

# flush() in loop
Grep: "foreach.*->flush\(\)" --glob "**/*.php"

# strlen/count in loop condition
Grep: "for\s*\([^;]+;\s*\$\w+\s*<\s*(strlen|count)\(" --glob "**/*.php"

# array_merge in loop
Grep: "foreach.*array_merge" --glob "**/*.php"
```

## Complexity Comparison

| Pattern | Before | After |
|---------|--------|-------|
| Nested loop search | O(n*m) | O(n+m) with index |
| Multiple passes | O(3n) | O(n) single pass |
| In-loop flush | n DB round trips | 1 round trip |
| strlen in condition | O(n²) | O(n) |

## Severity Classification

| Pattern | Severity |
|---------|----------|
| Nested loop O(n²) | 🔴 Critical |
| Individual DB operations in loop | 🔴 Critical |
| Loop invariant code | 🟠 Major |
| Multiple array passes | 🟠 Major |
| strlen in condition | 🟡 Minor |
| Verbose vs array_* | 🟢 Suggestion |

## Output Format

```markdown
### Unnecessary Loop: [Description]

**Severity:** 🔴/🟠/🟡
**Location:** `file.php:line`
**Current Complexity:** O(n²)
**Optimized Complexity:** O(n)

**Issue:**
[Description of the inefficient pattern]

**Code:**
```php
// Inefficient loop
```

**Optimization:**
```php
// Optimized version
```

**Improvement:**
For 1000 items: 1,000,000 ops → 2,000 ops
```

Related Skills

find-infinite-loops

59
from dykyi-roman/awesome-claude-code

Detects infinite loop risks in PHP code. Finds missing break conditions, incorrect loop variables, unbounded recursion, circular references.

detect-test-smells

59
from dykyi-roman/awesome-claude-code

Detects test antipatterns and code smells in PHP test suites. Identifies 15 smells (Logic in Test, Mock Overuse, Fragile Tests, Mystery Guest, etc.) with fix recommendations and refactoring patterns for testability.

detect-docker-antipatterns

59
from dykyi-roman/awesome-claude-code

Detects Docker antipatterns in PHP projects. Identifies layer ordering issues, cache invalidation, bloated images, and configuration smells.

detect-code-smells

59
from dykyi-roman/awesome-claude-code

Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.

detect-ci-antipatterns

59
from dykyi-roman/awesome-claude-code

Detects CI/CD antipatterns in pipeline configurations. Identifies slow pipelines, security issues, maintenance problems, and provides remediation guidance.

detect-architecture-pattern

59
from dykyi-roman/awesome-claude-code

Detects architectural patterns (MVC, DDD, Hexagonal, CQRS, Layered, Event Sourcing, Microservice) from namespace structure, interface placement, and dependency direction. Outputs confidence score per pattern.

yii-knowledge

59
from dykyi-roman/awesome-claude-code

Yii framework knowledge base. Provides Yii3 modular architecture, DDD integration, PSR-7/PSR-15 compliance, persistence, DI, security (RBAC, auth), event system (PSR-14), queue/jobs, infrastructure components (cache, rate limiter, HTTP client), testing, and antipatterns for Yii PHP projects.

troubleshooting-template

59
from dykyi-roman/awesome-claude-code

Generates troubleshooting guides and FAQ sections for PHP projects. Creates problem-solution documentation.

trace-request-lifecycle

59
from dykyi-roman/awesome-claude-code

Traces full request lifecycle from Router through Middleware, Controller, UseCase, Repository to Response. Documents HTTP methods, routes, middleware stack, response codes, and error handling paths.

trace-data-transformation

59
from dykyi-roman/awesome-claude-code

Maps data transformation chains — Request DTO to Command to Entity to Response DTO. Identifies mappers, serializers, type conversions, and data loss points across layer boundaries.

testing-knowledge

59
from dykyi-roman/awesome-claude-code

Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.

task-progress-knowledge

59
from dykyi-roman/awesome-claude-code

TaskCreate pattern guidelines for progress tracking in coordinator agents