Overview of SwaggerPhp Alternative Analysers
developphpstan/phpdoc-parser instead of the deprecated doctrine/annotations. This is primarily used to facilitate OpenAPI specification generation in modules/System/Controller/Api.php.repository·develop·Indexed 20 days ago
https://github.com/cockpit-hq/cockpitA modern, headless Content Management System (CMS) providing content infrastructure via GraphQL and REST APIs. This documentation includes detailed guides on ESQL, a PHP library for database interaction supporting MySQL, PostgreSQL, and SQLite, featuring a fluent query builder, automatic JSON encoding/decoding, transaction management, and safe SQL execution.
phpstan/phpdoc-parser instead of the deprecated doctrine/annotations. This is primarily used to facilitate OpenAPI specification generation in modules/System/Controller/Api.php.ScriptLite provides a sandboxed environment designed for executing untrusted user code safely. The sandbox enforces the following restrictions:
require, import, or file I/O.fetch, XMLHttpRequest, or sockets.eval, exec, system, or access to PHP's global scope.process, globalThis, window, or document.$globals parameter.Note: While the sandbox prevents unauthorized access, it does not prevent CPU or memory exhaustion. For untrusted input, you should combine ScriptLite with PHP's set_time_limit() and memory_limit to cap resource usage.
ESQL provides seamless JSON integration for complex data structures:
When passing arrays or objects in the data key of an insert() or update() call, ESQL automatically converts them to JSON strings for storage.
When fetching data, ESQL automatically detects and decodes JSON strings back into PHP arrays or objects. You can control the decoding behavior using the jsonDecodeAssoc option in your query:
jsonDecodeAssoc => true (default): Decodes JSON into associative arrays.jsonDecodeAssoc => false: Decodes JSON into stdClass objects.// Example of automatic encoding during insert
$db->insert([
'table' => 'users',
'data' => [
'name' => 'John',
'settings' => ['theme' => 'dark'] // Auto-encoded to JSON
]
]);
// Example of automatic decoding during select
$user = $db->selectOne('users', [
'conditions' => ['id' => 1],
'jsonDecodeAssoc' => false // Decodes JSON as stdClass objects
]);IndexHybrid is a unified search abstraction layer that provides a consistent interface across multiple search backends. It allows you to switch between backends (like IndexLite or Meilisearch) without changing your application code by providing a unified API for indexing, searching, and faceting.
| Backend | Protocol | Features |
|---|---|---|
| IndexLite | indexlite://path/to/db | Enhanced fuzzy, SQLite FTS5, facets, field boosting |
| Meilisearch | meilisearch://host:port | Typo tolerance, highlights, synonyms, geo search |
Manager instance using a backend-specific protocol.search() method with various options.use IndexHybrid\Manager;
// Initialize
$manager = new Manager('indexlite://storage/search.db');
// Create index
$manager->createIndex('products', ['title', 'description', 'category', 'price']);
// Get index and add data
$index = $manager->index('products');
$index->addDocument('prod1', [
'title' => 'iPhone 15 Pro',
'description' => 'Latest Apple smartphone',
'category' => 'Electronics',
'price' => 999
]);
// Search
$results = $index->search('phone', ['fuzzy' => true]);Engine instance maintains internal LRU (Least Recently Used) caches for parsing, compilation, and transpilation. To benefit from these caches, reuse the same Engine instance across multiple calls.IndexLite provides several fuzzy matching algorithms to handle typos and variations. You can enable fuzzy search by setting 'fuzzy' => true in the search options and optionally specifying an algorithm via 'fuzzy_algorithm'.
Available Algorithms:
fts5: Standard SQLite FTS5 (default)levenshtein: Best for spelling errorsjaro_winkler: Best for names and peopletrigram: Best for partial matchessoundex: Best for pronunciation-based matchinghybrid: Combined scoring for best overall resultsFuzzy Options:
fuzzy_algorithm (string): The algorithm to use.fuzzy_threshold (int): The distance threshold (default: 2).fuzzy_min_score (int): Minimum score for the hybrid algorithm.// Basic fuzzy search (uses hybrid algorithm)
$results = $index->search('iphon', ['fuzzy' => true]);
// Algorithm-specific search with threshold
$results = $index->search('macbok', [
'fuzzy' => true,
'fuzzy_algorithm' => 'levenshtein',
'fuzzy_threshold' => 2
]);
// Hybrid algorithm with custom scoring
$results = $index->search('searh', [
'fuzzy' => true,
'fuzzy_algorithm' => 'hybrid',
'fuzzy_min_score' => 70,
'fuzzy_threshold' => 2
]);ScriptLite supports three primary execution modes, each with different performance characteristics:
eval() (leveraging OPcache/JIT). This is the fastest mode available if the C extension is not installed.ESQL features automatic JSON handling for complex data types.
When passing an array as a value in insert() or update() calls, ESQL automatically encodes it into a JSON string for storage.
When retrieving data, ESQL automatically decodes JSON columns back into PHP arrays.
Client using encodeJson and decodeJson options.jsonDecodeAssoc option in select methods to determine if JSON should be decoded as associative arrays (default) or stdClass objects.// Decode JSON as stdClass objects instead of associative arrays
$user = $db->selectOne('users', [
'conditions' => ['id' => 1],
'jsonDecodeAssoc' => false
]);// Insert user with complex preferences (auto-encoded to JSON)
$db->insert([
'table' => 'users',
'data' => [
'name' => 'John',
'preferences' => [
'ui' => ['theme' => 'dark', 'language' => 'en'],
'notifications' => ['email' => ['newsletters' => true]]
]
]
]);
// Retrieve and work with the data (auto-decoded from JSON)
$user = $db->selectOne('users', ['conditions' => ['name' => 'John']]);
// $user['preferences']['ui']['theme'] === 'dark'If VIPS is enabled, you can use intelligent cropping algorithms to focus on the most important parts of an image using the smartcrop option. This is available via the PHP helper or the REST API.
Available smartcrop modes:
attention - Focuses on areas of visual interest (recommended)entropy - Focuses on high-detail/high-contrast areascentre / center - Crops from the centerlow - Focuses on low-frequency areashigh - Focuses on high-frequency areas// Attention-based smart cropping
$url = $app->helper('asset')->image([
'src' => '/path/to/image.jpg',
'width' => 400,
'height' => 300,
'mode' => 'thumbnail',
'smartcrop' => 'attention'
]);The eventStream helper allows the server to push real-time events to clients. On the client side, these events are accessible via window.AppEventStream.
Server-side usage:
// Add event to stream
$app->helper('eventStream')->add('notify', [
'message' => 'Hello World',
'status' => 'success'
], [
'to' => $userId, // Optional: target specific user
'sessionId' => $sessionId // Optional: target specific session
]);
// Get events since timestamp
$events = $app->helper('eventStream')->getEvents($timestamp);
// Cleanup old events (automatically called)
$app->helper('eventStream')->cleanup();Client-side usage:
// Client-side (automatically initialized)
window.AppEventStream.on('custom-event', function(evt) {
console.log('Received:', evt.data);
});Built-in event types include notify, alert, and logout.
// Add event to stream
$app->helper('eventStream')->add('notify', [
'message' => 'Hello World',
'status' => 'success'
], [
'to' => $userId, // Optional: target specific user
'sessionId' => $sessionId // Optional: target specific session
]);The aggregate() method allows you to process data through a series of pipeline stages.
$match: Filters documents.$group: Groups documents by a key, using accumulators like $sum, $avg, $min, $max, $push, etc.$sort: Sorts results.$project: Reshapes documents (includes/excludes fields).$addFields: Adds new fields to documents.$unwind: Deconstructs an array field into multiple documents.$lookup: Performs left outer joins to other collections.$out / $merge: Exports or merges results into a collection.$geoNear: (Must be first stage) Performs proximity searches.$analytics = $collection->aggregate([
['$match' => ['status' => 'active']],
['$group' => [
'_id' => '$department',
'employee_count' => ['$sum' => 1],
'avg_salary' => ['$avg' => '$salary']
]],
['$sort' => ['avg_salary' => -1]],
['$out' => 'department_analytics']
])->toArray();To ensure high performance, leverage the automatic Query Optimizer by using top-level field queries and standard comparison operators.
Optimized (Fast):
['status' => 'active'])$eq, $ne, $gt, $gte, $lt, $lte$in, $nin$exists, $type, $size$and, $orSlower (Falls back to PHP processing):
$regex)meta.rating)users.name)Best Practices:
find($criteria, ['field' => 1]).$match stages before $group or $sort.skip() and limit() to handle large datasets.while loop with skip() and limit() to process data in batches to manage memory.// Example of efficient pagination/chunking
$offset = 0;
$limit = 1000;
while (true) {
$batch = $collection->find($criteria)
->skip($offset)
->limit($limit)
->toArray();
if (empty($batch)) break;
// Process batch...
$offset += $limit;
}