Skip to content

Criteria Query Builder

PHP Laravel-style query building for filtering and sorting

The Criteria class provides a fluent, PHP Laravel-style interface for building queries.

Basic Usage

import { Criteria } from '@laravel-streams/api-client';

const criteria = new Criteria()
    .where('status', 'published')
    .orderBy('created_at', 'desc')
    .limit(10);

const response = await client.entries.get('posts', { criteria });

Creating Criteria

Static Factory

const criteria = Criteria.make()
    .where('status', 'active');

Constructor

const criteria = new Criteria();
criteria.where('status', 'active');

Where Clauses

Basic Where

// Simple equality
criteria.where('status', 'published');
// Generates: WHERE status == 'published'

// With operator
criteria.where('views', '>', 100);
// Generates: WHERE views > 100

Available Operators

Comparison Operators

criteria.where('views', '>', 100);     // Greater than
criteria.where('views', '>=', 100);    // Greater than or equal
criteria.where('views', '<', 100);     // Less than
criteria.where('views', '<=', 100);    // Less than or equal
criteria.where('status', '==', 'active'); // Equal
criteria.where('status', '!=', 'deleted'); // Not equal
criteria.where('value', '<>', 0);      // Not equal (alternative)

Logical Operators

criteria.where('status', 'IN', ['published', 'featured']);
criteria.where('title', 'LIKE', '%tutorial%');
criteria.where('content', 'NOT', null);
criteria.where('tags', 'ALL', ['javascript', 'tutorial']);
criteria.where('categories', 'ANY', ['tech', 'news']);

OR Where Clauses

const criteria = new Criteria()
    .where('status', 'published')
    .orWhere('status', 'featured');
// WHERE status == 'published' OR status == 'featured'

Chaining Where Clauses

const criteria = new Criteria()
    .where('status', 'published')
    .where('views', '>', 100)
    .where('category', 'technology')
    .where('created_at', '>=', '2024-01-01');
// WHERE status == 'published' 
//   AND views > 100 
//   AND category == 'technology'
//   AND created_at >= '2024-01-01'

Ordering Results

Order By

// Descending (default)
criteria.orderBy('created_at');

// Ascending
criteria.orderBy('title', 'asc');

// Descending
criteria.orderBy('views', 'desc');

Multiple Order By

const criteria = new Criteria()
    .orderBy('priority', 'desc')  // First by priority
    .orderBy('created_at', 'desc') // Then by date
    .orderBy('title', 'asc');      // Then by title

Limiting Results

Limit

criteria.limit(10); // Return maximum 10 results

First

criteria.first(); // Same as limit(1)

Find by ID

criteria.find(123); 
// Same as: where('id', 123).limit(1)

Pagination

// paginate(perPage, page)
criteria.paginate(25, 1); // 25 per page, page 1

// Default pagination (100 per page, page 1)
criteria.paginate();

Complex Queries

Combining Conditions

const criteria = new Criteria()
    // Published or featured
    .where('status', 'published')
    .orWhere('status', 'featured')
    // With minimum views
    .where('views', '>=', 100)
    // In specific categories
    .where('category', 'IN', ['tech', 'tutorial'])
    // Recent posts
    .where('created_at', '>=', '2024-01-01')
    // Sort by popularity, then date
    .orderBy('views', 'desc')
    .orderBy('created_at', 'desc')
    // Paginate
    .paginate(20, 1);

Search Functionality

function searchPosts(query) {
    return new Criteria()
        .where('title', 'LIKE', `%${query}%`)
        .orWhere('content', 'LIKE', `%${query}%`)
        .orWhere('tags', 'LIKE', `%${query}%`)
        .where('status', 'published')
        .orderBy('relevance', 'desc')
        .limit(50);
}

const criteria = searchPosts('javascript');
const results = await client.entries.get('posts', { criteria });

Working with Parameters

Get Parameters

const criteria = new Criteria()
    .where('status', 'published')
    .orderBy('created_at', 'desc')
    .limit(10);

const params = criteria.getParameters();
console.log(params);
// [
//   { name: 'where', value: ['status', '==', 'published', null] },
//   { name: 'orderBy', value: ['created_at', 'desc'] },
//   { name: 'limit', value: 10 }
// ]

Set Parameters

const criteria = new Criteria();
criteria.setParameters([
    { name: 'where', value: ['status', '==', 'published', null] },
    { name: 'limit', value: 10 }
]);

Add Parameter

const criteria = new Criteria();
criteria.addParameter('where', ['status', '==', 'published', null]);

Standardize Parameters

const criteria = new Criteria()
    .where('status', 'published')
    .limit(10);

const standardized = criteria.standardizeParameters();
console.log(standardized);
// {
//   where: ['status', '==', 'published', null],
//   limit: 10
// }

Real-World Examples

Blog Post Filtering

// Featured posts from last month
const criteria = new Criteria()
    .where('featured', true)
    .where('published_at', '>=', getLastMonth())
    .where('status', 'published')
    .orderBy('published_at', 'desc')
    .limit(5);

// Posts by category with minimum engagement
const criteria = new Criteria()
    .where('category', 'javascript')
    .where('likes', '>', 50)
    .where('comments', '>', 10)
    .orderBy('engagement_score', 'desc')
    .paginate(20, 1);

E-commerce Product Filtering

// Products in price range, in stock
const criteria = new Criteria()
    .where('price', '>=', 10)
    .where('price', '<=', 100)
    .where('stock', '>', 0)
    .where('category', 'electronics')
    .orderBy('popularity', 'desc')
    .paginate(24, 1);

// Sale items
const criteria = new Criteria()
    .where('on_sale', true)
    .where('discount', '>=', 20)
    .where('stock', '>', 0)
    .orderBy('discount', 'desc')
    .orderBy('price', 'asc');

User Management

// Active users who logged in recently
const criteria = new Criteria()
    .where('status', 'active')
    .where('last_login', '>=', getLastWeek())
    .where('email_verified', true)
    .orderBy('last_login', 'desc')
    .limit(100);

// Premium users expiring soon
const criteria = new Criteria()
    .where('subscription', 'premium')
    .where('expires_at', '<=', getNextMonth())
    .where('expires_at', '>=', getToday())
    .orderBy('expires_at', 'asc');

Builder Pattern

The Criteria class uses the builder pattern, allowing you to chain methods:

const criteria = new Criteria()
    .where('a', 1)     // Returns this
    .where('b', 2)     // Returns this
    .orderBy('c')      // Returns this
    .limit(10);        // Returns this

// Same as:
const criteria = new Criteria();
criteria.where('a', 1);
criteria.where('b', 2);
criteria.orderBy('c');
criteria.limit(10);

Reusable Criteria

// Create base criteria
const publishedPosts = () => new Criteria()
    .where('status', 'published')
    .where('deleted_at', null);

// Extend it
const recentPublishedPosts = publishedPosts()
    .where('created_at', '>=', getLastWeek())
    .orderBy('created_at', 'desc');

const popularPublishedPosts = publishedPosts()
    .where('views', '>', 1000)
    .orderBy('views', 'desc');

Next Steps