Beartropy Tables

Models & Eloquent
Use Eloquent models for server-side pagination, searching, sorting, and relationship support — all out of the box.

Using Models

Define the $model property to enable Eloquent mode instead of the data() method.

Basic Eloquent Setup

Set public $model = User::class to enable Eloquent mode. This gives you automatic server-side pagination, searching, and sorting directly on the database.

Eager Loading: Define public $with to preload relationships and avoid N+1 query issues.

1class UsersTable extends YATBaseTable
2{
3 // Enable Eloquent mode by defining the model
4 public $model = User::class;
5 
6 // Eager load relationships to avoid N+1 issues
7 public $with = ['role', 'settings'];
8 
9 public function columns(): array {
10 return [
11 // Use dot notation to access related data
12 Column::make('Role', 'role.name'),
13 
14 // Search works automatically on related columns
15 Column::make('Email', 'email'),
16 ];
17 }
18}

Model vs data()

When $model is defined, you don't need the data() method. The table queries the model automatically. Use data() only for array/collection-based tables.

Relationships

Access related model data using dot notation and eager loading.

Relationship Types

  • BelongsTo / HasOne: Use dot notation directly (e.g., role.name, profile.bio).
  • HasMany: Use customData() to extract specific values from a collection (e.g., getting a setting from a settings collection).

Always eager load

Define public $with = ['relation'] or public array $with = ['relation'] for every relationship you access in columns. This prevents N+1 queries and significantly improves performance.

Advanced Column Logic

Custom sorting and searching for computed columns and complex relationships.

Custom Sort & Search

For columns that don't map directly to a database column, pass closures to sortable() and searchable() for full query builder control.

1Column::make('Theme', 'theme_setting')
2 ->customData(fn($row) => $row->settings->firstWhere('key', 'theme')?->value)
3 ->sortable(function($query, $direction) {
4 $query->orderBy(
5 UserSetting::select('value')
6 ->whereColumn('user_settings.user_id', 'users.id')
7 ->where('key', 'theme'),
8 $direction
9 );
10 })
11 ->searchable(function($query, $term) {
12 $query->orWhereHas('settings', function($q) use ($term) {
13 $q->where('key', 'theme')->where('value', 'like', "%$term%");
14 });
15 });

Filter Relationships

Two approaches for filtering by related model data.

Custom Filter Logic

->query(callable $callback) — Override default filter logic for full control. When using the callback, the default filtering is skipped entirely.

1FilterString::make('Name')
2 ->query(function($query, $value) {
3 $query->where('custom_col', 'like', "%$value%")
4 ->orWhere('other_col', 'like', "%$value%");
5 })

Relationship Filters

Dot Notation: If the Eloquent relationship exists, use dot notation (e.g., profile.bio) and the table handles joins automatically.

Custom Query: For complex relationships (like filtering a specific key in a HasMany), use the query() callback.

1// Dot notation — auto-handled relation join
2FilterSelect::make('Bio', \App\Models\Profile::distinct()->pluck('bio')->toArray(), 'profile.bio'),
3 
4// Custom query — for complex relationship filtering
5FilterSelect::make('Theme', UserSetting::where('key','theme')->distinct()->pluck('value')->toArray(), 'theme_setting')
6 ->query(function($query, $value, $filter) {
7 $query->whereHas('settings', function($q) use ($value) {
8 $q->where('key', 'theme')->where('value', 'like', "%$value%");
9 });
10 })

Complete Example

A playground table with eager-loaded relationships, dot-notation columns, and relationship filters.

RelationshipUsersTable.php

This example eager-loads three relationships (profile, plataforma, settings), uses dot notation for columns, and implements custom query filters for related data.

1use App\Models\User;
2use Beartropy\Tables\Classes\Columns\Column;
3use Beartropy\Tables\Classes\Columns\DateColumn;
4use Beartropy\Tables\Classes\Filters\FilterSelect;
5use Beartropy\Tables\Classes\Filters\FilterString;
6use Beartropy\Tables\YATBaseTable;
7 
8class RelationshipUsersTable extends YATBaseTable
9{
10 public $model = User::class;
11 
12 public array $with = ['profile', 'plataforma', 'settings'];
13 
14 public function columns(): array
15 {
16 return [
17 Column::make('Name', 'name')->sortable()->searchable(),
18 Column::make('Email', 'email')->sortable()->searchable(),
19 Column::make('Platform', 'plataforma.name')
20 ->sortable(false)->searchable(),
21 Column::make('Bio', 'profile.bio')
22 ->sortable(false)->searchable(),
23 Column::make('Settings')->sortable(false)->searchable(false),
24 DateColumn::make('Created', 'created_at')
25 ->outputFormat('M d, Y'),
26 ];
27 }
28 
29 public function filters(): array
30 {
31 $plataformas = \App\Models\Plataforma::pluck('name', 'id')->toArray();
32 
33 return [
34 FilterString::make('Name', 'name'),
35 FilterSelect::make('Platform', $plataformas)
36 ->query(function ($query, $value) {
37 $query->whereHas('plataforma', function ($q) use ($value) {
38 $q->where('id', $value);
39 });
40 }),
41 FilterString::make('Bio')
42 ->query(function ($query, $value) {
43 $query->whereHas('profile', function ($q) use ($value) {
44 $q->where('bio', 'like', "%{$value}%");
45 });
46 }),
47 ];
48 }
49 
50 public function settings(): void
51 {
52 $this->setPerPageDefault(15);
53 }
54}
Beartropy Logo

© 2026 Beartropy. All rights reserved.

Provided as-is, without warranty. Use at your own risk.