---
title: "Selector Project"
description: "Derafu Selector"
type: "docs"
category: "doc"
tags: [php]
authors: [Anonymous]
date: "2026-08-24"
last_update: "2026-08-24"
time_minutes: 1
draft: false
unlisted: false
url: "https://www.derafu.dev/docs/data/selector"
---

# Derafu Selector



---

## Introduction

Elegant Data Structure Navigation for PHP

# Elegant Data Structure Navigation for PHP

![GitHub last commit](https://img.shields.io/github/last-commit/derafu/selector/main)
![CI Workflow](https://github.com/derafu/selector/actions/workflows/ci.yml/badge.svg?branch=main&amp;event=push)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/derafu/selector)
![GitHub Issues](https://img.shields.io/github/issues-raw/derafu/selector)
![Total Downloads](https://poser.pugx.org/derafu/selector/downloads)
![Monthly Downloads](https://poser.pugx.org/derafu/selector/d/monthly)

A powerful, flexible, and efficient PHP library for querying, extracting, and modifying complex data structures using a **declarative selector syntax**.

## Why Derafu\Selector?

### 🚀 **A Smarter Way to Work with Data Structures**

Traditional PHP methods for accessing and modifying nested data structures (`$array[&#039;key&#039;][&#039;subkey&#039;]`) are:

- **Error-prone**: Risk of `Undefined index` or `Trying to access array offset on null` errors.
- **Verbose &amp; Hard to Read**: Requires multiple `isset()` checks and deep nesting.
- **Limited**: No built-in support for **filters, conditional selectors, or transformations**.

### 🔥 **What Makes Derafu\Selector Unique?**

| Feature                              | Derafu\Selector | PHP Native (`isset()` &amp; loops) | Other Libraries |
|--------------------------------------|-----------------|--------------------------------|-----------------|
| **Dot-Notation Access**              | ✅ Yes          | ❌ No                          | ⚠️ Limited      |
| **Nested Selection with Conditions** | ✅ Yes          | ❌ No                          | ⚠️ Limited      |
| **Dynamic Path Resolution**          | ✅ Yes          | ❌ No                          | ⚠️ Varies       |
| **Auto-Handles Undefined Keys**      | ✅ Yes          | ❌ No                          | ⚠️ Partial      |
| **Filters &amp; Expressions**            | ✅ Yes          | ❌ No                          | ⚠️ Partial      |

---

## 🔍 Overview

Derafu Selector gives you a clean, robust way to work with nested arrays and objects in PHP. It eliminates the need for repetitive null checks, nested loops, and error-prone array access, replacing them with a powerful, declarative syntax.

```php
// Instead of this:
$userName = isset($data[&#039;user&#039;]) &amp;&amp; isset($data[&#039;user&#039;][&#039;profile&#039;]) &amp;&amp; isset($data[&#039;user&#039;][&#039;profile&#039;][&#039;name&#039;])
    ? $data[&#039;user&#039;][&#039;profile&#039;][&#039;name&#039;]
    : null;

// Simply write this:
$userName = Selector::get($data, &#039;user.profile.name&#039;);

// Or even filter arrays with conditions:
$adminEmail = Selector::get($data, &#039;users[role=admin:email]&#039;);
```

## ✨ Features

{.list-unstyled}
- ✅ **Powerful Dot Notation** - Access deeply nested data with simple paths (`user.profile.name`).
- ✅ **Array Access** - Use numeric indices to access array elements (`items[0].name`).
- ✅ **Filtering** - Find array elements by key/value conditions (`users[id=123:email]`).
- ✅ **Conditional Logic** - Use ternary-like expressions (`((type) = &quot;admin&quot; ? (admin_role) : (user_role))`).
- ✅ **Multiple Query Languages** - Support for native syntax, JSONPath, and JMESPath.
- ✅ **Error Handling** - No more &quot;undefined index&quot; or &quot;trying to access array offset on null&quot; errors.
- ✅ **Write Support** - Modify data structures with the same powerful syntax.
- ✅ **Zero Dependencies** - Lightweight core with optional support for JSONPath and JMESPath.

---

## 📦 Installation

```bash
composer require derafu/selector
```

## 🚀 Quick Start

### Reading Data

```php
use Derafu\Selector\Selector;

$data = [
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John Doe&#039;,
        &#039;email&#039; =&gt; &#039;john@example.com&#039;,
        &#039;profile&#039; =&gt; [
            &#039;avatar&#039; =&gt; &#039;john.jpg&#039;,
            &#039;settings&#039; =&gt; [&#039;theme&#039; =&gt; &#039;dark&#039;, &#039;notifications&#039; =&gt; true],
        ],
        &#039;roles&#039; =&gt; [&#039;editor&#039;, &#039;contributor&#039;],
    ],
    &#039;products&#039; =&gt; [
        [&#039;id&#039; =&gt; 101, &#039;name&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999],
        [&#039;id&#039; =&gt; 102, &#039;name&#039; =&gt; &#039;Phone&#039;, &#039;price&#039; =&gt; 699],
        [&#039;id&#039; =&gt; 103, &#039;name&#039; =&gt; &#039;Headphones&#039;, &#039;price&#039; =&gt; 149],
    ],
];

// Simple property access.
$name = Selector::get($data, &#039;user.name&#039;);  // &quot;John Doe&quot;

// Nested properties.
$theme = Selector::get($data, &#039;user.profile.settings.theme&#039;);  // &quot;dark&quot;

// Array elements by index.
$firstRole = Selector::get($data, &#039;user.roles[0]&#039;);  // &quot;editor&quot;

// Array filtering.
$laptop = Selector::get($data, &#039;products[id=101:name]&#039;);  // &quot;Laptop&quot;

// With default values.
$address = Selector::get($data, &#039;user.address&#039;, &#039;Not specified&#039;);  // &quot;Not specified&quot;

// Check if a path exists.
$hasAvatar = Selector::has($data, &#039;user.profile.avatar&#039;);  // true
```

### Writing Data

```php
// Set a simple value.
Selector::set($data, &#039;user.address&#039;, &#039;123 Main St&#039;);

// Create nested structures automatically.
Selector::set($data, &#039;user.profile.settings.language&#039;, &#039;en&#039;);

// Update array elements.
Selector::set($data, &#039;products[id=101:price]&#039;, 899);

// Remove a value.
Selector::clear($data, &#039;user.profile.settings.notifications&#039;);
```

### Advanced Selector Syntax

```php
// Conditional selectors.
$role = Selector::get($data, &#039;((user.type) = &quot;admin&quot; ? (admin_role) : (user_role))&#039;);

// String concatenation.
$greeting = Selector::get($data, &#039;&quot;Hello, &quot;(user.name)&quot;!&quot;&#039;);  // &quot;Hello, John Doe!&quot;

// OR operator for fallbacks.
$contactInfo = Selector::get($data, &#039;user.phone||user.email&#039;);  // Uses email if phone is null

// JSONPath integration.
$expensiveProducts = Selector::get($data, &#039;$.products[?(@.price &gt; 500)].name&#039;);  // [&quot;Laptop&quot;, &quot;Phone&quot;]

// JMESPath integration.
$productNames = Selector::get($data, &#039;jmespath:products[*].name&#039;);  // [&quot;Laptop&quot;, &quot;Phone&quot;, &quot;Headphones&quot;]
```




---

## Basic Usage

Basic Usage

# Basic Usage

This guide covers the fundamentals of working with Derafu Selector for navigating and manipulating data structures.

## Reading Data

The most common operation with Selector is to read values from complex data structures. The `get()` method provides a clean, safe way to extract values without worry about undefined indices or null values.

### Basic Dot Notation

```php
use Derafu\Selector\Selector;

$data = [
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John Doe&#039;,
        &#039;email&#039; =&gt; &#039;john@example.com&#039;,
        &#039;profile&#039; =&gt; [
            &#039;avatar&#039; =&gt; &#039;john.jpg&#039;,
        ],
    ],
];

// Simple property access.
$name = Selector::get($data, &#039;user.name&#039;);  // &quot;John Doe&quot;

// Nested properties.
$avatar = Selector::get($data, &#039;user.profile.avatar&#039;);  // &quot;john.jpg&quot;

// Non-existent path returns null.
$age = Selector::get($data, &#039;user.age&#039;);  // null
```

### Default Values

You can provide a default value that will be returned if the selector path doesn&#039;t exist:

```php
// With default value
$address = Selector::get($data, &#039;user.address&#039;, &#039;No address provided&#039;);  // &quot;No address provided&quot;
```

### Array Access

Access array elements by index:

```php
$data = [
    &#039;items&#039; =&gt; [&#039;apple&#039;, &#039;banana&#039;, &#039;cherry&#039;],
];

$firstItem = Selector::get($data, &#039;items[0]&#039;);  // &quot;apple&quot;
$lastItem = Selector::get($data, &#039;items[2]&#039;);   // &quot;cherry&quot;
```

### Combining Dot Notation and Array Access

```php
$data = [
    &#039;categories&#039; =&gt; [
        &#039;fruits&#039; =&gt; [&#039;apple&#039;, &#039;banana&#039;, &#039;cherry&#039;],
        &#039;vegetables&#039; =&gt; [&#039;carrot&#039;, &#039;broccoli&#039;, &#039;spinach&#039;],
    ],
];

$firstFruit = Selector::get($data, &#039;categories.fruits[0]&#039;);  // &quot;apple&quot;
$secondVegetable = Selector::get($data, &#039;categories.vegetables[1]&#039;);  // &quot;broccoli&quot;
```

## Writing Data

Writing data is just as easy as reading it. The `set()` method handles creating intermediate structures as needed.

### Setting Simple Values

```php
$data = [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;John&#039;]];

// Update an existing value.
Selector::set($data, &#039;user.name&#039;, &#039;Jane&#039;);
// $data is now [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;Jane&#039;]]

// Create a new property.
Selector::set($data, &#039;user.email&#039;, &#039;jane@example.com&#039;);
// $data is now [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;Jane&#039;, &#039;email&#039; =&gt; &#039;jane@example.com&#039;]]
```

### Creating Nested Structures

Selector will automatically create intermediate arrays:

```php
$data = [];

// Create a deep structure.
Selector::set($data, &#039;settings.theme.colors.primary&#039;, &#039;#3366FF&#039;);
// $data is now [&#039;settings&#039; =&gt; [&#039;theme&#039; =&gt; [&#039;colors&#039; =&gt; [&#039;primary&#039; =&gt; &#039;#3366FF&#039;]]]]
```

### Working with Arrays

```php
$data = [&#039;items&#039; =&gt; [&#039;apple&#039;, &#039;banana&#039;]];

// Add or update an array element.
Selector::set($data, &#039;items[2]&#039;, &#039;cherry&#039;);
// $data is now [&#039;items&#039; =&gt; [&#039;apple&#039;, &#039;banana&#039;, &#039;cherry&#039;]]

// Update a specific element.
Selector::set($data, &#039;items[0]&#039;, &#039;red apple&#039;);
// $data is now [&#039;items&#039; =&gt; [&#039;red apple&#039;, &#039;banana&#039;, &#039;cherry&#039;]]
```

### Merging Arrays

When setting an array value to an existing array path, the arrays are merged:

```php
$data = [
    &#039;settings&#039; =&gt; [
        &#039;display&#039; =&gt; [&#039;theme&#039; =&gt; &#039;light&#039;],
    ],
];

Selector::set($data, &#039;settings.display&#039;, [&#039;fontSize&#039; =&gt; &#039;large&#039;]);
// $data is now [&#039;settings&#039; =&gt; [&#039;display&#039; =&gt; [&#039;theme&#039; =&gt; &#039;light&#039;, &#039;fontSize&#039; =&gt; &#039;large&#039;]]]
```

## Checking if Paths Exist

The `has()` method checks if a value exists at the specified path:

```php
$data = [
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John&#039;,
        &#039;email&#039; =&gt; null,
    ],
];

Selector::has($data, &#039;user.name&#039;);      // true
Selector::has($data, &#039;user.email&#039;);     // false (because the value is null)
Selector::has($data, &#039;user.address&#039;);   // false (path doesn&#039;t exist)
```

## Clearing Values

Remove values from the data structure with the `clear()` method:

```php
$data = [
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John&#039;,
        &#039;email&#039; =&gt; &#039;john@example.com&#039;,
        &#039;settings&#039; =&gt; [&#039;theme&#039; =&gt; &#039;dark&#039;],
    ],
];

// Remove a simple property.
Selector::clear($data, &#039;user.email&#039;);
// $data is now [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;John&#039;, &#039;settings&#039; =&gt; [&#039;theme&#039; =&gt; &#039;dark&#039;]]]

// Remove a nested property.
Selector::clear($data, &#039;user.settings.theme&#039;);
// $data is now [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;John&#039;, &#039;settings&#039; =&gt; []]]

// Parent arrays are cleaned up if they become empty.
Selector::clear($data, &#039;user.name&#039;);
// $data is now [&#039;user&#039; =&gt; [&#039;settings&#039; =&gt; []]]
```

## Working with Different Data Types

Selector handles various data types properly:

```php
$data = [
    &#039;values&#039; =&gt; [
        &#039;string&#039; =&gt; &#039;text&#039;,
        &#039;number&#039; =&gt; 42,
        &#039;boolean&#039; =&gt; true,
        &#039;null_value&#039; =&gt; null,
        &#039;array&#039; =&gt; [1, 2, 3],
        &#039;object&#039; =&gt; [&#039;key&#039; =&gt; &#039;value&#039;],
    ],
];

Selector::get($data, &#039;values.string&#039;);     // &quot;text&quot;
Selector::get($data, &#039;values.number&#039;);     // 42
Selector::get($data, &#039;values.boolean&#039;);    // true
Selector::get($data, &#039;values.null_value&#039;); // null
Selector::get($data, &#039;values.array&#039;);      // [1, 2, 3]
Selector::get($data, &#039;values.object&#039;);     // [&#039;key&#039; =&gt; &#039;value&#039;]
```

## Error Handling

Selector is designed to be forgiving and avoid common PHP errors:

```php
// No &quot;undefined index&quot; errors.
Selector::get($data, &#039;non.existent.path&#039;);  // returns null

// No &quot;trying to access array offset on null&quot; errors.
$data = [&#039;user&#039; =&gt; null];
Selector::get($data, &#039;user.name&#039;);  // returns null

// However, if you have syntax errors in your selector, you&#039;ll get a SelectorException.
try {
    Selector::get($data, &#039;user..name&#039;);  // Invalid selector with double dot
} catch (\Derafu\Selector\Exception\SelectorException $e) {
    echo $e-&gt;getMessage();  // &quot;Failed to read using selector &#039;user..name&#039;...&quot;
}
```

---

For more advanced usage, check out the other guides in the documentation.




---

## Working with Arrays and Filters

Working with Arrays and Filters

# Working with Arrays and Filters

This guide focuses on techniques for working with arrays and using filters in Derafu Selector.

## Basic Array Access

Arrays can be accessed using both dot notation and square bracket syntax:

```php
use Derafu\Selector\Selector;

$data = [
    &#039;items&#039; =&gt; [&#039;apple&#039;, &#039;banana&#039;, &#039;cherry&#039;],
    &#039;counts&#039; =&gt; [5, 10, 15],
];

// Access entire array.
$allItems = Selector::get($data, &#039;items&#039;);
// [&#039;apple&#039;, &#039;banana&#039;, &#039;cherry&#039;]

// First element.
$firstItem = Selector::get($data, &#039;items[0]&#039;);
// &#039;apple&#039;

// Last element.
$lastItem = Selector::get($data, &#039;items[2]&#039;);
// &#039;cherry&#039;

// Non-existent index.
$nonExistent = Selector::get($data, &#039;items[5]&#039;);
// null
```

## Numeric Indexing

```php
$data = [
    &#039;matrix&#039; =&gt; [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ],
];

// Accessing multi-dimensional arrays.
$center = Selector::get($data, &#039;matrix[1][1]&#039;);
// 5

// Alternative dot notation.
$center = Selector::get($data, &#039;matrix.1.1&#039;);
// 5

// Mixed notation.
$firstRow = Selector::get($data, &#039;matrix[0]&#039;);
// [1, 2, 3]
$firstRowThirdElement = Selector::get($data, &#039;matrix[0][2]&#039;);
// 3
```

## Filtering Arrays by Condition

The most powerful feature for array handling is filtering by key/value conditions:

```php
$data = [
    &#039;users&#039; =&gt; [
        [&#039;id&#039; =&gt; 1, &#039;name&#039; =&gt; &#039;John&#039;, &#039;role&#039; =&gt; &#039;admin&#039;],
        [&#039;id&#039; =&gt; 2, &#039;name&#039; =&gt; &#039;Jane&#039;, &#039;role&#039; =&gt; &#039;user&#039;],
        [&#039;id&#039; =&gt; 3, &#039;name&#039; =&gt; &#039;Bob&#039;, &#039;role&#039; =&gt; &#039;user&#039;],
    ]
];

// Find user by ID.
$userName = Selector::get($data, &#039;users[id=2:name]&#039;);
// &#039;Jane&#039;

// Find user by role.
$adminName = Selector::get($data, &#039;users[role=admin:name]&#039;);
// &#039;John&#039;

// Non-matching filter.
$nonExistent = Selector::get($data, &#039;users[id=99:name]&#039;);
// null
```

### Syntax for Dependent Selectors

The syntax for array filtering with dependent selectors is:

```
arrayKey[requiredKey=requiredValue:dependentKey]
```

Where:

- `arrayKey` is the key containing the array to search in.
- `requiredKey` is the key to match in each array element.
- `requiredValue` is the value that `requiredKey` should equal.
- `dependentKey` is the key to extract from the matching element.

## Complex Filtering

You can combine filters with further navigation:

```php
$data = [
    &#039;orders&#039; =&gt; [
        [
            &#039;id&#039; =&gt; 1001,
            &#039;customer&#039; =&gt; &#039;John&#039;,
            &#039;items&#039; =&gt; [
                [&#039;product&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999],
                [&#039;product&#039; =&gt; &#039;Mouse&#039;, &#039;price&#039; =&gt; 25],
            ],
        ],
        [
            &#039;id&#039; =&gt; 1002,
            &#039;customer&#039; =&gt; &#039;Jane&#039;,
            &#039;items&#039; =&gt; [
                [&#039;product&#039; =&gt; &#039;Phone&#039;, &#039;price&#039; =&gt; 699],
                [&#039;product&#039; =&gt; &#039;Headphones&#039;, &#039;price&#039; =&gt; 149],
            ],
        ],
    ],
];

// Get the first item from order 1002.
$product = Selector::get($data, &#039;orders[id=1002:items][0].product&#039;);
// &#039;Phone&#039;

// Get the price of the second item from order 1001.
$price = Selector::get($data, &#039;orders[id=1001:items][1].price&#039;);
// 25

// Find an item by product name within an order.
$data = [
    &#039;orders&#039; =&gt; [
        [
            &#039;id&#039; =&gt; 1001,
            &#039;items&#039; =&gt; [
                [&#039;product&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999],
                [&#039;product&#039; =&gt; &#039;Mouse&#039;, &#039;price&#039; =&gt; 25],
            ],
        ],
    ],
];
$mousePrice = Selector::get($data, &#039;orders[id=1001:items][product=Mouse:price]&#039;);
// 25
```

## Nested Arrays

For deeply nested structures:

```php
$data = [
    &#039;departments&#039; =&gt; [
        [
            &#039;name&#039; =&gt; &#039;Engineering&#039;,
            &#039;teams&#039; =&gt; [
                [
                    &#039;name&#039; =&gt; &#039;Frontend&#039;,
                    &#039;members&#039; =&gt; [
                        [&#039;id&#039; =&gt; 101, &#039;name&#039; =&gt; &#039;Alice&#039;],
                        [&#039;id&#039; =&gt; 102, &#039;name&#039; =&gt; &#039;Bob&#039;],
                    ]
                ],
                [
                    &#039;name&#039; =&gt; &#039;Backend&#039;,
                    &#039;members&#039; =&gt; [
                        [&#039;id&#039; =&gt; 201, &#039;name&#039; =&gt; &#039;Charlie&#039;],
                        [&#039;id&#039; =&gt; 202, &#039;name&#039; =&gt; &#039;Diana&#039;],
                    ],
                ],
            ],
        ],
    ],
];

// Find Charlie&#039;s ID through the department and team.
$charlieId = Selector::get($data,
    &#039;departments[name=Engineering:teams][name=Backend:members][name=Charlie:id]&#039;
); // 201
```

## Array Operations

### Writing to Arrays

```php
$data = [
    &#039;users&#039; =&gt; [
        [&#039;id&#039; =&gt; 1, &#039;name&#039; =&gt; &#039;John&#039;],
        [&#039;id&#039; =&gt; 2, &#039;name&#039; =&gt; &#039;Jane&#039;],
    ],
];

// Update a value.
Selector::set($data, &#039;users[id=1:name]&#039;, &#039;Johnny&#039;);
// $data[&#039;users&#039;][0][&#039;name&#039;] is now &#039;Johnny&#039;

// Add a new property.
Selector::set($data, &#039;users[id=2:email]&#039;, &#039;jane@example.com&#039;);
// $data[&#039;users&#039;][1][&#039;email&#039;] is now &#039;jane@example.com&#039;

// Add a new element.
Selector::set($data, &#039;users[3]&#039;, [&#039;id&#039; =&gt; 3, &#039;name&#039; =&gt; &#039;Bob&#039;]);
// $data[&#039;users&#039;][3] is now [&#039;id&#039; =&gt; 3, &#039;name&#039; =&gt; &#039;Bob&#039;]

// If no matching element exists, a new one is created.
Selector::set($data, &#039;users[id=4:name]&#039;, &#039;Alice&#039;);
// Adds a new element to $data[&#039;users&#039;] with id=4 and name=&#039;Alice&#039;
```

### Clearing Array Elements

```php
$data = [
    &#039;users&#039; =&gt; [
        [&#039;id&#039; =&gt; 1, &#039;name&#039; =&gt; &#039;John&#039;, &#039;email&#039; =&gt; &#039;john@example.com&#039;],
        [&#039;id&#039; =&gt; 2, &#039;name&#039; =&gt; &#039;Jane&#039;, &#039;email&#039; =&gt; &#039;jane@example.com&#039;],
    ],
];

// Remove a property.
Selector::clear($data, &#039;users[id=1:email]&#039;);
// John&#039;s email is now removed.

// Remove an entire array element.
Selector::clear($data, &#039;users[id=2]&#039;);
// Jane&#039;s record is now completely removed.

// Clean up empty array elements.
$data = [
    &#039;teams&#039; =&gt; [
        [&#039;id&#039; =&gt; 1, &#039;members&#039; =&gt; [&#039;Alice&#039;, &#039;Bob&#039;]],
        [&#039;id&#039; =&gt; 2, &#039;members&#039; =&gt; [&#039;Charlie&#039;]],
    ],
];

// Remove the last member from team 2.
Selector::clear($data, &#039;teams[id=2:members][0]&#039;);
// Now teams[id=2:members] is an empty array.

// Derafu Selector automatically cleans up empty arrays:
// $data[&#039;teams&#039;][1][&#039;members&#039;] is now an empty array.
// If we clear team 1&#039;s members too, it would clean up further.
Selector::clear($data, &#039;teams[id=1:members]&#039;);
// Now both teams have empty members arrays.
```

### Working with Mixed Array Types

Selector handles both associative and indexed arrays seamlessly:

```php
$data = [
    &#039;products&#039; =&gt; [
        &#039;electronics&#039; =&gt; [
            [&#039;id&#039; =&gt; &#039;e1&#039;, &#039;name&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999],
            [&#039;id&#039; =&gt; &#039;e2&#039;, &#039;name&#039; =&gt; &#039;Phone&#039;, &#039;price&#039; =&gt; 699],
        ],
        &#039;books&#039; =&gt; [
            [&#039;id&#039; =&gt; &#039;b1&#039;, &#039;name&#039; =&gt; &#039;Novel&#039;, &#039;price&#039; =&gt; 15],
            [&#039;id&#039; =&gt; &#039;b2&#039;, &#039;name&#039; =&gt; &#039;Textbook&#039;, &#039;price&#039; =&gt; 50],
        ],
    ],
];

// Access by category and index.
$firstElectronic = Selector::get($data, &#039;products.electronics[0].name&#039;);
// &#039;Laptop&#039;

// Access by category and ID.
$textbookPrice = Selector::get($data, &#039;products.books[id=b2:price]&#039;);
// 50

// Numeric indices still work with filtering.
$secondBookName = Selector::get($data, &#039;products.books[1].name&#039;);
// &#039;Textbook&#039;
```

### Handling Empty or Non-existent Arrays

Selector provides safe handling for empty or non-existent arrays:

```php
$data = [
    &#039;categories&#039; =&gt; [
        &#039;active&#039; =&gt; [
            [&#039;id&#039; =&gt; 1, &#039;name&#039; =&gt; &#039;Electronics&#039;],
            [&#039;id&#039; =&gt; 2, &#039;name&#039; =&gt; &#039;Books&#039;],
        ],
        &#039;inactive&#039; =&gt; [],
    ],
];

// Access on empty array.
$inactiveCategory = Selector::get($data, &#039;categories.inactive[0]&#039;);
// null

// Filter on empty array.
$result = Selector::get($data, &#039;categories.inactive[id=1:name]&#039;);
// null

// Non-existent array path.
$result = Selector::get($data, &#039;categories.archived[0].name&#039;);
// null

// Providing defaults.
$result = Selector::get($data, &#039;categories.archived[0].name&#039;, &#039;Not found&#039;);
// &#039;Not found&#039;
```

### Modifying Array Elements in Place

You can modify array elements directly:

```php
$data = [
    &#039;cart&#039; =&gt; [
        [&#039;id&#039; =&gt; &#039;p1&#039;, &#039;name&#039; =&gt; &#039;Laptop&#039;, &#039;quantity&#039; =&gt; 1],
        [&#039;id&#039; =&gt; &#039;p2&#039;, &#039;name&#039; =&gt; &#039;Mouse&#039;, &#039;quantity&#039; =&gt; 2],
    ],
];

// Increase quantity.
$currentQuantity = Selector::get($data, &#039;cart[id=p1:quantity]&#039;);
Selector::set($data, &#039;cart[id=p1:quantity]&#039;, $currentQuantity + 1);
// Now p1&#039;s quantity is 2

// Add a new property to an array element.
Selector::set($data, &#039;cart[id=p2:price]&#039;, 25);
// Mouse now has a price property

// Modify a nested property.
$data = [
    &#039;orders&#039; =&gt; [
        [
            &#039;id&#039; =&gt; 1,
            &#039;items&#039; =&gt; [
                [&#039;product&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999],
            ],
        ],
    ],
];

// Apply discount.
Selector::set($data, &#039;orders[id=1:items][product=Laptop:price]&#039;, 899);
// Price is now 899
```

---

By leveraging these array handling capabilities, you can work with complex nested data structures in a clean, readable way without worrying about undefined indices or complex nesting logic.




---

## Advanced Syntax

Advanced Selector Syntax

# Advanced Selector Syntax

This guide covers the advanced selector syntax features that make Derafu Selector powerful for complex data manipulation.

## String Literals and Concatenation

You can include literal strings in your selectors and concatenate them with values from your data:

```php
$data = [&#039;user&#039; =&gt; [&#039;name&#039; =&gt; &#039;John&#039;]];

// Simple string concatenation.
$greeting = Selector::get($data, &#039;&quot;Hello, &quot;(user.name)&quot;!&quot;&#039;);
// &quot;Hello, John!&quot;

// Multiple concatenations.
$message = Selector::get($data, &#039;&quot;User &quot;(user.name)&quot; logged in at &quot;(timestamp)&#039;);
// &quot;User John logged in at 2023-04-15 10:30:45&quot;
```

## OR Operator for Fallbacks

The `||` operator provides fallback values when a selector path doesn&#039;t exist or returns null:

```php
$data = [
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John&#039;,
        &#039;email&#039; =&gt; &#039;john@example.com&#039;,
        // phone is not set
    ],
];

// Use email if phone doesn&#039;t exist.
$contact = Selector::get($data, &#039;user.phone||user.email&#039;);
// &quot;john@example.com&quot;

// Chains of fallbacks.
$identifier = Selector::get($data, &#039;user.id||user.username||user.email&#039;);
// &quot;john@example.com&quot;

// Fallback to a literal string.
$phone = Selector::get($data, &#039;user.phone||&quot;Not provided&quot;&#039;);
// &quot;Not provided&quot;

// Combine with string concatenation.
$phoneDisplay = Selector::get($data, &#039;&quot;Phone: &quot;(user.phone||&quot;N/A&quot;)&#039;);
// &quot;Phone: N/A&quot;
```

## Conditional (Ternary) Selectors

Conditionals let you choose between different selector paths based on conditions:

```php
$data = [
    &#039;user&#039; =&gt; [
        &#039;type&#039; =&gt; &#039;admin&#039;,
        &#039;admin_role&#039; =&gt; &#039;super_admin&#039;,
        &#039;user_role&#039; =&gt; &#039;regular&#039;,
    ],
];

// Simple condition using equality.
$role = Selector::get($data,
    &#039;((user.type) = &quot;admin&quot; ? (user.admin_role) : (user.user_role))&#039;
); // &quot;super_admin&quot;

// Using not equal.
$accessLevel = Selector::get($data,
    &#039;((user.type) != &quot;guest&quot; ? (&quot;authenticated&quot;) : (&quot;anonymous&quot;))&#039;
); // &quot;authenticated&quot;

// Numeric comparisons.
$data = [&#039;score&#039; =&gt; 85];
$grade = Selector::get($data,
    &#039;((score) &gt;= &quot;90&quot; ? (&quot;A&quot;) : ((score) &gt;= &quot;80&quot; ? (&quot;B&quot;) : (&quot;C&quot;)))&#039;
); // &quot;B&quot;
```

## Dependent Selectors

Find and access specific elements in arrays based on key/value matching:

```php
$data = [
    &#039;users&#039; =&gt; [
        [&#039;id&#039; =&gt; 101, &#039;name&#039; =&gt; &#039;John&#039;, &#039;email&#039; =&gt; &#039;john@example.com&#039;],
        [&#039;id&#039; =&gt; 102, &#039;name&#039; =&gt; &#039;Jane&#039;, &#039;email&#039; =&gt; &#039;jane@example.com&#039;],
        [&#039;id&#039; =&gt; 103, &#039;name&#039; =&gt; &#039;Bob&#039;, &#039;email&#039; =&gt; &#039;bob@example.com&#039;],
    ],
];

// Get the name of user with id 102.
$name = Selector::get($data, &#039;users[id=102:name]&#039;);
// &quot;Jane&quot;

// Get the email of user with id 101.
$email = Selector::get($data, &#039;users[id=101:email]&#039;);
// &quot;john@example.com&quot;

// Nested properties.
$data = [
    &#039;orders&#039; =&gt; [
        [
            &#039;id&#039; =&gt; 1001,
            &#039;customer&#039; =&gt; [&#039;id&#039; =&gt; 101, &#039;name&#039; =&gt; &#039;John&#039;],
            &#039;items&#039; =&gt; [[&#039;product&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999]],
        ],
        [
            &#039;id&#039; =&gt; 1002,
            &#039;customer&#039; =&gt; [&#039;id&#039; =&gt; 102, &#039;name&#039; =&gt; &#039;Jane&#039;],
            &#039;items&#039; =&gt; [[&#039;product&#039; =&gt; &#039;Phone&#039;, &#039;price&#039; =&gt; 699]],
        ],
    ],
];

// Get Jane&#039;s first order item.
$janeProduct = Selector::get($data, &#039;orders[id=1002:items][0].product&#039;);
// &quot;Phone&quot;

// Access by string values with special characters.
$data = [
    &#039;categories&#039; =&gt; [
        [&#039;id&#039; =&gt; &#039;cat-1&#039;, &#039;name&#039; =&gt; &#039;Electronics&#039;],
        [&#039;id&#039; =&gt; &#039;cat-2&#039;, &#039;name&#039; =&gt; &#039;Books&#039;]
    ]
];

$catName = Selector::get($data, &#039;categories[id=cat-1:name]&#039;);
// &quot;Electronics&quot;
```

## Comparison Operators

Conditional selectors support several comparison operators:

```php
$data = [
    &#039;product&#039; =&gt; [
        &#039;price&#039; =&gt; 50,
        &#039;stock&#039; =&gt; 10,
        &#039;name&#039; =&gt; &#039;Gadget&#039;,
        &#039;tags&#039; =&gt; [&#039;electronics&#039;, &#039;new&#039;],
    ],
];

// Equality.
$isGadget = Selector::get($data,
    &#039;((product.name) = &quot;Gadget&quot; ? (&quot;Yes&quot;) : (&quot;No&quot;))&#039;
); // &quot;Yes&quot;

// Not equal.
$isExpensive = Selector::get($data,
    &#039;((product.price) != &quot;100&quot; ? (&quot;Affordable&quot;) : (&quot;Expensive&quot;))&#039;
); // &quot;Affordable&quot;

// Greater than.
$priceTier = Selector::get($data,
    &#039;((product.price) &gt; &quot;75&quot; ? (&quot;Premium&quot;) : (&quot;Standard&quot;))&#039;
); // &quot;Standard&quot;

// Less than or equal.
$stockStatus = Selector::get($data,
    &#039;((product.stock) &lt;= &quot;5&quot; ? (&quot;Low Stock&quot;) : (&quot;In Stock&quot;))&#039;
); // &quot;In Stock&quot;

// Contains (for arrays and strings).
$isNew = Selector::get($data,
    &#039;((product.tags) contains &quot;new&quot; ? (&quot;New Arrival&quot;) : (&quot;Regular Item&quot;))&#039;
); // &quot;New Arrival&quot;

// Length check.
$nameLength = Selector::get($data,
    &#039;((product.name) length &quot;6&quot; ? (&quot;Six Letters&quot;) : (&quot;Other Length&quot;))&#039;
); // &quot;Six Letters&quot;

// Null check.
$data[&#039;product&#039;][&#039;description&#039;] = null;
$hasDescription = Selector::get($data,
    &#039;((product.description) is &quot;null&quot; ? (&quot;No Description&quot;) : (&quot;Has Description&quot;))&#039;
); // &quot;No Description&quot;
```

## Special Functions

The selector syntax includes several special functions:

```php
$data = [
    &#039;product&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;Gadget&#039;,
        &#039;price&#039; =&gt; 49.99,
        &#039;tags&#039; =&gt; [&#039;electronics&#039;, &#039;gadget&#039;, &#039;new&#039;],
    ],
];

// contains - check if an array or string contains a value.
$hasTag = Selector::get($data,
    &#039;((product.tags) contains &quot;gadget&quot; ? (&quot;Tagged as gadget&quot;) : (&quot;Not tagged&quot;))&#039;
); // &quot;Tagged as gadget&quot;

// length - check the length of a string or array.
$tagCount = Selector::get($data,
    &#039;((product.tags) length &quot;3&quot; ? (&quot;Has 3 tags&quot;) : (&quot;Has another tag count&quot;))&#039;
); // &quot;Has 3 tags&quot;

$nameLength = Selector::get($data,
    &#039;((product.name) length &quot;6&quot; ? (&quot;Name has 6 chars&quot;) : (&quot;Name has different length&quot;))&#039;
); // &quot;Name has 6 chars&quot;

// is - check the type of a value (currently supports null checks).
$hasDescription = Selector::get($data,
    &#039;((product.description) is &quot;null&quot; ? (&quot;No description&quot;) : (&quot;Has description&quot;))&#039;
); // &quot;No description&quot;
```

## Parentheses and Escaping

The selector syntax uses parentheses and quotes extensively:

```php
// (selector) extracts a value from the data
// &quot;string&quot; is a literal string

$data = [&#039;message&#039; =&gt; &#039;Hello World&#039;];

// Simple extraction.
$msg = Selector::get($data, &#039;(message)&#039;); // &quot;Hello World&quot;

// Literal string.
$literal = Selector::get($data, &#039;&quot;Static text&quot;&#039;); // &quot;Static text&quot;

// Concatenating extractions and literals.
$full = Selector::get($data, &#039;(message)&quot; - welcome!&quot;&#039;); // &quot;Hello World - welcome!&quot;

// Escaping quotes and parentheses.
$escaped = Selector::get($data, &#039;&quot;This is a \\&quot;quoted\\&quot; string&quot;&#039;); // &#039;This is a &quot;quoted&quot; string&#039;
$parentheses = Selector::get($data, &#039;&quot;Formula: (x + y)&quot;&#039;); // &quot;Formula: (x + y)&quot;

// Nested parentheses for complex expressions.
$nested = Selector::get($data, &#039;((message) = &quot;Hello World&quot; ? (&quot;Greeting&quot;) : (&quot;Other message&quot;))&#039;);
// &quot;Greeting&quot;
```

---

For even more advanced capabilities, explore the integration with JSONPath and JMESPath in their respective guides.




---

## JSONPath Integration

JSONPath Integration

# JSONPath Integration

This guide explains how to use JSONPath with Derafu Selector for powerful data structure querying.

## Introduction to JSONPath

JSONPath is a query language for JSON, similar to XPath for XML. It provides a powerful way to extract data from complex JSON structures. Derafu Selector integrates JSONPath to give you even more flexibility in navigating your data.

All JSONPath expressions in Derafu Selector start with `$.` to distinguish them from regular selectors.

## Basic JSONPath Queries

Here are some basic JSONPath examples:

```php
use Derafu\Selector\Selector;

$data = [
    &#039;store&#039; =&gt; [
        &#039;books&#039; =&gt; [
            [&#039;title&#039; =&gt; &#039;Book 1&#039;, &#039;price&#039; =&gt; 10],
            [&#039;title&#039; =&gt; &#039;Book 2&#039;, &#039;price&#039; =&gt; 20],
            [&#039;title&#039; =&gt; &#039;Book 3&#039;, &#039;price&#039; =&gt; 30],
        ],
        &#039;bicycles&#039; =&gt; [
            [&#039;model&#039; =&gt; &#039;Model A&#039;, &#039;price&#039; =&gt; 100],
            [&#039;model&#039; =&gt; &#039;Model B&#039;, &#039;price&#039; =&gt; 200],
        ],
    ],
    &#039;user&#039; =&gt; [
        &#039;name&#039; =&gt; &#039;John&#039;,
        &#039;email&#039; =&gt; &#039;john@example.com&#039;,
    ],
];

// Access a simple property.
$userName = Selector::get($data, &#039;$.user.name&#039;);
// &quot;John&quot;

// Access an array element by index.
$firstBook = Selector::get($data, &#039;$.store.books[0].title&#039;);
// &quot;Book 1&quot;

// Get all book titles.
$allTitles = Selector::get($data, &#039;$.store.books[*].title&#039;);
// [&quot;Book 1&quot;, &quot;Book 2&quot;, &quot;Book 3&quot;]

// Get the entire books array.
$allBooks = Selector::get($data, &#039;$.store.books&#039;);
// The complete books array
```

## Advanced JSONPath Features

JSONPath offers powerful filtering capabilities:

```php
// Filter books by price (more than 15).
$expensiveBooks = Selector::get($data, &#039;$.store.books[?(@.price &gt; 15)].title&#039;);
// [&quot;Book 2&quot;, &quot;Book 3&quot;]

// Filter books by title (exact match).
$specificBook = Selector::get($data, &#039;$.store.books[?(@.title == &quot;Book 2&quot;)]&#039;);
// Returns the complete book object with title &quot;Book 2&quot;

// Multiple conditions with AND.
$filtered = Selector::get($data,
    &#039;$.store.books[?(@.price &gt; 15 &amp;&amp; @.price &lt; 25)].title&#039;
);
// [&quot;Book 2&quot;]

// Regular expression matching (if supported by the JSONPath implementation).
$booksWithPattern = Selector::get($data, &#039;$.store.books[?(@.title =~ /Book [1-2]/)].title&#039;);
// [&quot;Book 1&quot;, &quot;Book 2&quot;]

// Array slicing.
$firstTwoBooks = Selector::get($data, &#039;$.store.books[0:2].title&#039;);
// [&quot;Book 1&quot;, &quot;Book 2&quot;]
```

### Common JSONPath Syntax Elements

| Symbol            | Description                                              |
|-------------------|----------------------------------------------------------|
| `$`               | The root object/element                                  |
| `@`               | The current object/element                               |
| `.`               | Child operator                                           |
| `..`              | Recursive descent (find all matches at any level)        |
| `*`               | Wildcard (all objects/elements)                          |
| `[n]`             | Array index (0-based)                                    |
| `[n:m]`           | Array slice from n to m                                  |
| `[?()]`           | Filter expression                                        |
| `==` `!=`         | Equality operators                                       |
| `&gt;` `&lt;` `&gt;=` `&lt;=` | Comparison operators                                     |
| `&amp;&amp;` `\|\|`       | Logical AND and OR                                       |

## Combining JSONPath with Derafu Selectors

You can mix JSONPath with regular Derafu selectors for maximum flexibility:

```php
// Use JSONPath to get a value and then concatenate with text.
$message = Selector::get($data, &#039;&quot;User: &quot;($.user.name)&#039;);
// &quot;User: John&quot;

// Use JSONPath as part of an OR selector.
$contact = Selector::get($data, &#039;$.user.phone||$.user.email&#039;);
// Falls back to &quot;john@example.com&quot; if phone doesn&#039;t exist

// Use JSONPath result in a conditional expression.
$userType = Selector::get($data,
    &#039;(($.user.email) contains &quot;example.com&quot; ? (&quot;Standard&quot;) : (&quot;Premium&quot;))&#039;
);
// &quot;Standard&quot;

// Format array results.
$bookList = Selector::get($data,
    &#039;&quot;Available books: &quot;($.store.books[*].title)&#039;
);
// &quot;Available books: [\&quot;Book 1\&quot;, \&quot;Book 2\&quot;, \&quot;Book 3\&quot;]&quot;

// Mix JSONPath with regular selectors.
$data = [
    &#039;config&#039; =&gt; [&#039;theme&#039; =&gt; &#039;dark&#039;],
    &#039;preferences&#039; =&gt; [
        &#039;admin&#039; =&gt; [&#039;theme&#039; =&gt; &#039;light&#039;],
        &#039;user&#039; =&gt; [&#039;theme&#039; =&gt; &#039;system&#039;]
    ]
];

$theme = Selector::get($data,
    &#039;(($.user.role) = &quot;admin&quot; ? (preferences.admin.theme) : (config.theme))&#039;
);
// Falls back to &quot;dark&quot; if user.role doesn&#039;t exist
```

## Performance Considerations

While JSONPath provides powerful querying capabilities, it may have different performance characteristics compared to native Derafu selectors:

1. **Initialization Cost**: JSONPath queries require initializing the JSONPath processor, which adds some overhead.

2. **Complex Queries**: For very complex queries with multiple conditions, JSONPath may be more efficient than chaining multiple native selectors.

3. **Large Data Sets**: For very large data structures, JSONPath&#039;s optimized filtering can be more efficient than iterating through the data manually.

4. **Writing Operations**: Note that JSONPath in Derafu Selector supports read operations only. For writing operations, you need to use native selectors.

**Best Practices**:

- Use native Derafu selectors for simple path access (`user.profile.name`).
- Use JSONPath for complex filtering and array operations.
- Consider caching results of expensive JSONPath queries if they&#039;re used repeatedly.
- Avoid using `..` (recursive descent) on very large data structures if performance is critical.

```php
// Less efficient for simple access.
$name = Selector::get($data, &#039;$.user.name&#039;);

// More efficient native syntax for simple access.
$name = Selector::get($data, &#039;user.name&#039;);

// JSONPath is more efficient for complex filtering.
$expensiveItems = Selector::get($data,
    &#039;$.items[?(@.price &gt; 100 &amp;&amp; @.category == &quot;electronics&quot;)].name&#039;
);
```

---

By understanding when to use JSONPath versus native selectors, you can optimize your code for both readability and performance.




---

## JMESPath Integration

JMESPath Integration

# JMESPath Integration

This guide explains how to use JMESPath with Derafu Selector for powerful data querying.

## Introduction to JMESPath

JMESPath is a query language for JSON that allows you to extract and transform elements from complex data structures. It provides a more structured and feature-rich alternative to JSONPath with a clear specification.

All JMESPath expressions in Derafu Selector start with `jmespath:` to distinguish them from regular selectors.

## Basic JMESPath Queries

Here are some basic JMESPath examples:

```php
use Derafu\Selector\Selector;

$data = [
    &#039;people&#039; =&gt; [
        [
            &#039;name&#039; =&gt; &#039;John&#039;,
            &#039;age&#039; =&gt; 30,
            &#039;phones&#039; =&gt; [&#039;home&#039; =&gt; &#039;555-1234&#039;, &#039;mobile&#039; =&gt; &#039;555-5678&#039;],
        ],
        [
            &#039;name&#039; =&gt; &#039;Jane&#039;,
            &#039;age&#039; =&gt; 25,
            &#039;phones&#039; =&gt; [&#039;home&#039; =&gt; &#039;555-4321&#039;, &#039;mobile&#039; =&gt; &#039;555-8765&#039;],
        ],
    ],
    &#039;locations&#039; =&gt; [
        &#039;Seattle&#039; =&gt; [&#039;state&#039; =&gt; &#039;WA&#039;, &#039;population&#039; =&gt; 724305],
        &#039;New York&#039; =&gt; [&#039;state&#039; =&gt; &#039;NY&#039;, &#039;population&#039; =&gt; 8804190],
    ],
];

// Access a simple path.
$firstPerson = Selector::get($data, &#039;jmespath:people[0]&#039;);
// Complete first person object.

// Access a specific property.
$firstName = Selector::get($data, &#039;jmespath:people[0].name&#039;);
// &quot;John&quot;

// Access all names.
$allNames = Selector::get($data, &#039;jmespath:people[*].name&#039;);
// [&quot;John&quot;, &quot;Jane&quot;]

// Access a nested property.
$firstMobile = Selector::get($data, &#039;jmespath:people[0].phones.mobile&#039;);
// &quot;555-5678&quot;

// Use bracket notation for keys with special characters.
$nyState = Selector::get($data, &#039;jmespath:locations.&quot;New York&quot;.state&#039;);
// &quot;NY&quot;
```

## Advanced JMESPath Features

JMESPath offers powerful filtering, projection, and transformation capabilities:

### Filtering

```php
// Filter people over age 25.
$over25 = Selector::get($data, &#039;jmespath:people[?age &gt; `25`]&#039;);
// Returns the complete person object for John.

// Filter with multiple conditions.
$filtered = Selector::get($data,
    &#039;jmespath:people[?age &gt; `25` &amp;&amp; contains(name, `Jo`)]&#039;
);
// Returns John&#039;s complete object.

// Get just the names of filtered results.
$names = Selector::get($data, &#039;jmespath:people[?age &gt; `25`].name&#039;);
// [&quot;John&quot;]

// Filter on nested properties.
$withMobile = Selector::get($data,
    &#039;jmespath:people[?phones.mobile != null].name&#039;
);
// [&quot;John&quot;, &quot;Jane&quot;]
```

### Multi-select and Projections

```php
// Select specific fields (projection).
$simplified = Selector::get($data, &#039;jmespath:people[*].{n: name, a: age}&#039;);
// [{&quot;n&quot;:&quot;John&quot;,&quot;a&quot;:30}, {&quot;n&quot;:&quot;Jane&quot;,&quot;a&quot;:25}]

// Multi-select on a single object.
$details = Selector::get($data, &#039;jmespath:people[0].{name: name, mobile: phones.mobile}&#039;);
// {&quot;name&quot;:&quot;John&quot;,&quot;mobile&quot;:&quot;555-5678&quot;}

// Flatten nested structures.
$phones = Selector::get($data, &#039;jmespath:people[*].phones.*&#039;);
// [&quot;555-1234&quot;, &quot;555-5678&quot;, &quot;555-4321&quot;, &quot;555-8765&quot;]
```

### Functions

JMESPath supports a variety of built-in functions:

```php
// String functions.
$upperNames = Selector::get($data, &#039;jmespath:people[*].name | [*].to_upper(@)&#039;);
// [&quot;JOHN&quot;, &quot;JANE&quot;]

// Length/count.
$peopleCount = Selector::get($data, &#039;jmespath:length(people)&#039;);
// 2

// Min/max of values.
$data = [&#039;values&#039; =&gt; [5, 3, 8, 1, 7]];
$maxValue = Selector::get($data, &#039;jmespath:max(values)&#039;);
// 8

// Sort function.
$sortedNames = Selector::get($data, &#039;jmespath:sort(people[*].name)&#039;);
// [&quot;Jane&quot;, &quot;John&quot;]

// Map function for transformations.
$ages = Selector::get($data, &#039;jmespath:people[*].age | map(&amp;to_string(@), @)&#039;);
// [&quot;30&quot;, &quot;25&quot;]
```

### Slicing and Indexing

```php
// Array slicing.
$firstPerson = Selector::get($data, &#039;jmespath:people[:1]&#039;);
// [Complete first person object]

// Negative indices.
$lastPerson = Selector::get($data, &#039;jmespath:people[-1]&#039;);
// Complete last person object (Jane).

// Step values.
$everyOtherPerson = Selector::get($data, &#039;jmespath:people[::2]&#039;);
// Every other person in the array.
```

## Combining JMESPath with Derafu Selectors

You can mix JMESPath with regular Derafu selectors:

```php
// Use JMESPath to get a value and then concatenate with text.
$greeting = Selector::get($data, &#039;&quot;Hello, &quot;(jmespath:people[0].name)&quot;!&quot;&#039;);
// &quot;Hello, John!&quot;

// Use JMESPath as part of an OR selector.
$location = Selector::get($data,
    &#039;jmespath:current_location||jmespath:locations.&quot;Seattle&quot;.state&#039;
);
// Falls back to &quot;WA&quot; if current_location doesn&#039;t exist.

// Use JMESPath within a conditional.
$message = Selector::get($data,
    &#039;((jmespath:people | length(@)) &gt; &quot;1&quot; ? (&quot;Multiple people&quot;) : (&quot;One person&quot;))&#039;
);
// &quot;Multiple people&quot;

// Format array results.
$nameList = Selector::get($data,
    &#039;&quot;People: &quot;(jmespath:people[*].name)&#039;
);
// &quot;People: [\&quot;John\&quot;, \&quot;Jane\&quot;]&quot;
```

## Choosing Between JMESPath and JSONPath

Derafu Selector supports both JMESPath and JSONPath. Here are some considerations for choosing between them:

### JMESPath Advantages

- **Formal Specification**: JMESPath has a formal, well-defined specification.
- **Functions**: Built-in functions for transformation and manipulation.
- **Multi-select Projection**: Create new structures with the data you extract.
- **Expressions**: More powerful expression language.
- **Pipe Operator**: Chain operations together.

### JSONPath Advantages

- **Simplicity**: More straightforward syntax for basic queries.
- **Familiarity**: If you&#039;re already using JSONPath elsewhere.
- **Recursive Descent**: The `..` operator for finding elements at any level.

### Examples of the Same Query in Both

```php
$data = [
    &#039;products&#039; =&gt; [
        [&#039;name&#039; =&gt; &#039;Laptop&#039;, &#039;price&#039; =&gt; 999, &#039;category&#039; =&gt; &#039;electronics&#039;],
        [&#039;name&#039; =&gt; &#039;Phone&#039;, &#039;price&#039; =&gt; 699, &#039;category&#039; =&gt; &#039;electronics&#039;],
        [&#039;name&#039; =&gt; &#039;Book&#039;, &#039;price&#039; =&gt; 15, &#039;category&#039; =&gt; &#039;media&#039;],
    ],
];

// Get electronics products with JSONPath.
$electronics = Selector::get($data,
    &#039;$.products[?(@.category == &quot;electronics&quot;)].name&#039;
);
// [&quot;Laptop&quot;, &quot;Phone&quot;]

// Same query with JMESPath.
$electronics = Selector::get($data,
    &#039;jmespath:products[?category == `electronics`].name&#039;
);
// [&quot;Laptop&quot;, &quot;Phone&quot;]

// Filter by price and sort with JSONPath (sorting may not be available in all implementations).
// May require multiple selector calls.

// With JMESPath, this is built-in.
$sortedProducts = Selector::get($data,
    &#039;jmespath:products[?price &gt; `500`].name | sort(@)&#039;
);
// [&quot;Laptop&quot;, &quot;Phone&quot;] (sorted)
```

---

By understanding the strengths of each query language, you can choose the right tool for your specific data navigation needs.





---
Last updated on 24/08/2026
#php
