This document provides a comprehensive overview of the enhancements made to the PHP CRUD API Generator in version 1.1.0.
- Advanced Filtering
- Field Selection
- Count Endpoint
- Bulk Operations
- Input Validation
- Security Improvements
- Migration Guide
The filtering system has been enhanced to support multiple comparison operators beyond simple equality checks.
| Operator | Description | Example |
|---|---|---|
eq |
Equals (default) | filter=name:eq:Alice |
neq, ne |
Not equals | filter=status:neq:deleted |
gt |
Greater than | filter=age:gt:18 |
gte, ge |
Greater than or equal | filter=price:gte:100 |
lt |
Less than | filter=stock:lt:10 |
lte, le |
Less than or equal | filter=discount:lte:50 |
like |
Pattern matching | filter=email:like:%@gmail.com |
in |
In list (pipe-separated) | `filter=status:in:active |
notin, nin |
Not in list | `filter=role:notin:admin |
null |
Is NULL | filter=deleted_at:null: |
notnull |
Is NOT NULL | filter=email:notnull: |
New Format: col:operator:value
- Example:
filter=age:gt:18,status:eq:active
Legacy Format: col:value (still supported)
- Example:
filter=name:Alice - Automatically uses
=for exact match orLIKEif value contains%
Combine multiple filters using commas:
/index.php?action=list&table=users&filter=age:gte:18,status:eq:active,email:like:%@gmail.com
This creates an AND condition for all filters.
E-commerce Product Filtering:
# Products between $10 and $100 with stock
/index.php?action=list&table=products&filter=price:gte:10,price:lte:100,stock:gt:0
# Out of stock products
/index.php?action=list&table=products&filter=stock:eq:0
User Management:
# Active users who registered recently
/index.php?action=list&table=users&filter=status:eq:active,created_at:gte:2024-01-01
# Users without email verification
/index.php?action=list&table=users&filter=email_verified_at:null:
The field selection feature allows you to retrieve only specific columns from a table, reducing bandwidth and improving performance.
/index.php?action=list&table=users&fields=id,name,email
- Reduced bandwidth: Only requested fields are transferred
- Improved performance: Less data to serialize and deserialize
- Privacy: Exclude sensitive fields from responses
- Mobile optimization: Send only necessary data to mobile clients
Basic field selection:
/index.php?action=list&table=users&fields=id,name
Combined with filtering:
/index.php?action=list&table=users&fields=id,name,email&filter=status:eq:active
Combined with sorting and pagination:
/index.php?action=list&table=products&fields=id,name,price&sort=-price&page=1&page_size=20
A dedicated endpoint for counting records without pagination overhead. Perfect for dashboards, analytics, and statistics.
GET /index.php?action=count&table=users
- Supports all filter operators
- No pagination overhead
- Returns simple count object
- Uses same permissions as
listaction
Basic count:
curl "http://localhost/index.php?action=count&table=users"
# Response: {"count": 150}Count with filters:
# Count active users
curl "http://localhost/index.php?action=count&table=users&filter=status:eq:active"
# Response: {"count": 120}
# Count users over 18
curl "http://localhost/index.php?action=count&table=users&filter=age:gt:18"
# Response: {"count": 95}
# Count premium subscriptions
curl "http://localhost/index.php?action=count&table=subscriptions&filter=type:eq:premium,status:in:active|trial"
# Response: {"count": 45}Dashboard Statistics:
// Fetch multiple counts for dashboard
Promise.all([
fetch('/index.php?action=count&table=users&filter=status:eq:active'),
fetch('/index.php?action=count&table=orders&filter=status:eq:pending'),
fetch('/index.php?action=count&table=products&filter=stock:lt:10')
]).then(results => {
// Display statistics
});Analytics:
# User growth metrics
curl "http://localhost/index.php?action=count&table=users&filter=created_at:gte:2024-01-01"
# Conversion rates
curl "http://localhost/index.php?action=count&table=leads&filter=status:eq:converted"Bulk operations allow you to create or delete multiple records efficiently in single API calls.
Endpoint: POST /index.php?action=bulk_create&table=users
Features:
- Transaction-based (all or nothing)
- Returns all created records with IDs
- Automatic rollback on failure
Request:
[
{"name": "Alice", "email": "alice@example.com", "age": 25},
{"name": "Bob", "email": "bob@example.com", "age": 30},
{"name": "Charlie", "email": "charlie@example.com", "age": 35}
]Response:
{
"success": true,
"created": 3,
"data": [
{"id": 101, "name": "Alice", "email": "alice@example.com", "age": 25},
{"id": 102, "name": "Bob", "email": "bob@example.com", "age": 30},
{"id": 103, "name": "Charlie", "email": "charlie@example.com", "age": 35}
]
}curl Example:
curl -X POST -H "Content-Type: application/json" \
-d '[{"name":"Alice","email":"alice@example.com"},{"name":"Bob","email":"bob@example.com"}]' \
"http://localhost/index.php?action=bulk_create&table=users"Endpoint: POST /index.php?action=bulk_delete&table=users
Features:
- Single efficient query
- Returns count of deleted records
- Works with any ID format (numeric or UUID)
Request:
{
"ids": [1, 2, 3, 4, 5]
}Response:
{
"success": true,
"deleted": 5
}curl Example:
curl -X POST -H "Content-Type: application/json" \
-d '{"ids":[1,2,3,4,5]}' \
"http://localhost/index.php?action=bulk_delete&table=users"Data Import:
// Import users from CSV
const users = parseCSV(csvData);
fetch('/index.php?action=bulk_create&table=users', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(users)
});Batch Cleanup:
// Delete old records
const oldRecordIds = [101, 102, 103, 104, 105];
fetch('/index.php?action=bulk_delete&table=logs', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ids: oldRecordIds})
});Comprehensive input validation has been added to prevent SQL injection, invalid queries, and malicious inputs.
The new Validator class provides centralized validation methods:
Validator::validateTableName($table) // Alphanumeric + underscore only
Validator::validateColumnName($column) // Alphanumeric + underscore only
Validator::validateId($id) // Numeric or UUID format
Validator::validatePage($page) // Positive integer
Validator::validatePageSize($size) // Integer, 1-100
Validator::validateOperator($op) // Valid filter operator
Validator::validateSort($sort) // Valid sort formatTable Names:
- Must be alphanumeric with underscores only
- Example:
users,order_items,product_123
Column Names:
- Must be alphanumeric with underscores only
- Example:
user_id,created_at,email_address
IDs:
- Must be numeric or valid UUID format
- Examples:
123,550e8400-e29b-41d4-a716-446655440000
Pagination:
- Page must be positive integer (≥1)
- Page size must be 1-100 (default: 20)
Sort Parameters:
- Column names must be valid
- Format:
col1,-col2(prefix-for DESC)
Problem: Previous filter implementation could have parameter name collisions.
Solution: Each filter parameter now gets a unique name:
// Old: $params['name'] could be overwritten
// New: $params['name_0'], $params['name_1'], etc.All database queries use prepared statements with bound parameters:
// Good: Using prepared statements
$stmt = $pdo->prepare("SELECT * FROM `$table` WHERE `col` = :param");
$stmt->execute(['param' => $value]);
// Bad: Never concatenate user input
$stmt = $pdo->query("SELECT * FROM $table WHERE col = '$value'"); // ❌All user inputs are validated before use:
- Table names checked against allowed characters
- Column names validated
- IDs validated for correct format
- Filter operators checked against whitelist
Input validation is applied before RBAC checks, ensuring invalid inputs are rejected early:
Request → Input Validation → Authentication → RBAC → Database Query
No Breaking Changes! Version 1.1.0 is fully backward compatible.
1. Upgrade your filtering:
Before:
/index.php?action=list&table=users&filter=age:30
After (more options available):
/index.php?action=list&table=users&filter=age:gte:30,status:eq:active
2. Optimize with field selection:
Before:
/index.php?action=list&table=users
// Returns all columns
After:
/index.php?action=list&table=users&fields=id,name,email
// Returns only specified columns
3. Use count for statistics:
Before:
/index.php?action=list&table=users&page_size=1
// Inefficient, still fetches data
After:
/index.php?action=count&table=users
// Efficient, returns just the count
4. Bulk operations for efficiency:
Before:
// Create users one by one
for (const user of users) {
await fetch('/index.php?action=create&table=users', {
method: 'POST',
body: JSON.stringify(user)
});
}After:
// Create all users at once
await fetch('/index.php?action=bulk_create&table=users', {
method: 'POST',
body: JSON.stringify(users)
});- Test basic operations still work as before
- Try new filter operators on non-production data
- Test field selection to ensure correct columns returned
- Validate error responses for invalid inputs
- Test bulk operations with small datasets first
Always specify fields when you don't need all columns:
✅ /index.php?action=list&table=users&fields=id,name
❌ /index.php?action=list&table=users (returns all columns)
Use the count endpoint for statistics instead of fetching and counting:
✅ /index.php?action=count&table=users
❌ /index.php?action=list&table=users then count in code
Use bulk operations when creating or deleting multiple records:
✅ bulk_create with array of records
❌ Multiple create calls in a loop
Use specific operators instead of fetching and filtering in code:
✅ filter=age:gte:18,status:in:active|trial
❌ Fetch all records and filter in application code
Always paginate large result sets:
✅ page=1&page_size=20
❌ Fetching thousands of records at once
- Field Selection: 50-70% reduction in response size for tables with many columns
- Count Endpoint: 10x faster than fetching records for counting
- Bulk Operations: 10-100x faster than individual operations depending on record count
- Indexed Columns: Use indexed columns in filters for better performance
- Pagination: Keep page_size reasonable (20-50 records) for best performance
For questions or issues with these enhancements:
- Check the README.md for usage examples
- Review the CHANGELOG.md for version history
- Open an issue on GitHub
Built by BitHost | Version 1.1.0