New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

act-training/query-builder

Package Overview
Dependencies
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

act-training/query-builder

A drop in query builder for Laravel models.

Source
Packagist
Version
2.4.1
Version published
Total downloads
10K
Maintainers
1
Created
Source

Query Builder for Laravel

Drop-in Livewire components for building query builders, tables, and reports on Eloquent models.

Installation

composer require act-training/query-builder

Optionally, publish the views:

php artisan vendor:publish --tag="query-builder-views"

Model Setup

Models should use the AppliesCriteria trait:

use ACTTraining\QueryBuilder\Support\Criteria\AppliesCriteria;

class Employee extends Model
{
    use AppliesCriteria;
}

Components

The package provides three main abstract Livewire components to extend:

ComponentPurpose
QueryBuilderFull query builder with criteria-based AND/OR filtering
TableBuilderSimpler table with URL-persisted filters and search
ReportBuilderDynamic column selection, save/load/export, optional groupBy

QueryBuilder

Create a Livewire component that extends QueryBuilder. Define query(), columns(), and conditions():

<?php

namespace App\Livewire;

use ACTTraining\QueryBuilder\QueryBuilder;
use ACTTraining\QueryBuilder\Support\Columns\BooleanColumn;
use ACTTraining\QueryBuilder\Support\Columns\Column;
use ACTTraining\QueryBuilder\Support\Columns\DateColumn;
use ACTTraining\QueryBuilder\Support\Conditions\BooleanCondition;
use ACTTraining\QueryBuilder\Support\Conditions\DateCondition;
use ACTTraining\QueryBuilder\Support\Conditions\TextCondition;
use App\Models\Employee;
use Illuminate\Database\Eloquent\Builder;

class EmployeesTable extends QueryBuilder
{
    public function config(): void
    {
        $this
            ->enableQueryBuilder()
            ->rowClickable(false);
    }

    public function query(): Builder
    {
        return Employee::query()->with(['contract', 'contract.job', 'contract.location']);
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'full_name')
                ->component('columns.common.title')
                ->sortable(),
            Column::make('Job Title', 'contract.job.name'),
            Column::make('Location', 'contract.location.name'),
            BooleanColumn::make('Line Manager', 'contract.line_manager')
                ->hideIf(false)
                ->justify('center'),
            DateColumn::make('Start Date', 'contract.start_date')
                ->humanDiff()
                ->justify('right'),
        ];
    }

    public function conditions(): array
    {
        return [
            TextCondition::make('Name', 'full_name'),
            TextCondition::make('Job Title', 'contract.job.name'),
            BooleanCondition::make('Line Manager', 'contract.line_manager'),
            TextCondition::make('Location', 'contract.location.name'),
            DateCondition::make('Start Date', 'contract.start_date'),
        ];
    }
}

TableBuilder

A simpler alternative using filters instead of criteria. Define query(), columns(), and filters():

<?php

namespace App\Livewire;

use ACTTraining\QueryBuilder\TableBuilder;
use ACTTraining\QueryBuilder\Support\Columns\Column;
use ACTTraining\QueryBuilder\Support\Filters\TextFilter;
use ACTTraining\QueryBuilder\Support\Filters\SelectFilter;
use App\Models\Employee;
use Illuminate\Database\Eloquent\Builder;

class EmployeesList extends TableBuilder
{
    public function query(): Builder
    {
        return Employee::query();
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'full_name')->sortable()->searchable(),
            Column::make('Department', 'department')->sortable(),
        ];
    }

    public function filters(): array
    {
        return [
            TextFilter::make('Name', 'full_name'),
            SelectFilter::make('Department', 'department')
                ->options(['HR' => 'HR', 'IT' => 'IT', 'Finance' => 'Finance']),
        ];
    }
}

ReportBuilder

Extends QueryBuilder with dynamic column selection. Users pick columns at runtime from availableColumns(), and the component builds columns and conditions automatically:

<?php

namespace App\Livewire;

use ACTTraining\QueryBuilder\ReportBuilder;
use App\Models\Employee;
use Illuminate\Database\Eloquent\Builder;

class EmployeesReport extends ReportBuilder
{
    public function query(): Builder
    {
        return Employee::query()->with(['contract', 'contract.job', 'contract.location']);
    }

    public function availableColumns(): array
    {
        return [
            'Employee' => [
                ['label' => 'Name', 'key' => 'full_name'],
                ['label' => 'Email', 'key' => 'email'],
            ],
            'Contract' => [
                ['label' => 'Job Title', 'key' => 'contract.job.name'],
                ['label' => 'Location', 'key' => 'contract.location.name'],
                ['label' => 'Start Date', 'key' => 'contract.start_date', 'type' => 'date'],
                ['label' => 'Salary', 'key' => 'contract.salary', 'type' => 'number'],
                ['label' => 'Line Manager', 'key' => 'contract.line_manager', 'type' => 'boolean'],
            ],
        ];
    }
}

Column definitions in availableColumns() support these keys:

KeyDescription
labelDisplay label (required)
keyColumn key, supports dot-notation for relationships (required)
typeColumn type: text (default), number, float, boolean, date, enum, null, view
sortableEnable sorting on this column
justifyAlignment: left, center, right
viewCustom Blade component for rendering
optionsOptions array for enum type
skipConditionExclude from query builder conditions

ReportBuilder with GroupBy

Enable groupBy to allow users to group results by a column with aggregate functions (COUNT, SUM, AVG, MIN, MAX). Set $enableGroupBy = true:

<?php

namespace App\Livewire;

use ACTTraining\QueryBuilder\ReportBuilder;
use App\Models\Employee;
use Illuminate\Database\Eloquent\Builder;

class EmployeesGroupReport extends ReportBuilder
{
    public bool $enableGroupBy = true;

    public function query(): Builder
    {
        return Employee::query()->with(['contract', 'contract.job', 'contract.location']);
    }

    public function availableColumns(): array
    {
        return [
            'Employee' => [
                ['label' => 'Name', 'key' => 'full_name'],
                ['label' => 'Department', 'key' => 'department'],
            ],
            'Contract' => [
                ['label' => 'Job Title', 'key' => 'contract.job.name'],
                ['label' => 'Location', 'key' => 'contract.location.name'],
                ['label' => 'Salary', 'key' => 'contract.salary', 'type' => 'number'],
            ],
        ];
    }
}

When enableGroupBy is true, the report editor UI shows additional controls:

  • Group By Column - select which column to group by
  • Function - aggregate function (COUNT, SUM, AVG, MIN, MAX)
  • Aggregate Column - which column to aggregate (defaults to id, numeric columns from availableColumns() are included automatically)

An "Aggregate" column is automatically appended to the table when grouping is active.

You can customise the available aggregate functions and groupable/aggregatable columns by overriding:

public function aggregateFunctions(): array
{
    return ['COUNT', 'SUM', 'AVG'];
}

public function groupableColumns(): array
{
    // Return a flat array of ['label' => ..., 'key' => ...] items
    return [
        ['label' => 'Department', 'key' => 'department'],
        ['label' => 'Location', 'key' => 'contract.location.name'],
    ];
}

public function aggregatableColumns(): array
{
    return [
        ['label' => 'ID', 'key' => 'id'],
        ['label' => 'Salary', 'key' => 'contract.salary'],
    ];
}

Columns

All column types use a fluent make($label, $key) constructor. If $key is omitted, it defaults to Str::snake($label).

Column TypeDescription
ColumnGeneral text column
BooleanColumnBoolean/checkbox display
DateColumnDate formatting with ->format() and ->humanDiff()
ViewColumnCustom Blade view rendering

Columns support: ->sortable(), ->searchable(), ->justify('right'), ->component('view.name'), ->reformatUsing(callable), ->withSubTitle(callable), ->hideIf(condition), ->hideHeader().

Conditions (QueryBuilder)

Used with QueryBuilder and ReportBuilder for criteria-based filtering:

Condition TypeOperations
TextConditionequals, not_equals, contains, starts_with, ends_with
NumberConditionequals, not_equals, greater_than, less_than, is_between
FloatConditionequals, not_equals, greater_than, less_than, is_between
BooleanConditionis_true, is_false
DateConditionequals, before, after, is_between
EnumConditionequals, not_equals (with defined options)
NullConditionis_set, is_not_set

Filters (TableBuilder)

Used with TableBuilder for simpler key/operator/value filtering:

TextFilter, NumberFilter, DateFilter, BooleanFilter, SelectFilter, NullFilter

Relationship Support

Dot-notation keys work throughout columns, conditions, and filters to traverse Eloquent relationships:

Column::make('Job Title', 'contract.job.name')
TextCondition::make('Location', 'contract.location.name')

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

Keywords

laravel

FAQs

Package last updated on 10 Jun 2026

Related posts