Skip to content

Query Engine

lpachecob edited this page Mar 23, 2026 · 3 revisions

πŸ”Ž Pro Query Engine: API Search Power

BOUNDLY's Dynamic Repository provides a powerful query engine out of the box. Any entity with a resource in its #[Entity] attribute gets a fully functional GET endpoint with filtering, sorting, pagination, and eager loading.


πŸ”Ž Filtering

Add filters directly as URL parameters. Only fields declared in the entity's #[Column] attributes are accepted β€” unknown fields are silently ignored for security.

Suffix Operator Example
(none) = ?status=1
_like LIKE %value% ?name_like=Luis
_gt > ?price_gt=100
_lt < ?id_lt=50
_gte >= ?age_gte=18
_lte <= ?score_lte=99
_not != ?category_not=3
_in IN (...) ?id_in=1,2,3
_null IS NULL / IS NOT NULL ?deleted_at_null=1
GET /api/users?name_like=Luis&age_gte=18

πŸ”€ OR Filter Groups

Group filter conditions with or[...] to produce WHERE (a OR b) queries:

GET /api/users?or[name_like]=john&or[email_like]=john
# β†’ WHERE (name LIKE '%john%' OR email LIKE '%john%')

πŸ“¦ Eager Loading (include)

Use include to fetch relationships defined in your entity. Supports dot-notation for nested relations. N+1 Optimized: BOUNDLY automatically collapses relationship queries into highly efficient WHERE IN (...) calls under the hood, regardless of how deep your nesting goes.

# Single relation
GET /api/posts?include=author

# Multiple relations
GET /api/users?include=profile,posts

# Nested relations (posts β†’ comments β†’ author)
GET /api/users?include=posts.comments.author

πŸ” Pagination

BOUNDLY supports two pagination strategies:

Offset Pagination (default)

Standard page-based pagination. Best for small-to-medium datasets.

Parameter Default Description
per_page 15 Number of items per page.
page 1 Current page number.
GET /api/products?per_page=50&page=2

Cursor Pagination

Highly efficient for large datasets and infinite scroll. Pass ?cursor=<last_id> to fetch the next page.

Parameter Description
cursor The ID of the last item from the previous page.
per_page Number of items to return.
GET /api/events?cursor=250&per_page=20
# Response includes 'next_cursor' and 'has_more' fields

πŸ”ƒ Sorting

Parameter Default Description
sort 'id' Column to sort by (must be declared in the entity).
direction 'asc' Sort direction (asc or desc).
GET /api/orders?sort=created_at&direction=desc

πŸ”’ Automatic Validation & Sanitization

On POST, PUT, and PATCH requests, BOUNDLY automatically validates the payload against the entity metadata:

  • Type checking based on #[Column(type: '...')]
  • Max length from #[Column(length: N)]
  • Nullable enforcement from #[Column(nullable: true/false)]
  • Whitelist sanitization: any field NOT declared in the entity is stripped silently.

For PATCH, only the fields present in the request are validated (partial update mode).

πŸ”„ Automatic Relationship Syncing (Many-To-Many)

If your entity defines a #[ManyToMany] relation (like roles), you can safely pass an array of IDs in your POST or PUT payloads. BOUNDLY will naturally extract the array, save the main entity, and perform an automatic pivot table sync for you.

{
  "name": "Luis",
  "roles": [1, 2] 
}
// BOUNDLY handles the pivot table inserts/deletes transparently!

πŸ§ͺ Combined Example

Get the first 10 active users named "Luis", including their profiles and last 5 posts, sorted by registration date:

GET /api/users?name_like=Luis&status=1&include=profile,posts&sort=created_at&direction=asc&per_page=10

Next Step: CLI-Commands πŸš€

Clone this wiki locally