---
title: "Value shapes — Query Builder for Laravel | Roundly"
description: "Declare a FilterValueShape on typed columns so a malformed uuid or id returns an empty result instead of a PostgreSQL 500."
url: https://roundly-consulting.com/open-source/docs/query-builder-for-laravel/value-shapes
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Query Builder for Laravel](https://roundly-consulting.com/open-source/docs/query-builder-for-laravel.md)

# Value shapes

PostgreSQL answers a value of the wrong type with an error rather than “no match”, so filter\[project\]=garbage on a uuid column is a request-triggerable 500. (MySQL and SQLite coerce instead — a non-numeric string becomes 0 and quietly matches row zero.) Declare a FilterValueShape on any typed column and values the column cannot hold never reach the driver:

| Case | Value | Accepts |
| --- | --- | --- |
| `FilterValueShape::Text` | `text` | Any string — the default; guards nothing. |
| `FilterValueShape::Uuid` | `uuid` | A valid UUID. |
| `FilterValueShape::Id` | `id` | A non-negative integer up to PHP\_INT\_MAX (a bigint’s maximum) in FILTER\_VALIDATE\_INT syntax; the sign is read from the parsed number, so “ -5” is refused and -0 is 0. |
| `FilterValueShape::Boolean` | `boolean` | true/false/1/0 in any case, handed to the query as a real boolean. |

```php
use RoundlyConsulting\QueryBuilder\Enums\FilterValueShape;
use RoundlyConsulting\QueryBuilder\Enums\RequestedOperator;

->allowedFilters(
    AllowedFilter::operators('author', [RequestedOperator::Not], 'author_id', shape: FilterValueShape::Id),
    AllowedFilter::nullable('project', 'project_id', FilterValueShape::Uuid),
    AllowedFilter::relation('label', 'labels', 'labels.id', FilterValueShape::Uuid),
)

// ?filter[author]=garbage     → empty result, no driver error
// ?filter[author]=not:garbage → excludes nothing
// ?filter[project]=12345      → empty result
```

Boolean also hands the query a real boolean — the text 'false' is not false to any engine. Combined with operators() it gives a flag column a negation:

```php
->allowedFilters(
    AllowedFilter::operators('active', [RequestedOperator::Not], shape: FilterValueShape::Boolean), // not:true
)
```

## How it behaves

- Accepted by operators(), nullable(), relation() and jsonContains(); AllowedFilter::boolean() is operators() with the Boolean shape. The default Text guards nothing, so no existing filter changes.
- Values of the wrong shape are dropped before the query is built. If none survive, a match returns an empty result — never the unfiltered list — and a negation excludes nothing, since no row could have matched.
- No value is not a wrong value: filter\[active\]= on boolean('active') adds no constraint at all, while filter\[active\]=maybe matches nothing.
- Id rejects out-of-range numbers too: PostgreSQL fails on an out-of-range bigint exactly as on a malformed uuid.
- A typed shape cannot be combined with a LIKE-family operator (contains, ncontains, starts) or partialByDefault — the declaration throws UnsupportedOperator instead of failing on the first request.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/query-builder-for-laravel.md)
