Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Datatables Fractal Laravel Package

yajra/laravel-datatables-fractal

Laravel DataTables plugin that transforms server-side JSON responses using League Fractal. Adds Fractal integration to yajra/laravel-datatables for cleaner, consistent API output. Supports PHP 8.2+ and Laravel 12.x.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require yajra/laravel-datatables-fractal:^12.0
    
  2. Publish config (optional):

    php artisan vendor:publish --tag=datatables-fractal
    

    (Auto-registers service provider in Laravel 5.5+)

  3. First use case: Create a Fractal transformer for your model (e.g., app/Transformers/UserTransformer.php):

    namespace App\Transformers;
    
    use App\Models\User;
    use League\Fractal\TransformerAbstract;
    
    class UserTransformer extends TransformerAbstract
    {
        public function transform(User $user)
        {
            return [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'created_at' => $user->created_at->format('Y-m-d'),
            ];
        }
    }
    
  4. Integrate with DataTables: In your controller:

    use Yajra\DataTables\Facades\DataTables;
    use App\Transformers\UserTransformer;
    
    public function anyData()
    {
        return DataTables::of(User::query())
            ->transformer(new UserTransformer)
            ->make(true);
    }
    
  5. Frontend integration: Use DataTables with the standard AJAX source:

    $('#user-table').DataTable({
        processing: true,
        serverSide: true,
        ajax: '/users/data'
    });
    

Implementation Patterns

Core Workflows

  1. Transformer-Based Responses:

    • Pattern: Use transformers for all DataTables responses to enforce consistency.
    • Example: Extend TransformerAbstract and define transform() for each model.
    • Best Practice: Group transformers in app/Transformers/ and use dependency injection.
  2. Dynamic Includes/Fields:

    • Pattern: Leverage Fractal’s include and fields parameters for flexible data fetching.
    • Usage:
      return DataTables::of(User::query())
          ->include('posts') // Eager loads 'posts' relationship
          ->fields(['users' => ['id', 'name']]) // Limits fields for 'users'
          ->transformer(new UserTransformer)
          ->make(true);
      
    • Frontend: Append ?include=posts&fields[users]=id,name to AJAX URLs.
  3. Nested Transformers:

    • Pattern: Chain transformers for complex relationships.
    • Example:
      class UserTransformer extends TransformerAbstract
      {
          public function transform(User $user)
          {
              return [
                  'id' => $user->id,
                  'posts' => $this->transformPosts($user->posts),
              ];
          }
      
          protected function transformPosts($posts)
          {
              return PostTransformer::transformCollection($posts);
          }
      }
      
  4. Controller Integration:

    • Pattern: Use a base controller trait for DRY code.
    • Example:
      use Yajra\DataTables\Facades\DataTables;
      
      trait DataTablesTrait
      {
          protected function respondWithDataTable($query, $transformer)
          {
              return DataTables::of($query)
                  ->transformer($transformer)
                  ->make(true);
          }
      }
      
    • Usage:
      class UserController extends Controller
      {
          use DataTablesTrait;
      
          public function data()
          {
              return $this->respondWithDataTable(User::query(), new UserTransformer);
          }
      }
      
  5. API Resource Compatibility:

    • Pattern: Reuse existing API Resources as transformers.
    • Example:
      use App\Http\Resources\User as UserResource;
      
      return DataTables::of(User::query())
          ->transformer(function ($user) {
              return UserResource::make($user);
          })
          ->make(true);
      
  6. Pagination Customization:

    • Pattern: Override default pagination metadata.
    • Example:
      return DataTables::of(User::query())
          ->transformer(new UserTransformer)
          ->addColumn('custom_meta', function ($user) {
              return ['key' => 'value'];
          })
          ->make(true);
      

Integration Tips

  1. Route Grouping: Use route groups for DataTables endpoints:

    Route::prefix('api')->group(function () {
        Route::get('/users/data', [UserController::class, 'data']);
    });
    
  2. Middleware: Apply auth/role middleware to DataTables routes:

    Route::middleware(['auth:sanctum'])->group(function () {
        Route::get('/admin/users/data', [AdminUserController::class, 'data']);
    });
    
  3. Testing:

    • Use DataTablesTestCase for testing:
      use Yajra\DataTables\Tests\TestCase as DataTablesTestCase;
      
      class UserDataTableTest extends DataTablesTestCase
      {
          public function test_returns_transformed_data()
          {
              $response = $this->get('/users/data');
              $response->assertJsonStructure([
                  'data' => [[
                      'id', 'name', 'email'
                  ]],
                  'recordsTotal', 'recordsFiltered'
              ]);
          }
      }
      
  4. Caching:

    • Cache transformers or responses for read-heavy endpoints:
      $transformer = Cache::remember('user.transformer', now()->addHours(1), function () {
          return new UserTransformer();
      });
      
  5. Error Handling:

    • Customize error responses:
      DataTables::of(User::query())
          ->transformer(new UserTransformer)
          ->setErrorHandler(function ($request, $query, $message) {
              return response()->json([
                  'error' => $message,
                  'status' => 'error'
              ], 500);
          })
          ->make(true);
      

Gotchas and Tips

Pitfalls

  1. Transformer Registration:

    • Issue: Forgetting to pass the transformer to DataTables::of().
    • Fix: Always chain ->transformer(new YourTransformer) before ->make(true).
  2. Relationship Loading:

    • Issue: N+1 queries if relationships aren’t eager-loaded.
    • Fix: Use ->include('relationship') or manually eager-load:
      DataTables::of(User::with('posts')->query())
          ->transformer(new UserTransformer)
          ->make(true);
      
  3. Query Parameter Conflicts:

    • Issue: include and fields parameters may conflict with DataTables’ own parameters.
    • Fix: Use ->setInclude() and ->setFields() explicitly:
      DataTables::of(User::query())
          ->setInclude('posts')
          ->setFields(['users' => ['id', 'name']])
          ->transformer(new UserTransformer)
          ->make(true);
      
  4. Circular References:

    • Issue: Infinite loops in transformers with circular relationships (e.g., User->posts->author->posts).
    • Fix: Use ->ignoreMissing() or manually break cycles:
      $this->item($user->posts, new PostTransformer)->ignoreMissing();
      
  5. Pagination Metadata:

    • Issue: Custom pagination metadata may not appear in responses.
    • Fix: Use ->addIndexColumn() or override ->setPaginationType():
      DataTables::of(User::query())
          ->addIndexColumn()
          ->transformer(new UserTransformer)
          ->make(true);
      
  6. Frontend DataTables Version:

    • Issue: Mismatched DataTables frontend/backend versions may cause JSON parsing errors.
    • Fix: Ensure frontend uses serverSide: true and matches backend response structure.

Debugging Tips

  1. Log Raw Data:

    • Inspect raw query results before transformation:
      $query = User::query();
      $results = $query->get();
      \Log::info('Raw results:', $results->toArray());
      
  2. Transformer Debugging:

    • Add debug output in transformers:
      public function transform(User $user)
      {
          \Log::debug('Transforming user:', $user->toArray());
          return [...];
      }
      
  3. Network Inspection:

    • Check the raw JSON response in browser dev tools to verify structure.
  4. Disable Transformation:

    • Temporarily remove ->transformer() to isolate issues:
      return DataTables::of(User::query())->make(true); // Raw response
      

Configuration Quirks

  1. Service Provider:

    • Note: Auto-registered in Laravel 5.5+, but manually register for older versions:
      Yajra\DataTables\FractalServiceProvider::class,
      
  2. Published Config:

    • Location: config/datatables-fractal.php (published via vendor:publish).
    • **Custom
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport