PHP code example of behindsolution / laragrep

1. Go to this page and download the library: Download behindsolution/laragrep 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/ */

    

behindsolution / laragrep example snippets


'connections' => [
    // ... your existing connections

    'laragrep' => [
        'driver' => 'sqlite',
        'database' => database_path('laragrep.sqlite'),
        'foreign_key_constraints' => true,
    ],
],

use LaraGrep\Config\Table;
use LaraGrep\Config\Column;
use LaraGrep\Config\Relationship;

'contexts' => [
    'default' => [
        // ...
        'tables' => [
            Table::make('users')
                ->description('Registered users.')
                ->columns([
                    Column::id(),
                    Column::string('name'),
                    Column::string('email'),
                    Column::timestamp('created_at'),
                ]),

            Table::make('orders')
                ->description('Customer orders.')
                ->columns([
                    Column::id(),
                    Column::bigInteger('user_id')->unsigned(),
                    Column::decimal('total', 10, 2),
                    Column::enum('status', ['pending', 'paid', 'cancelled']),
                    Column::timestamp('created_at'),
                ])
                ->relationships([
                    Relationship::belongsTo('users', 'user_id'),
                ]),
        ],
    ],
],

// config/laragrep.php
'monitor' => [
    'enabled' => true,
    'middleware' => ['auth:sanctum'],
],

Broadcast::channel('laragrep.{queryId}', function ($user, $queryId) {
    return true; // your authorization logic
});

// app/Http/Middleware/ConfigureLaraGrep.php
public function handle(Request $request, Closure $next)
{
    $tenant = tenant();

    config()->set('laragrep.provider', $tenant->ai_provider);   // 'openai' or 'anthropic'
    config()->set('laragrep.api_key',  $tenant->ai_api_key);
    config()->set('laragrep.model',    $tenant->ai_model);
    config()->set('laragrep.user_language', $tenant->locale);

    // Optional fallback per tenant
    config()->set('laragrep.fallback.provider', $tenant->ai_fallback_provider);
    config()->set('laragrep.fallback.api_key',  $tenant->ai_fallback_api_key);
    config()->set('laragrep.fallback.model',    $tenant->ai_fallback_model);

    return $next($request);
}

use LaraGrep\Config\Table;
use LaraGrep\Config\Column;
use LaraGrep\Config\Relationship;

Table::make('orders')
    ->description('Customer orders.')
    ->columns([
        Column::id(),
        Column::bigInteger('user_id')->unsigned()->description('FK to users.id.'),
        Column::decimal('total', 10, 2)->description('Order total.'),
        Column::enum('status', ['pending', 'paid', 'cancelled']),
        Column::json('metadata')
            ->description('Order metadata')
            ->template(['shipping_method' => 'express', 'tracking_code' => 'BR123456789']),
        Column::timestamp('created_at'),
    ])
    ->relationships([
        Relationship::belongsTo('users', 'user_id'),
    ]),

// app/LaraGrep/Tables/OrdersTable.php
namespace App\LaraGrep\Tables;

use LaraGrep\Config\Table;
use LaraGrep\Config\Column;
use LaraGrep\Config\Relationship;

class OrdersTable
{
    public static function define(): Table
    {
        return Table::make('orders')
            ->description('Customer orders.')
            ->columns([
                Column::id(),
                Column::bigInteger('user_id')->unsigned(),
                Column::decimal('total', 10, 2),
                Column::timestamp('created_at'),
            ])
            ->relationships([
                Relationship::belongsTo('users', 'user_id'),
            ]);
    }
}

// config/laragrep.php
'tables' => [
    \App\LaraGrep\Tables\UsersTable::define(),
    \App\LaraGrep\Tables\OrdersTable::define(),
    \App\LaraGrep\Tables\ProductsTable::define(),
],

'tables' => [
    Table::make('users')
        ->description('Registered users.')
        ->columns([
            Column::id(),
            Column::string('name'),
            Column::string('email'),
        ]),

    Table::make('analytics_events')
        ->description('Columnar analytics store.')
        ->connection('clickhouse', 'ClickHouse')
        ->columns([
            Column::string('event_name'),
            Column::timestamp('event_time'),
            Column::bigInteger('user_id'),
        ]),
],

// Connection only (same engine as the primary database)
->connection('replica')

// Connection + engine (different SQL dialect)
->connection('clickhouse', 'ClickHouse')

'contexts' => [
    'default' => [
        'connection' => fn () => 'tenant_' . tenant()->id,
        'tables' => [
            Table::make('users')->columns([...]),
            Table::make('orders')->columns([...]),
        ],
    ],
],

'contexts' => [
    'default' => [
        'connection' => fn () => app('tenant')->getConnectionName(),
        'tables' => [
            Table::make('orders')->columns([...]),

            Table::make('plans')
                ->connection('central')
                ->columns([...]),
        ],
    ],
],

Table::make('orders')->connection(fn () => 'tenant_' . tenant()->id)

'contexts' => [
    'default' => [
        'connection' => env('LARAGREP_CONNECTION'),
        'tables' => [...],
    ],
    'analytics' => [
        'connection' => 'analytics_db',
        'schema_mode' => 'auto',
        'database' => ['type' => 'MariaDB 10.6', 'name' => 'analytics'],
        'exclude_tables' => ['migrations', 'jobs'],
    ],
],

'contexts' => [
    'default' => [
        'clarification_rules' => [
            'Always ask for a date range when the question involves time-based data',
            'Always ask which store/branch if not specified',
        ],
        'tables' => [...],
    ],
],

$laraGrep = app(LaraGrep::class);

// Pass conversationId so the AI considers conversation history
$clarification = $laraGrep->clarifyQuestion('Show me the sales', 'default', $conversationId);

if ($clarification !== null) {
    // Collect answers from the user, then reformulate
    $reformulated = $laraGrep->reformulateQuestion(
        'Show me the sales',
        [
            ['question' => 'What date range?', 'answer' => 'January 2026'],
            ['question' => 'Which store?', 'answer' => 'Store Centro'],
        ],
        'default',
    );

    $answer = $laraGrep->answerQuestion($reformulated);
} else {
    // Question is clear — proceed normally
    $answer = $laraGrep->answerQuestion('Show me the sales');
}

'contexts' => [
    'default' => [
        'suggestions' => [
            ['label' => 'Incidents Dashboard', 'description' => 'Shows incidents per company with period filters', 'url' => '/dashboard/incidents'],
            ['label' => 'Monthly Sales Report', 'description' => 'Pre-built report with sales by region and product', 'url' => '/reports/sales'],
        ],
        'clarification_rules' => [...],
        'tables' => [...],
    ],
],

'contexts' => [
    'default' => [
        'answer_guard_rules' => [
            'Never mention internal database table or column names',
            'Never expose tenant names or IDs from other clients',
            'Never reveal raw SQL queries or technical database details',
        ],
        'tables' => [...],
    ],
],

$laraGrep = app(LaraGrep::class);

// Already applied automatically by answerQuestion(); call directly to
// guard text generated outside the agent loop (e.g., a custom message
// you want to sanitize against the same rules).
$safe = $laraGrep->guardAnswer('Raw answer with sensitive details', 'default');

'contexts' => [
    'default' => [
        'global_filters' => function () {
            $user = auth()->user();

            // Sem user, central, ou rota admin → sem filtro
            if (!$user || $user->isCentral() || request()->is('api/admin/*')) {
                return [];
            }

            $assetIds   = implode(',', array_map('intval', $user->visibleAssetIds()));
            $companyId  = (int) $user->company_id;

            return [
                'assets'    => "(assets.id IN ({$assetIds}) OR assets.company_id != {$companyId})",
                'incidents' => "EXISTS (SELECT 1 FROM job_sessions js WHERE js.id = incidents.job_session_id AND js.company_id = {$companyId})",
            ];
        },
        'tables' => [...],
    ],
],

$laraGrep->answerQuestion(
    question: $question,
    scope: 'default',
    globalFilters: ['assets' => '...'],   // overrides the config closure
);

'route' => [
    'prefix' => 'laragrep',
    'middleware' => ['auth:sanctum'],
],

use LaraGrep\LaraGrep;

$laraGrep = app(LaraGrep::class);

$answer = $laraGrep->answerQuestion(
    question: 'How many orders were placed today?',
    scope: 'default',
);

echo $answer['summary'];

$answer = $laraGrep->answerQuestion('Weekly sales by region');

$result = $laraGrep->formatResult($answer, 'query');
// [
//     'title' => 'Weekly Sales by Region',
//     'headers' => ['Region', 'Total Sales', 'Order Count'],
//     'query' => 'SELECT r.name as region, SUM(o.total) ... GROUP BY r.name',
//     'bindings' => ['2026-02-01'],
// ]

// Stream with cursor
foreach (DB::cursor($result['query'], $result['bindings']) as $row) {
    // process row
}

// Chunk for batch processing
DB::table(DB::raw("({$result['query']}) as sub"))
    ->setBindings($result['bindings'])
    ->chunk(1000, function ($rows) {
        // process chunk
    });

$notification = $laraGrep->formatResult($answer, 'notification');
// [
//     'title' => 'Weekly Sales Report',
//     'html' => '<p>Sales this week totaled...</p><table>...</table>',
//     'text' => 'Sales this week totaled...\nProduct | Revenue...',
// ]

// app/Listeners/HandleRecipeDispatch.php
use LaraGrep\Events\RecipeDispatched;

public function handle(RecipeDispatched $event)
{
    $job = new ProcessRecipeJob($event->recipe, $event->format, $event->userId);

    if ($event->period === 'now') {
        dispatch($job);
    } else {
        dispatch($job)->delay(Carbon::parse($event->period));
    }
}

// app/Jobs/ProcessRecipeJob.php
use LaraGrep\LaraGrep;

public function handle(LaraGrep $laraGrep)
{
    $answer = $laraGrep->replayRecipe($this->recipe);
    $result = $laraGrep->formatResult($answer, $this->format);

    // Send email, generate Excel, post to Slack, etc.
}

use LaraGrep\LaraGrep;

$laraGrep = app(LaraGrep::class);

// First run
$answer = $laraGrep->answerQuestion('Weekly sales by region');
$recipe = $laraGrep->extractRecipe($answer, 'Weekly sales by region', 'default');

// Later — replay with fresh data
$freshAnswer = $laraGrep->replayRecipe($recipe);
$notification = $laraGrep->formatResult($freshAnswer, 'notification');

$this->app->singleton(AiClientInterface::class, fn () => new MyCustomClient());

$this->app->singleton(MetadataLoaderInterface::class, fn ($app) => new MySqliteSchemaLoader($app['db']));

$this->app->singleton(ConversationStoreInterface::class, fn () => new RedisConversationStore());
bash
php artisan vendor:publish --tag=laragrep-config
php artisan vendor:publish --tag=laragrep-migrations
bash
php artisan migrate

POST /laragrep/{scope?}