1. High-Level Architectural Summary
Zero CMS features an advanced, 100% decoupled **Search Index and Driver Architecture**. Moving away from slow, un-indexed cross-table dynamic lookups, the system compiles searchable content into a dedicated search_index database table in real-time. This index-based search guarantees ultra-fast query execution, scales gracefully under heavy traffic, enforces strict multi-tenant boundary scoping, and supports weighted **Title-Hit Boosting** to ensure that relevance ranking prioritizes exact and partial title matches.
2. Decoupled Search Drivers
By utilizing a driver interface model, the search core is fully decoupled from the underlying index storage. This allows administrators to hot-swap search drivers based on environment variables (e.g., swapping from standard MySQL matching to Elasticsearch or Algolia) without modifying any application controller code.
# Configure active search index driver (defaults to database)
SEARCH_DRIVER=database3. The Hybrid Block Helper Model (No N+1 Queries)
A critical architectural mandate of Zero CMS is the **absolute prevention of N+1 database queries**. When extracting search text from page-builder layouts (which are saved as structured JSON arrays of blocks), instantiating full layout renderers or calling individual database hooks for block assets would trigger a catastrophic N+1 query loop. To prevent this, Zero CMS implements a **Hybrid Block Helper Model**:
- OOP Block Helpers: Blocks implement a standard
BlockHelperInterface, acting as lightweight, in-memory data-transfer objects that extract searchable plain text from JSON attributes with zero database queries. - Recursive Fallback Scanner: If a custom block does not have a specialized helper class defined, the indexing engine automatically falls back to an intelligent recursive array scanner, keeping the search index 100% self-healing and backward-compatible.
4. Developer How-To: Implementing Searchable Models
namespace Zero\Custom\Models;
class CustomBook implements Model
{
// 1. Import Searchable Trait alongside standard active-record IsModel
use IsModel, Searchable;
protected static $tableName = 'custom_books';
protected static $modelType = 'book';
// 2. Include 'exclude_from_search' in DB and fillables
protected static $fillable = ['title', 'content', 'status', 'exclude_from_search'];
public $exclude_from_search = 0;
public $status;
}
5. Developer How-To: Creating Custom Block Helpers
namespace Zero\Blocks;
class ProductShowcaseBlock implements BlockHelperInterface
{
protected array $data;
public function __construct(array $data)
{
$this->data = $data;
}
/**
* Compile plain text content from block parameters with 0 database hits.
*/
public function getSearchableContent(): string
{
$parts = [];
if (!empty($this->data['heading'])) {
$parts[] = $this->data['heading'];
}
if (!empty($this->data['product_name'])) {
$parts[] = $this->data['product_name'];
}
if (!empty($this->data['description'])) {
$parts[] = strip_tags($this->data['description']);
}
return implode(' ', $parts);
}
}