PHP code example of omoba / laravel-queryable

1. Go to this page and download the library: Download omoba/laravel-queryable library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

omoba / laravel-queryable example snippets


User::search('john')
    ->filter([
        'status'           => 'active,pending',
        'created_at'       => ['from' => '2025-01-01', 'to' => '2025-12-31'],
        'company.industry' => 'fintech',
    ])
    ->sort('-created_at,name')
    ->paginate();

use Omoba\LaravelQueryable\Concerns\Queryable;
use Omoba\LaravelQueryable\Operators\FilterOperator;

class User extends Model
{
    use Queryable;

    public function searchable(): array
    {
        return ['name', 'email', 'company.name'];
    }

    public function filterable(): array
    {
        return [
            'status'     => FilterOperator::In,
            'created_at' => FilterOperator::DateRange,
        ];
    }

    public function sortable(): array
    {
        return ['name', 'created_at'];
    }
}

public function index(Request $request): JsonResponse
{
    return response()->json(
        User::query()
            ->search($request->string('q')->toString() ?: null)
            ->filter($request->array('filter'))
            ->sort($request->string('sort')->toString() ?: null)
            ->paginate($request->integer('per_page', 25))
    );
}

use Omoba\LaravelQueryable\Concerns\Filterable;
use Omoba\LaravelQueryable\Concerns\Sortable;

class Product extends Model
{
    use Filterable, Sortable;

    // No searchable() needed — Searchable trait is not used
}

public function searchable(): array
{
    return [
        'name',
        'email',
        'company.name',        // one level deep
        'team.company.name',   // two levels deep
    ];
}

public function searchableEncrypted(): array
{
    return ['phone_hash'];
}

public function hashSearchTerm(string $term): string
{
    return hash('sha256', strtolower(trim($term)));
}

public function filterable(): array
{
    return [
        // Explicit operator via enum
        'name'             => FilterOperator::Like,
        'email'            => FilterOperator::Exact,
        'status'           => FilterOperator::In,
        'created_at'       => FilterOperator::DateRange,
        'archived_at'      => FilterOperator::Null,
        'amount'           => FilterOperator::Gte,

        // Explicit operator via string (case-insensitive)
        'score'            => 'gte',

        // No operator — inferred from the incoming value shape at runtime
        'category',
        'updated_at',
    ];
}

public function filterable(): array
{
    return [
        'company.industry' => FilterOperator::Exact,
        'team.company.name' => FilterOperator::Like,
    ];
}

public function having(): array
{
    return [
        'posts_count' => FilterOperator::Between,
    ];
}

public function sortable(): array
{
    return ['name', 'created_at', 'email'];
}

User::search('john')->get();
// WHERE (name LIKE '%john%' OR email LIKE '%john%' OR EXISTS (SELECT ... company.name LIKE '%john%'))

User::searchEncrypted('+15550100')->first();
// WHERE phone_hash = 'a1b2c3...'

User::filter([
    'status'     => 'active',
    'created_at' => ['from' => '2025-01-01', 'to' => '2025-12-31'],
])->get();

User::withCount('posts')
    ->filterHaving(['posts_count' => ['from' => 5]])
    ->get();
// HAVING posts_count >= 5

// String form — prefix with '-' for descending
User::sort('-created_at,name')->get();
// ORDER BY created_at DESC, name ASC

// Associative array
User::sort(['created_at' => 'desc', 'name' => 'asc'])->get();

// Indexed array
User::sort(['-created_at', 'name'])->get();

public function searchable(): array
{
    return [
        'name',
        'company.name',           // whereHas('company', fn($q) => $q->orWhere('name', ...))
        'team.company.name',      // whereHas('team.company', fn($q) => $q->orWhere('name', ...))
    ];
}

public function filterable(): array
{
    return [
        'company.industry'  => FilterOperator::Exact,
        'team.company.name' => FilterOperator::Like,
    ];
}

// config/queryable.php
return ['strict' => false];

// or in .env
QUERYABLE_STRICT=false

User::query()
    ->whereNotNull('email_verified_at')
    ->with(['company', 'profile'])
    ->search($request->string('q')->toString() ?: null)
    ->filter($request->array('filter'))
    ->sort($request->string('sort')->toString() ?: null)
    ->paginate(25);

User::query()
    ->withCount('posts')
    ->search($request->string('q')->toString() ?: null)
    ->filter($request->array('filter'))
    ->filterHaving($request->array('having'))
    ->sort($request->string('sort')->toString() ?: null)
    ->paginate(25);

use Omoba\LaravelQueryable\Concerns\Queryable;
use Omoba\LaravelQueryable\Operators\FilterOperator;

class Transaction extends Model
{
    use Queryable;

    public function searchable(): array
    {
        return ['reference', 'pocket.user.email', 'pocket.user.first_name'];
    }

    public function searchableEncrypted(): array
    {
        return [];
    }

    public function filterable(): array
    {
        return [
            'type'       => FilterOperator::Exact,
            'category'   => FilterOperator::Exact,
            'status'     => FilterOperator::In,
            'created_at' => FilterOperator::DateRange,
            'amount'     => FilterOperator::Gte,
        ];
    }

    public function sortable(): array
    {
        return ['created_at', 'amount'];
    }
}

public function index(Request $request): JsonResponse
{
    $transactions = Transaction::query()
        ->search($request->string('q')->toString() ?: null)
        ->filter($request->array('filter'))
        ->sort($request->string('sort')->toString() ?: null)
        ->with('pocket.user')
        ->paginate($request->integer('per_page', 25));

    return response()->json($transactions);
}
bash
php artisan vendor:publish --tag=queryable-config