diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index c58ccce..fe75aa3 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -1,23 +1,25 @@
-name: "Continuous Integration"
+name: Continuous Integration
 
 on:
   push:
+    branches:
+      - master
+      - '*.x'
   pull_request:
   schedule:
     - cron: '0 0 * * *'
 
 jobs:
-  phpunit:
-
+  tests:
     runs-on: ubuntu-latest
 
     strategy:
       fail-fast: true
       matrix:
-        php: [8.0, 8.1]
+        php: [8.2, 8.3, 8.4]
         stability: [prefer-stable]
 
-    name: PHP ${{ matrix.php }} - ${{ matrix.stability }}
+    name: PHP ${{ matrix.php }} - STABILITY ${{ matrix.stability }}
 
     steps:
       - name: Checkout code
@@ -27,7 +29,7 @@ jobs:
         uses: shivammathur/setup-php@v2
         with:
           php-version: ${{ matrix.php }}
-          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, memcached
+          extensions: oci8
           tools: composer:v2
           coverage: none
 
@@ -42,4 +44,4 @@ jobs:
           command: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress
 
       - name: Execute tests
-        run: vendor/bin/phpunit --verbose
+        run: vendor/bin/phpunit
diff --git a/.github/workflows/pint.yml b/.github/workflows/pint.yml
new file mode 100644
index 0000000..c07577f
--- /dev/null
+++ b/.github/workflows/pint.yml
@@ -0,0 +1,33 @@
+name: PHP Linting
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+      - '*.x'
+
+jobs:
+  pint:
+    name: Pint
+
+    runs-on: ubuntu-latest
+
+    permissions:
+      contents: write
+      pull-requests: write
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          ref: ${{ github.head_ref }}
+
+      - name: "laravel-pint"
+        uses: aglipanci/laravel-pint-action@latest
+        with:
+          preset: laravel
+          verboseMode: true
+
+      - uses: stefanzweifel/git-auto-commit-action@v5
+        with:
+          commit_message: "fix: pint :robot:"
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 59f0a2c..4dccad0 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -1,48 +1,39 @@
-name: "Static Analysis"
+name: Static Analysis
 
 on:
   push:
-    paths:
-      - .github/workflows/static-analysis.yml
-      - composer.*
-      - phpstan.neon.dist
-      - src/**
-      - tests/**
+    branches:
+      - master
+      - '*.x'
 
   pull_request:
-    paths:
-      - .github/workflows/static-analysis.yml
-      - composer.*
-      - phpstan.neon.dist
-      - src/**
-      - tests/**
 
   schedule:
     - cron: '0 0 * * *'
 
 jobs:
   static-analysis-phpstan:
-    name: "Static Analysis with PHPStan"
-    runs-on: ubuntu-latest
 
-    strategy:
-      matrix:
-        php-version:
-          - "8.1"
+    name: Source Code
+    runs-on: ubuntu-latest
 
     steps:
-      - name: "Checkout code"
-        uses: "actions/checkout@v2"
+      - name: Checkout code
+        uses: actions/checkout@v4
 
-      - name: "Install PHP"
-        uses: "shivammathur/setup-php@v2"
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
         with:
-          coverage: "none"
-          php-version: "${{ matrix.php-version }}"
-          tools: "cs2pr"
+          php-version: 8.2
+          tools: composer:v2
+          coverage: none
 
-      - name: "Install dependencies with Composer"
-        uses: "ramsey/composer-install@v1"
+      - name: Install dependencies
+        uses: nick-fields/retry@v3
+        with:
+          timeout_minutes: 5
+          max_attempts: 5
+          command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress
 
-      - name: "Run a static analysis with phpstan/phpstan"
-        run: "vendor/bin/phpstan --error-format=checkstyle | cs2pr"
+      - name: Run Static Analysis
+        run: vendor/bin/phpstan
diff --git a/.gitignore b/.gitignore
index 7e74d0e..cf5ef41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,4 @@
 /coverage
 composer.phar
 composer.lock
-/.phpunit.cache/
+/.phpunit.cache
diff --git a/.styleci.yml b/.styleci.yml
deleted file mode 100644
index 0285f17..0000000
--- a/.styleci.yml
+++ /dev/null
@@ -1 +0,0 @@
-preset: laravel
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8ba8e0..954868c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,76 +1,21 @@
 # Laravel DataTables Buttons Plugin CHANGELOG.
 
-## v9.1.4 - 2023-02-20
+## v12.1.3 - 2025-04-07
 
-- fix: applyScopes method to support Collection #168
+- fix: custom ajax action #197
 
-## v9.1.3 - 2022-11-15
+## v12.1.2 - 2025-03-18
 
-- Fixes some issues and confusion of datatable generator command #165
+- fix: stubs with generics #196
 
-## v9.1.2 - 2022-10-29
+## v12.1.1 - 2025-02-26
 
-- fix: Change for correct $action and $actionMethod #162
-- chore: update stubs #161
+- fix: stubs #195
 
-## v9.1.1 - 2022-10-06
+## v12.1.0 - 2025-02-26
 
-- fix(phpstan) Downgrade to 2.1.12 #158
-- fix: Allow null on view #152
+- feat: Macroable DataTable Base Class #193
 
-## v9.1.0 - 2022-10-05
+## v12.0.0 - 2025-02-26
 
-- Correcting with parameter typehints #155
-- Add contributing.md #156
-- Fix #154
-
-## v9.0.10 - 2022-06-25
-
-- Fix scopes for Eloquent Relation - Exception: "TypeError" #150
-
-## v9.0.9 - 2022-06-21
-
-- Fix datatables.stub #149
-- Add type hint and return type on stubs.
-
-## v9.0.8 - 2022-05-19
-
-- Improve exporting of array & other data type values
-
-## v9.0.7 - 2022-05-19
-
-- Remove try catch, fix stan
-
-## v9.0.6 - 2022-05-19
-
-- Fix exporting of boolean values
-
-## v9.0.5 - 2022-05-19
-
-- Fix exporting data via relationship
-
-## v9.0.4 - 2022-05-13
-
-- Fix nullable builder and request
-
-## v9.0.3 - 2022-05-12
-
-- Fix $htmlBuilder must not be accessed before initialization
-
-## v9.0.2 - 2022-05-12
-
-- Fix csv export extension
-
-## v9.0.1 - 2022-05-10
-
-- Quick fix for orthogonal column data
-- Introduce in https://github.com/yajra/laravel-datatables-html/commit/c6cc9a707a5a3095bca47adef2bae0614406a254
-- Add test for before & response callback for https://github.com/yajra/laravel-datatables/issues/2777
-
-## v9.0.0 - 2022-05-07
-
-- Added Laravel 9 specific support
-- Bump major version to match with the framework
-- Move `maatwebsite/excel` to suggest. #139
-- Add phpstan static analysis
-- Add tests
+- Laravel 12.x support
diff --git a/README.md b/README.md
index 69ca495..fb669a2 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,20 @@
 # Laravel DataTables Buttons Plugin
 
-[![Laravel 9.x](https://img.shields.io/badge/Laravel-9.x-orange.svg)](http://laravel.com)
+[![Laravel 12.x](https://img.shields.io/badge/Laravel-12.x-orange.svg)](http://laravel.com)
 [![Latest Stable Version](https://img.shields.io/packagist/v/yajra/laravel-datatables-buttons.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
-[![Build Status](https://travis-ci.org/yajra/laravel-datatables-buttons.svg?branch=master)](https://travis-ci.org/yajra/laravel-datatables-buttons)
+[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
+
+[![Continuous Integration](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/continuous-integration.yml)
+[![Static Analysis](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/static-analysis.yml)
 [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yajra/laravel-datatables-buttons/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yajra/laravel-datatables-buttons/?branch=master)
 [![Total Downloads](https://img.shields.io/packagist/dt/yajra/laravel-datatables-buttons.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
-[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
 
 This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for handling server-side function of exporting the table as csv, excel, pdf and printing.
 
 ## Requirements
 
-- [PHP >= 8.0.2](http://php.net/)
-- [Laravel 9.x](https://github.com/laravel/framework)
+- [PHP >= 8.2](http://php.net/)
+- [Laravel 12.x](https://github.com/laravel/framework)
 - [Laravel DataTables](https://github.com/yajra/laravel-datatables)
 - [jQuery DataTables v1.10.x](http://datatables.net/)
 - [jQuery DataTables Buttons Extension](https://datatables.net/reference/button/)
@@ -27,10 +29,13 @@ This package is a plugin of [Laravel DataTables](https://github.com/yajra/larave
 |:--------------|:--------|
 | 8.x and below | 4.x     |
 | 9.x           | 9.x     |
+| 10.x          | 10.x    |
+| 11.x          | 11.x    |
+| 12.x          | 12.x    |
 
 ## Quick Installation
 
-`composer require yajra/laravel-datatables-buttons:^9.0`
+`composer require yajra/laravel-datatables-buttons:^12`
 
 #### Service Provider (Optional on Laravel 5.5)
 
diff --git a/UPGADE.md b/UPGADE.md
new file mode 100644
index 0000000..c5ce3a6
--- /dev/null
+++ b/UPGADE.md
@@ -0,0 +1,22 @@
+# UPGRADE GUIDE
+
+## Upgrade from 10.x to 11.x
+
+1. Update the composer.json file and change the version of the package to `^11.0`:
+
+```json
+"require": {
+    "yajra/laravel-datatables-buttons": "^11.0"
+}
+```
+
+2. Run `composer update` to update the package.
+
+3. If you are using a custom class of laravel-excel to export the data, you need to update the collection method and include the return type `Collection|LazyCollection` in the method signature.
+
+```php
+public function collection(): Collection|LazyCollection
+{
+    return $this->collection;
+}
+```
diff --git a/composer.json b/composer.json
index 5be84e8..00654c9 100644
--- a/composer.json
+++ b/composer.json
@@ -1,58 +1,78 @@
 {
-  "name": "yajra/laravel-datatables-buttons",
-  "description": "Laravel DataTables Buttons Plugin.",
-  "keywords": [
-    "laravel",
-    "datatables",
-    "buttons",
-    "jquery"
-  ],
-  "license": "MIT",
-  "authors": [
-    {
-      "name": "Arjay Angeles",
-      "email": "aqangeles@gmail.com"
-    }
-  ],
-  "require": {
-    "php": "^8.0.2",
-    "yajra/laravel-datatables-oracle": "10.*",
-    "yajra/laravel-datatables-html": "9.*",
-    "illuminate/console": "*"
-  },
-  "require-dev": {
-    "maatwebsite/excel": "^3.1.40",
-    "nunomaduro/larastan": "2.1.*",
-    "orchestra/testbench": "^7.3",
-    "rap2hpoutre/fast-excel": "^3.2",
-    "barryvdh/laravel-snappy": "^1.0"
-  },
-  "autoload": {
-    "psr-4": {
-      "Yajra\\DataTables\\": "src/"
-    }
-  },
-  "autoload-dev": {
-    "psr-4": {
-      "Yajra\\DataTables\\Buttons\\Tests\\": "tests/"
-    }
-  },
-  "extra": {
-    "branch-alias": {
-      "dev-master": "9.0-dev"
+    "name": "yajra/laravel-datatables-buttons",
+    "description": "Laravel DataTables Buttons Plugin.",
+    "keywords": [
+        "laravel",
+        "datatables",
+        "buttons",
+        "jquery"
+    ],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Arjay Angeles",
+            "email": "aqangeles@gmail.com"
+        }
+    ],
+    "require": {
+        "php": "^8.2",
+        "yajra/laravel-datatables-oracle": "^12",
+        "yajra/laravel-datatables-html": "^12",
+        "illuminate/console": "^12"
     },
-    "laravel": {
-      "providers": [
-        "Yajra\\DataTables\\ButtonsServiceProvider"
-      ]
-    }
-  },
-  "suggest": {
-    "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.",
-    "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.",
-    "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.",
-    "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view."
-  },
-  "minimum-stability": "dev",
-  "prefer-stable": true
+    "require-dev": {
+        "larastan/larastan": "^3.1",
+        "orchestra/testbench": "^10",
+        "laravel/pint": "^1.21",
+        "rector/rector": "^2.0",
+        "maatwebsite/excel": "^3.1.64",
+        "rap2hpoutre/fast-excel": "^5.6"
+    },
+    "autoload": {
+        "psr-4": {
+            "Yajra\\DataTables\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Yajra\\DataTables\\Buttons\\Tests\\": "tests/"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "12.x-dev"
+        },
+        "laravel": {
+            "providers": [
+                "Yajra\\DataTables\\ButtonsServiceProvider"
+            ]
+        }
+    },
+    "suggest": {
+        "yajra/laravel-datatables-export": "Exporting of dataTables (excel, csv and PDF) via livewire and queue worker.",
+        "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.",
+        "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.",
+        "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.",
+        "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view."
+    },
+    "scripts": {
+        "test": "./vendor/bin/phpunit",
+        "pint": "./vendor/bin/pint",
+        "rector": "./vendor/bin/rector",
+        "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist",
+        "pr": [
+            "@pint",
+            "@rector",
+            "@stan",
+            "@test"
+        ]
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "funding": [
+        {
+            "type": "github",
+            "url": "https://github.com/sponsors/yajra"
+        }
+    ]
 }
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 2878532..7822d95 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -1,5 +1,5 @@
 includes:
-    - ./vendor/nunomaduro/larastan/extension.neon
+    - ./vendor/larastan/larastan/extension.neon
 
 parameters:
 
@@ -10,9 +10,17 @@ parameters:
 
     ignoreErrors:
         - '#Unsafe usage of new static\(\).#'
+        -   identifier: missingType.generics
+        -   identifier: missingType.iterableValue
+        -   identifier: argument.type
+        -   identifier: method.nonObject
+        -   identifier: foreach.nonIterable
+        -   identifier: assign.propertyType
+        -   identifier: return.type
+        -   identifier: offsetAccess.nonOffsetAccessible
+        -   identifier: property.defaultValue
+        -   identifier: binaryOp.invalid
+        -   identifier: encapsedStringPart.nonString
+        -   identifier: return.missing
 
     excludePaths:
-
-    checkMissingIterableValueType: false
-
-    checkGenericClassInNonGenericObjectType: false
diff --git a/rector.php b/rector.php
new file mode 100644
index 0000000..ca7ca05
--- /dev/null
+++ b/rector.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
+use Rector\Config\RectorConfig;
+use Rector\Set\ValueObject\LevelSetList;
+
+return static function (RectorConfig $rectorConfig): void {
+    $rectorConfig->paths([
+        __DIR__.'/src',
+        __DIR__.'/tests',
+    ]);
+
+    // register a single rule
+    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
+
+    // define sets of rules
+    $rectorConfig->sets([
+        LevelSetList::UP_TO_PHP_82,
+    ]);
+};
diff --git a/src/ButtonsServiceProvider.php b/src/ButtonsServiceProvider.php
index 23ea9c9..cdb273c 100644
--- a/src/ButtonsServiceProvider.php
+++ b/src/ButtonsServiceProvider.php
@@ -12,8 +12,6 @@ class ButtonsServiceProvider extends ServiceProvider
 {
     /**
      * Bootstrap the application events.
-     *
-     * @return void
      */
     public function boot(): void
     {
@@ -54,8 +52,6 @@ protected function registerCommands(): void
 
     /**
      * Register the service provider.
-     *
-     * @return void
      */
     public function register(): void
     {
diff --git a/src/Contracts/DataTableHtmlBuilder.php b/src/Contracts/DataTableHtmlBuilder.php
index 23eab85..ceb314b 100644
--- a/src/Contracts/DataTableHtmlBuilder.php
+++ b/src/Contracts/DataTableHtmlBuilder.php
@@ -8,8 +8,6 @@ interface DataTableHtmlBuilder
      * Handle building of dataTables html.
      *
      * @return \Yajra\DataTables\Html\Builder
-     *
-     * @throws \Exception
      */
     public function handle();
 }
diff --git a/src/Contracts/DataTableScope.php b/src/Contracts/DataTableScope.php
index c129a98..d6d59c3 100644
--- a/src/Contracts/DataTableScope.php
+++ b/src/Contracts/DataTableScope.php
@@ -7,7 +7,7 @@ interface DataTableScope
     /**
      * Apply a query scope.
      *
-     * @param  \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation|\Illuminate\Support\Collection  $query
+     * @param  \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation|\Illuminate\Support\Collection|\Illuminate\Http\Resources\Json\AnonymousResourceCollection  $query
      * @return mixed
      */
     public function apply($query);
diff --git a/src/Exports/DataTablesCollectionExport.php b/src/Exports/DataTablesCollectionExport.php
index 0719820..1e2f743 100644
--- a/src/Exports/DataTablesCollectionExport.php
+++ b/src/Exports/DataTablesCollectionExport.php
@@ -12,30 +12,18 @@ abstract class DataTablesCollectionExport implements FromCollection, WithHeading
 {
     use Exportable;
 
-    /**
-     * @var Collection|LazyCollection
-     */
-    protected $collection;
-
-    /**
-     * @param  Collection|LazyCollection|null  $collection
-     */
-    public function __construct($collection = null)
+    protected LazyCollection|Collection $collection;
+
+    public function __construct(Collection|LazyCollection|null $collection = null)
     {
         $this->collection = $collection ?? new Collection;
     }
 
-    /**
-     * @return Collection|LazyCollection
-     */
-    public function collection()
+    public function collection(): Collection|LazyCollection
     {
         return $this->collection;
     }
 
-    /**
-     * @return array
-     */
     public function headings(): array
     {
         /** @var array $first */
diff --git a/src/Generators/DataTablesHtmlCommand.php b/src/Generators/DataTablesHtmlCommand.php
index 5406ca0..95db37b 100644
--- a/src/Generators/DataTablesHtmlCommand.php
+++ b/src/Generators/DataTablesHtmlCommand.php
@@ -37,7 +37,6 @@ class DataTablesHtmlCommand extends DataTablesMakeCommand
      * Build the class with the given name.
      *
      * @param  string  $name
-     * @return string
      *
      * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
      */
@@ -48,18 +47,16 @@ protected function buildClass($name): string
         $stub = $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
 
         $this->replaceBuilder($stub)
-             ->replaceColumns($stub)
-             ->replaceButtons($stub)
-             ->replaceDOM($stub)
-             ->replaceTableId($stub);
+            ->replaceColumns($stub)
+            ->replaceButtons($stub)
+            ->replaceDOM($stub)
+            ->replaceTableId($stub);
 
         return $stub;
     }
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
@@ -72,7 +69,6 @@ protected function getStub(): string
      * Parse the name and format according to the root namespace.
      *
      * @param  string  $name
-     * @return string
      */
     protected function qualifyClass($name): string
     {
@@ -92,6 +88,6 @@ protected function qualifyClass($name): string
             $name = preg_replace('#datatablehtml$#i', 'DataTableHtml', $name);
         }
 
-        return $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name;
+        return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name;
     }
 }
diff --git a/src/Generators/DataTablesMakeCommand.php b/src/Generators/DataTablesMakeCommand.php
index 2a4c2d8..0a96770 100644
--- a/src/Generators/DataTablesMakeCommand.php
+++ b/src/Generators/DataTablesMakeCommand.php
@@ -61,7 +61,6 @@ public function handle()
      * Build the class with the given name.
      *
      * @param  string  $name
-     * @return string
      *
      * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
      */
@@ -70,32 +69,28 @@ protected function buildClass($name): string
         $stub = parent::buildClass($name);
 
         $this->replaceModelImport($stub)
-             ->replaceModel($stub)
-             ->replaceBuilder($stub)
-             ->replaceColumns($stub)
-             ->replaceButtons($stub)
-             ->replaceDOM($stub)
-             ->replaceTableId($stub)
-             ->replaceAction($stub)
-             ->replaceFilename($stub);
+            ->replaceModel($stub)
+            ->replaceBuilder($stub)
+            ->replaceColumns($stub)
+            ->replaceButtons($stub)
+            ->replaceDOM($stub)
+            ->replaceTableId($stub)
+            ->replaceAction($stub)
+            ->replaceFilename($stub);
 
         return $stub;
     }
 
     /**
      * Get DataTable class base name without the suffix.
-     *
-     * @return string
      */
     protected function getDataTableBaseName(): string
     {
-        return (string) preg_replace('#datatable$#i', '', $this->getNameInput());
+        return (string) preg_replace('#datatable$#i', '', (string) $this->getNameInput());
     }
 
     /**
      * Prepare model name from input.
-     *
-     * @return string
      */
     protected function prepareModelName(): string
     {
@@ -105,7 +100,6 @@ protected function prepareModelName(): string
     /**
      * Replace the filename.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceFilename(string &$stub): static
@@ -117,9 +111,6 @@ protected function replaceFilename(string &$stub): static
 
     /**
      * Replace the action.
-     *
-     * @param  string  $stub
-     * @return static
      */
     protected function replaceAction(string &$stub): static
     {
@@ -130,8 +121,6 @@ protected function replaceAction(string &$stub): static
 
     /**
      * Set the action view to be used.
-     *
-     * @return string
      */
     protected function getAction(): string
     {
@@ -148,7 +137,6 @@ protected function getAction(): string
     /**
      * Replace columns.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceTableId(string &$stub): static
@@ -161,7 +149,6 @@ protected function replaceTableId(string &$stub): static
     /**
      * Replace dom.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceDOM(string &$stub): static
@@ -177,7 +164,6 @@ protected function replaceDOM(string &$stub): static
     /**
      * Replace buttons.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceButtons(string &$stub): static
@@ -189,8 +175,6 @@ protected function replaceButtons(string &$stub): static
 
     /**
      * Get the columns to be used.
-     *
-     * @return string
      */
     protected function getButtons(): string
     {
@@ -209,10 +193,6 @@ protected function getButtons(): string
 
     /**
      * Parse array from definition.
-     *
-     * @param  string  $definition
-     * @param  int  $indentation
-     * @return string
      */
     protected function parseButtons(string $definition, int $indentation = 24): string
     {
@@ -239,7 +219,6 @@ protected function parseButtons(string $definition, int $indentation = 24): stri
     /**
      * Replace columns.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceColumns(string &$stub): static
@@ -251,8 +230,6 @@ protected function replaceColumns(string &$stub): static
 
     /**
      * Get the columns to be used.
-     *
-     * @return string
      */
     protected function getColumns(): string
     {
@@ -278,10 +255,6 @@ protected function getColumns(): string
 
     /**
      * Parse array from definition.
-     *
-     * @param  array|string  $definition
-     * @param  int  $indentation
-     * @return string
      */
     protected function parseColumns(array|string $definition, int $indentation = 12): string
     {
@@ -338,14 +311,13 @@ protected function qualifyClass($name)
             $name = preg_replace('#datatable$#i', 'DataTable', $name);
         }
 
-        return $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name;
+        return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name;
     }
 
     /**
      * Get the default namespace for the class.
      *
      * @param  string  $rootNamespace
-     * @return string
      */
     protected function getDefaultNamespace($rootNamespace): string
     {
@@ -354,9 +326,6 @@ protected function getDefaultNamespace($rootNamespace): string
 
     /**
      * Replace model name.
-     *
-     * @param  string  $stub
-     * @return static
      */
     protected function replaceModel(string &$stub): static
     {
@@ -369,16 +338,12 @@ protected function replaceModel(string &$stub): static
 
     /**
      * Get model name to use.
-     *
-     * @return string
      */
     protected function getModel(): string
     {
         /** @var string $modelFromOption */
         $modelFromOption = $this->option('model');
-        $modelNamespaceFromOption = $this->option('model-namespace')
-            ? $this->option('model-namespace')
-            : config('datatables-buttons.namespace.model');
+        $modelNamespaceFromOption = $this->option('model-namespace') ?: config('datatables-buttons.namespace.model');
 
         $name = $modelFromOption ?: $this->prepareModelName();
         $modelNamespace = $modelNamespaceFromOption ?: $this->laravel->getNamespace();
@@ -393,7 +358,6 @@ protected function getModel(): string
     /**
      * Replace model import.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceModelImport(string &$stub): static
@@ -405,8 +369,6 @@ protected function replaceModelImport(string &$stub): static
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
diff --git a/src/Generators/DataTablesScopeCommand.php b/src/Generators/DataTablesScopeCommand.php
index 78ee636..c0aa5fd 100644
--- a/src/Generators/DataTablesScopeCommand.php
+++ b/src/Generators/DataTablesScopeCommand.php
@@ -31,7 +31,6 @@ class DataTablesScopeCommand extends GeneratorCommand
      * Get the default namespace for the class.
      *
      * @param  string  $rootNamespace
-     * @return string
      */
     protected function getDefaultNamespace($rootNamespace): string
     {
@@ -40,8 +39,6 @@ protected function getDefaultNamespace($rootNamespace): string
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
diff --git a/src/Generators/stubs/builder.stub b/src/Generators/stubs/builder.stub
index 785bf13..511be79 100644
--- a/src/Generators/stubs/builder.stub
+++ b/src/Generators/stubs/builder.stub
@@ -11,10 +11,9 @@ use Yajra\DataTables\Services\DataTable;
 class DummyClass extends DataTable
 {
     /**
-     * Build DataTable class.
+     * Build the DataTable class.
      *
-     * @param QueryBuilder $query Results from query() method.
-     * @return \Yajra\DataTables\EloquentDataTable
+     * @param QueryBuilder<ModelName> $query Results from query() method.
      */
     public function dataTable(QueryBuilder $query): EloquentDataTable
     {
@@ -24,10 +23,9 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Get query source of dataTable.
+     * Get the query source of dataTable.
      *
-     * @param \DummyModel $model
-     * @return \Illuminate\Database\Eloquent\Builder
+     * @return QueryBuilder<ModelName>
      */
     public function query(ModelName $model): QueryBuilder
     {
@@ -35,9 +33,7 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Optional method if you want to use html builder.
-     *
-     * @return \Yajra\DataTables\Html\Builder
+     * Optional method if you want to use the html builder.
      */
     public function html(): HtmlBuilder
     {
@@ -45,9 +41,7 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Get filename for export.
-     *
-     * @return string
+     * Get the filename for export.
      */
     protected function filename(): string
     {
diff --git a/src/Generators/stubs/datatables.stub b/src/Generators/stubs/datatables.stub
index c55ac4d..1a574c1 100644
--- a/src/Generators/stubs/datatables.stub
+++ b/src/Generators/stubs/datatables.stub
@@ -15,10 +15,9 @@ use Yajra\DataTables\Html\Builder as HtmlBuilder;
 class DummyClass extends DataTable
 {
     /**
-     * Build DataTable class.
+     * Build the DataTable class.
      *
-     * @param QueryBuilder $query Results from query() method.
-     * @return \Yajra\DataTables\EloquentDataTable
+     * @param QueryBuilder<ModelName> $query Results from query() method.
      */
     public function dataTable(QueryBuilder $query): EloquentDataTable
     {
@@ -28,10 +27,9 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Get query source of dataTable.
+     * Get the query source of dataTable.
      *
-     * @param \DummyModel $model
-     * @return \Illuminate\Database\Eloquent\Builder
+     * @return QueryBuilder<ModelName>
      */
     public function query(ModelName $model): QueryBuilder
     {
@@ -39,9 +37,7 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Optional method if you want to use html builder.
-     *
-     * @return \Yajra\DataTables\Html\Builder
+     * Optional method if you want to use the html builder.
      */
     public function html(): HtmlBuilder
     {
@@ -49,7 +45,6 @@ class DummyClass extends DataTable
                     ->setTableId('DummyTableId')
                     ->columns($this->getColumns())
                     ->minifiedAjax()
-                    //->dom('DummyDOM')
                     ->orderBy(1)
                     ->selectStyleSingle()
                     ->buttons([
@@ -59,8 +54,6 @@ class DummyClass extends DataTable
 
     /**
      * Get the dataTable columns definition.
-     *
-     * @return array
      */
     public function getColumns(): array
     {
@@ -75,9 +68,7 @@ class DummyClass extends DataTable
     }
 
     /**
-     * Get filename for export.
-     *
-     * @return string
+     * Get the filename for export.
      */
     protected function filename(): string
     {
diff --git a/src/Generators/stubs/html.stub b/src/Generators/stubs/html.stub
index da7f0df..2d1c421 100644
--- a/src/Generators/stubs/html.stub
+++ b/src/Generators/stubs/html.stub
@@ -2,6 +2,7 @@
 
 namespace DummyNamespace;
 
+use Yajra\DataTables\Html\Builder;
 use Yajra\DataTables\Html\Button;
 use Yajra\DataTables\Html\Column;
 use Yajra\DataTables\Html\DataTableHtml;
@@ -13,26 +14,23 @@ class DummyClass extends DataTableHtml
     /**
      * Build the html builder.
      *
-     * @return \Yajra\DataTables\Html\Builder
      * @throws \Exception
      */
     public function handle(): Builder
     {
-        return $this->setTableId('DummyTableId')
-                    ->columns($this->getColumns())
-                    ->minifiedAjax()
-                    //->dom('DummyDOM')
-                    ->orderBy(1)
-                    ->selectStyleSingle()
-                    ->buttons([
-                        DummyButtons
-                    ]);
+        return $this->getHtmlBuilder()
+            ->setTableId('DummyTableId')
+            ->columns($this->getColumns())
+            ->minifiedAjax()
+            ->orderBy(1)
+            ->selectStyleSingle()
+            ->buttons([
+                DummyButtons
+            ]);
     }
 
     /**
      * Get the dataTable columns definition.
-     *
-     * @return array
      */
     public function getColumns(): array
     {
diff --git a/src/Html/DataTableHtml.php b/src/Html/DataTableHtml.php
index d16065a..92456f4 100644
--- a/src/Html/DataTableHtml.php
+++ b/src/Html/DataTableHtml.php
@@ -10,33 +10,26 @@
  */
 abstract class DataTableHtml implements DataTableHtmlBuilder
 {
-    /**
-     * @var \Yajra\DataTables\Html\Builder|null
-     */
     protected ?Builder $htmlBuilder = null;
 
-    /**
-     * @return \Yajra\DataTables\Html\Builder
-     *
-     * @throws \Exception
-     */
     public static function make(): Builder
     {
         if (func_get_args()) {
             return (new static(...func_get_args()))->handle();
         }
 
-        return app(static::class)->handle();
+        /** @var static $html */
+        $html = app(static::class);
+
+        return $html->handle();
     }
 
     /**
-     * @param  string  $method
-     * @param  mixed  $parameters
-     * @return mixed
+     * @return \Yajra\DataTables\Html\Builder
      *
      * @throws \Exception
      */
-    public function __call(string $method, $parameters)
+    public function __call(string $method, mixed $parameters)
     {
         if (method_exists($this->getHtmlBuilder(), $method)) {
             return $this->getHtmlBuilder()->{$method}(...$parameters);
@@ -45,9 +38,6 @@ public function __call(string $method, $parameters)
         throw new BadMethodCallException("Method {$method} does not exists");
     }
 
-    /**
-     * @return \Yajra\DataTables\Html\Builder
-     */
     protected function getHtmlBuilder(): Builder
     {
         if ($this->htmlBuilder) {
@@ -57,10 +47,6 @@ protected function getHtmlBuilder(): Builder
         return $this->htmlBuilder = app(Builder::class);
     }
 
-    /**
-     * @param  \Yajra\DataTables\Html\Builder  $builder
-     * @return static
-     */
     public function setHtmlBuilder(Builder $builder): static
     {
         $this->htmlBuilder = $builder;
diff --git a/src/Services/DataTable.php b/src/Services/DataTable.php
index cc4ba0e..64b1a3e 100644
--- a/src/Services/DataTable.php
+++ b/src/Services/DataTable.php
@@ -10,10 +10,14 @@
 use Illuminate\Database\Eloquent\Relations\Relation as EloquentRelation;
 use Illuminate\Database\Query\Builder as QueryBuilder;
 use Illuminate\Http\JsonResponse;
+use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
 use Illuminate\Http\Response;
+use Illuminate\Support\Arr;
 use Illuminate\Support\Collection;
 use Illuminate\Support\LazyCollection;
+use Illuminate\Support\Traits\Macroable;
 use Maatwebsite\Excel\ExcelServiceProvider;
+use OpenSpout\Common\Entity\Style\Style;
 use Rap2hpoutre\FastExcel\FastExcel;
 use Yajra\DataTables\Contracts\DataTableButtons;
 use Yajra\DataTables\Contracts\DataTableScope;
@@ -26,47 +30,37 @@
 
 abstract class DataTable implements DataTableButtons
 {
+    use Macroable;
+
     /**
      * DataTables print preview view.
      *
      * @phpstan-var view-string
-     *
-     * @var string
      */
     protected string $printPreview = 'datatables::print';
 
     /**
      * Name of the dataTable variable.
-     *
-     * @var string
      */
     protected string $dataTableVariable = 'dataTable';
 
     /**
      * List of columns to be excluded from export.
-     *
-     * @var array
      */
     protected array $excludeFromExport = [];
 
     /**
      * List of columns to be excluded from printing.
-     *
-     * @var array
      */
     protected array $excludeFromPrint = [];
 
     /**
      * List of columns to be exported.
-     *
-     * @var string|array
      */
     protected string|array $exportColumns = '*';
 
     /**
      * List of columns to be printed.
-     *
-     * @var string|array
      */
     protected string|array $printColumns = '*';
 
@@ -79,8 +73,6 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * Html builder.
-     *
-     * @var \Yajra\DataTables\Html\Builder|null
      */
     protected ?Builder $htmlBuilder = null;
 
@@ -93,15 +85,11 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * Export filename.
-     *
-     * @var string
      */
     protected string $filename = '';
 
     /**
      * Custom attributes set on the class.
-     *
-     * @var array
      */
     protected array $attributes = [];
 
@@ -123,20 +111,13 @@ abstract class DataTable implements DataTableButtons
      * Available button actions. When calling an action, the value will be used
      * as the function name (so it should be available)
      * If you want to add or disable an action, overload and modify this property.
-     *
-     * @var array
      */
     protected array $actions = ['print', 'csv', 'excel', 'pdf'];
 
-    /**
-     * @var \Yajra\DataTables\Utilities\Request|null
-     */
     protected ?Request $request = null;
 
     /**
      * Flag to use fast-excel package for export.
-     *
-     * @var bool
      */
     protected bool $fastExcel = false;
 
@@ -145,8 +126,6 @@ abstract class DataTable implements DataTableButtons
      * Note: Disabling this flag can improve you export time.
      * Enabled by default to emulate the same output
      * with laravel-excel.
-     *
-     * @var bool
      */
     protected bool $fastExcelCallback = true;
 
@@ -159,22 +138,16 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * CSV export typewriter.
-     *
-     * @var string
      */
     protected string $csvWriter = 'Csv';
 
     /**
      * Excel export typewriter.
-     *
-     * @var string
      */
     protected string $excelWriter = 'Xlsx';
 
     /**
      * PDF export typewriter.
-     *
-     * @var string
      */
     protected string $pdfWriter = 'Dompdf';
 
@@ -195,17 +168,10 @@ public function __construct()
      *
      * @phpstan-param view-string|null $view
      *
-     * @param  string|null  $view
-     * @param  array  $data
-     * @param  array  $mergeData
      * @return mixed
      */
-    public function render(string $view = null, array $data = [], array $mergeData = [])
+    public function render(?string $view = null, array $data = [], array $mergeData = [])
     {
-        if ($this->request()->ajax() && $this->request()->wantsJson()) {
-            return app()->call([$this, 'ajax']);
-        }
-
         /** @var string $action */
         $action = $this->request()->get('action');
         $actionMethod = $action === 'print' ? 'printPreview' : $action;
@@ -217,13 +183,16 @@ public function render(string $view = null, array $data = [], array $mergeData =
             return app()->call($callback);
         }
 
+        if ($this->request()->ajax() && $this->request()->wantsJson()) {
+            return app()->call($this->ajax(...));
+        }
+
+        /** @phpstan-ignore-next-line  */
         return view($view, $data, $mergeData)->with($this->dataTableVariable, $this->getHtmlBuilder());
     }
 
     /**
      * Get DataTables Request instance.
-     *
-     * @return \Yajra\DataTables\Utilities\Request
      */
     public function request(): Request
     {
@@ -236,8 +205,6 @@ public function request(): Request
 
     /**
      * Display ajax response.
-     *
-     * @return \Illuminate\Http\JsonResponse
      */
     public function ajax(): JsonResponse
     {
@@ -281,8 +248,6 @@ public function printPreview(): Renderable
 
     /**
      * Get mapped columns versus final decorated output.
-     *
-     * @return array
      */
     protected function getDataForPrint(): array
     {
@@ -293,8 +258,6 @@ protected function getDataForPrint(): array
 
     /**
      * Get printable columns.
-     *
-     * @return array|\Illuminate\Support\Collection
      */
     protected function printColumns(): array|Collection
     {
@@ -303,8 +266,6 @@ protected function printColumns(): array|Collection
 
     /**
      * Get filtered print columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getPrintColumnsFromBuilder(): Collection
     {
@@ -313,8 +274,6 @@ protected function getPrintColumnsFromBuilder(): Collection
 
     /**
      * Get filtered export columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getExportColumnsFromBuilder(): Collection
     {
@@ -323,8 +282,6 @@ protected function getExportColumnsFromBuilder(): Collection
 
     /**
      * Get columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getColumnsFromBuilder(): Collection
     {
@@ -343,8 +300,6 @@ public function html()
 
     /**
      * Get DataTables Html Builder instance.
-     *
-     * @return \Yajra\DataTables\Html\Builder
      */
     public function builder(): Builder
     {
@@ -361,24 +316,16 @@ public function builder(): Builder
 
     /**
      * Map ajax response to columns definition.
-     *
-     * @param  array|Collection  $columns
-     * @param  string  $type
-     * @return array
      */
-    protected function mapResponseToColumns($columns, string $type): array
+    protected function mapResponseToColumns(array|\Illuminate\Support\Collection $columns, string $type): array
     {
         $transformer = new DataArrayTransformer;
 
-        return array_map(function ($row) use ($columns, $type, $transformer) {
-            return $transformer->transform($row, $columns, $type);
-        }, $this->getAjaxResponseData());
+        return array_map(fn ($row) => $transformer->transform($row, $columns, $type), $this->getAjaxResponseData());
     }
 
     /**
      * Get decorated data as defined in datatables ajax response.
-     *
-     * @return array
      */
     protected function getAjaxResponseData(): array
     {
@@ -388,7 +335,7 @@ protected function getAjaxResponseData(): array
         ]);
 
         /** @var JsonResponse $response */
-        $response = app()->call([$this, 'ajax']);
+        $response = app()->call($this->ajax(...));
 
         /** @var array{data: array} $data */
         $data = $response->getData(true);
@@ -396,9 +343,6 @@ protected function getAjaxResponseData(): array
         return $data['data'];
     }
 
-    /**
-     * @return \Yajra\DataTables\Html\Builder
-     */
     protected function getHtmlBuilder(): Builder
     {
         $builder = $this->html();
@@ -412,7 +356,6 @@ protected function getHtmlBuilder(): Builder
     /**
      * Add html builder callback hook.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function withHtml(callable $callback): static
@@ -425,7 +368,6 @@ public function withHtml(callable $callback): static
     /**
      * Add callback before sending the response.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function before(callable $callback): static
@@ -438,7 +380,6 @@ public function before(callable $callback): static
     /**
      * Add callback after the response was processed.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function response(callable $callback): static
@@ -487,7 +428,7 @@ protected function buildExcelFile()
         }
 
         if (! class_exists(ExcelServiceProvider::class)) {
-            throw new Exception('Please install maatwebsite/excel to be able to use this function.');
+            throw new Exception('Please `composer require maatwebsite/excel` to be able to use this function.');
         }
 
         if (! new $this->exportClass instanceof DataTablesExportHandler) {
@@ -503,8 +444,6 @@ protected function buildExcelFile()
 
     /**
      * Get export filename.
-     *
-     * @return string
      */
     public function getFilename(): string
     {
@@ -514,7 +453,6 @@ public function getFilename(): string
     /**
      * Set export filename.
      *
-     * @param  string  $filename
      * @return $this
      */
     public function setFilename(string $filename): static
@@ -526,8 +464,6 @@ public function setFilename(string $filename): static
 
     /**
      * Get filename for export.
-     *
-     * @return string
      */
     protected function filename(): string
     {
@@ -536,8 +472,6 @@ protected function filename(): string
 
     /**
      * Get mapped columns versus final decorated output.
-     *
-     * @return array
      */
     protected function getDataForExport(): array
     {
@@ -558,9 +492,6 @@ protected function exportColumns(): Collection
 
     /**
      * Convert array to collection of Column class.
-     *
-     * @param  array  $columns
-     * @return Collection
      */
     private function toColumnsCollection(array $columns): Collection
     {
@@ -568,7 +499,7 @@ private function toColumnsCollection(array $columns): Collection
 
         foreach ($columns as $column) {
             if (isset($column['data'])) {
-                $column['title'] = $column['title'] ?? $column['data'];
+                $column['title'] ??= $column['data'];
                 $collection->push(new Column($column));
             } else {
                 $data = [];
@@ -602,7 +533,7 @@ public function csv()
         }
 
         // @phpstan-ignore-next-line
-        return $this->buildExcelFile()->download($path, $this->csvWriter);
+        return $excelFile->download($path, $this->csvWriter);
     }
 
     /**
@@ -610,15 +541,11 @@ public function csv()
      *
      * @return \Illuminate\Http\Response|string|\Symfony\Component\HttpFoundation\StreamedResponse
      *
-     * @throws \Box\Spout\Common\Exception\IOException
-     * @throws \Box\Spout\Common\Exception\InvalidArgumentException
-     * @throws \Box\Spout\Common\Exception\UnsupportedTypeException
-     * @throws \Box\Spout\Writer\Exception\WriterNotOpenedException
      * @throws \Exception
      */
     public function pdf()
     {
-        if ('snappy' == config('datatables-buttons.pdf_generator', 'snappy')) {
+        if (config('datatables-buttons.pdf_generator', 'snappy') == 'snappy') {
             return $this->snappyPdf();
         }
 
@@ -629,14 +556,13 @@ public function pdf()
     /**
      * PDF version of the table using print preview blade template.
      *
-     * @return \Illuminate\Http\Response
      *
      * @throws \Yajra\DataTables\Exceptions\Exception
      */
     public function snappyPdf(): Response
     {
         if (! class_exists(PdfWrapper::class)) {
-            throw new Exception('You need to install barryvdh/laravel-snappy to be able to use this feature.');
+            throw new Exception('Please `composer require barryvdh/laravel-snappy` to be able to use this feature.');
         }
 
         /** @var \Barryvdh\Snappy\PdfWrapper $snappy */
@@ -654,7 +580,6 @@ public function snappyPdf(): Response
     /**
      * Add basic array query scopes.
      *
-     * @param  \Yajra\DataTables\Contracts\DataTableScope  $scope
      * @return $this
      */
     public function addScope(DataTableScope $scope): static
@@ -667,7 +592,6 @@ public function addScope(DataTableScope $scope): static
     /**
      * Push multiples scopes to array query scopes.
      *
-     * @param  array  $scopes
      * @return $this
      */
     public function addScopes(array $scopes): static
@@ -680,8 +604,6 @@ public function addScopes(array $scopes): static
     /**
      * Set a custom class attribute.
      *
-     * @param  array|string  $key
-     * @param  mixed|null  $value
      * @return $this
      */
     public function with(array|string $key, mixed $value = null): static
@@ -698,7 +620,6 @@ public function with(array|string $key, mixed $value = null): static
     /**
      * Dynamically retrieve the value of an attribute.
      *
-     * @param  string  $key
      * @return mixed|null
      */
     public function __get(string $key)
@@ -712,12 +633,10 @@ public function __get(string $key)
 
     /**
      * Apply query scopes.
-     *
-     * @param  EloquentBuilder|QueryBuilder|EloquentRelation|Collection  $query
-     * @return EloquentBuilder|QueryBuilder|EloquentRelation|Collection
      */
-    protected function applyScopes(EloquentBuilder|QueryBuilder|EloquentRelation|Collection $query): EloquentBuilder|QueryBuilder|EloquentRelation|Collection
-    {
+    protected function applyScopes(
+        EloquentBuilder|QueryBuilder|EloquentRelation|Collection|AnonymousResourceCollection $query
+    ): EloquentBuilder|QueryBuilder|EloquentRelation|Collection|AnonymousResourceCollection {
         foreach ($this->scopes as $scope) {
             $scope->apply($query);
         }
@@ -727,24 +646,16 @@ protected function applyScopes(EloquentBuilder|QueryBuilder|EloquentRelation|Col
 
     /**
      * Determine if the DataTable has scopes.
-     *
-     * @param  array  $scopes
-     * @param  bool  $validateAll
-     * @return bool
      */
     protected function hasScopes(array $scopes, bool $validateAll = false): bool
     {
-        $filteredScopes = array_filter($this->scopes, function ($scope) use ($scopes) {
-            return in_array(get_class($scope), $scopes);
-        });
+        $filteredScopes = array_filter($this->scopes, fn ($scope) => in_array($scope::class, $scopes));
 
         return $validateAll ? count($filteredScopes) === count($scopes) : ! empty($filteredScopes);
     }
 
     /**
      * Get default builder parameters.
-     *
-     * @return array
      */
     protected function getBuilderParameters(): array
     {
@@ -754,10 +665,6 @@ protected function getBuilderParameters(): array
         return $defaults;
     }
 
-    /**
-     * @param  array|\Illuminate\Support\Collection  $collection
-     * @return \Illuminate\Support\LazyCollection
-     */
     protected function convertToLazyCollection(array|Collection $collection): LazyCollection
     {
         if (is_array($collection)) {
@@ -767,29 +674,43 @@ protected function convertToLazyCollection(array|Collection $collection): LazyCo
         return $collection->lazy();
     }
 
-    /**
-     * @return \Closure
-     */
     public function fastExcelCallback(): Closure
     {
         return function ($row) {
             $mapped = [];
 
-            $this->exportColumns()->each(function (Column $column) use (&$mapped, $row) {
-                if ($column['exportable']) {
-                    $mapped[$column['title']] = $row[$column['data']];
-                }
-            });
+            $this->exportColumns()
+                ->reject(fn (Column $column) => $column->exportable === false)
+                ->each(function (Column $column) use (&$mapped, $row) {
+                    $callback = $column->exportRender ?? null;
+                    $key = $column->data;
+
+                    if (is_array($key)) {
+                        $data = Arr::get($row, $key['_']);
+                    } else {
+                        $data = Arr::get($row, $key);
+                    }
+
+                    if (is_callable($callback)) {
+                        $mapped[$column->title] = $callback($row, $data);
+                    } else {
+                        $mapped[$column->title] = $data;
+                    }
+                });
 
             return $mapped;
         };
     }
 
     /**
-     * @return \Rap2hpoutre\FastExcel\FastExcel
+     * @throws \Yajra\DataTables\Exceptions\Exception
      */
     protected function buildFastExcelFile(): FastExcel
     {
+        if (! class_exists(FastExcel::class)) {
+            throw new Exception('Please `composer require rap2hpoutre/fast-excel` to be able to use this function.');
+        }
+
         $query = null;
         if (method_exists($this, 'query')) {
             /** @var EloquentBuilder|QueryBuilder $query */
@@ -802,19 +723,23 @@ protected function buildFastExcelFile(): FastExcel
         $dataTable = app()->call([$this, 'dataTable'], compact('query'));
         $dataTable->skipPaging();
 
+        $styles = [];
+        $this->exportColumns()
+            ->reject(fn (Column $column) => $column->exportable === false || ! $column->exportFormat)
+            ->each(function (Column $column) use (&$styles) {
+                $styles[$column->title] = (new Style)->setFormat($column->exportFormat);
+            });
+
         if ($dataTable instanceof QueryDataTable) {
-            // @phpstan-ignore-next-line
-            function queryGenerator($dataTable): Generator
-            {
+            $queryGenerator = function ($dataTable): Generator {
                 foreach ($dataTable->getFilteredQuery()->cursor() as $row) {
                     yield $row;
                 }
-            }
+            };
 
-            // @phpstan-ignore-next-line
-            return new FastExcel(queryGenerator($dataTable));
+            return (new FastExcel($queryGenerator($dataTable)))->setColumnStyles($styles);
         }
 
-        return new FastExcel($dataTable->toArray()['data']);
+        return (new FastExcel($dataTable->toArray()['data']))->setColumnStyles($styles);
     }
 }
diff --git a/src/Services/DataTablesExportHandler.php b/src/Services/DataTablesExportHandler.php
index 0b1e7e8..8cc53b3 100644
--- a/src/Services/DataTablesExportHandler.php
+++ b/src/Services/DataTablesExportHandler.php
@@ -4,6 +4,4 @@
 
 use Yajra\DataTables\Exports\DataTablesCollectionExport;
 
-class DataTablesExportHandler extends DataTablesCollectionExport
-{
-}
+class DataTablesExportHandler extends DataTablesCollectionExport {}
diff --git a/src/Transformers/DataArrayTransformer.php b/src/Transformers/DataArrayTransformer.php
index 36d7626..bd393e5 100644
--- a/src/Transformers/DataArrayTransformer.php
+++ b/src/Transformers/DataArrayTransformer.php
@@ -11,10 +11,7 @@ class DataArrayTransformer
     /**
      * Transform row data by column's definition.
      *
-     * @param  array  $row
      * @param  array|Collection<array-key, Column>  $columns
-     * @param  string  $type
-     * @return array
      */
     public function transform(array $row, array|Collection $columns, string $type = 'printable'): array
     {
@@ -28,10 +25,7 @@ public function transform(array $row, array|Collection $columns, string $type =
     /**
      * Transform row column by collection.
      *
-     * @param  array  $row
      * @param  Collection<array-key, Column>  $columns
-     * @param  string  $type
-     * @return array
      */
     protected function buildColumnByCollection(array $row, Collection $columns, string $type = 'printable'): array
     {
@@ -49,10 +43,15 @@ protected function buildColumnByCollection(array $row, Collection $columns, stri
 
                 if ($type == 'exportable') {
                     $title = $this->decodeContent($title);
-                    $data = is_array($data) ? json_encode($data) : $this->decodeContent($data);
+                    $data = is_array($data) ? json_encode($data, JSON_THROW_ON_ERROR) : $this->decodeContent($data);
                 }
 
-                $results[$title] = $data;
+                if (isset($column->exportRender)) {
+                    $callback = $column->exportRender;
+                    $results[$title] = $callback($row, $data);
+                } else {
+                    $results[$title] = $data;
+                }
             }
         });
 
@@ -61,9 +60,6 @@ protected function buildColumnByCollection(array $row, Collection $columns, stri
 
     /**
      * Decode content to a readable text value.
-     *
-     * @param  mixed  $data
-     * @return mixed
      */
     protected function decodeContent(mixed $data): mixed
     {
diff --git a/src/config/config.php b/src/config/config.php
index 51bc488..62d1365 100644
--- a/src/config/config.php
+++ b/src/config/config.php
@@ -23,13 +23,13 @@
          * With Model: App\Post
          * Export filename: posts_timestamp
          */
-        'model' => '',
+        'model' => 'App\\Models',
     ],
 
     /*
      * Set Custom stub folder
      */
-    //'stub' => '/resources/custom_stub',
+    // 'stub' => '/resources/custom_stub',
 
     /*
      * PDF generator to be used when converting the table to pdf.
diff --git a/tests/DataTableServiceTest.php b/tests/DataTableServiceTest.php
index 341392a..91b1b66 100644
--- a/tests/DataTableServiceTest.php
+++ b/tests/DataTableServiceTest.php
@@ -5,17 +5,19 @@
 use Illuminate\Foundation\Testing\DatabaseTransactions;
 use Illuminate\Http\Response;
 use Illuminate\Support\Collection;
+use PHPUnit\Framework\Attributes\Test;
 use Symfony\Component\HttpFoundation\BinaryFileResponse;
 use Yajra\DataTables\Buttons\Tests\DataTables\UsersDataTable;
 use Yajra\DataTables\Buttons\Tests\Models\User;
 use Yajra\DataTables\EloquentDataTable;
+use Yajra\DataTables\Services\DataTable;
 
 class DataTableServiceTest extends TestCase
 {
     use DatabaseTransactions;
 
-    /** @test */
-    public function it_can_handle_ajax_request()
+    #[Test]
+    public function it_can_handle_ajax_request(): void
     {
         $response = $this->getAjax('/users');
 
@@ -26,8 +28,8 @@ public function it_can_handle_ajax_request()
         ]);
     }
 
-    /** @test */
-    public function it_returns_view_on_normal_get_request()
+    #[Test]
+    public function it_returns_view_on_normal_get_request(): void
     {
         $response = $this->get('users');
 
@@ -35,32 +37,32 @@ public function it_returns_view_on_normal_get_request()
         $response->assertSeeText('LaravelDataTables');
     }
 
-    /** @test */
-    public function it_can_return_a_csv_file()
+    #[Test]
+    public function it_can_return_a_csv_file(): void
     {
         $response = $this->get('users?action=csv');
 
         $this->assertInstanceOf(BinaryFileResponse::class, $response->baseResponse);
     }
 
-    /** @test */
-    public function it_can_return_a_xls_file()
+    #[Test]
+    public function it_can_return_a_xls_file(): void
     {
         $response = $this->get('users?action=excel');
 
         $this->assertInstanceOf(BinaryFileResponse::class, $response->baseResponse);
     }
 
-    /** @test */
-    public function it_can_return_a_pdf_file()
+    #[Test]
+    public function it_can_return_a_pdf_file(): void
     {
         $response = $this->get('users?action=pdf');
 
         $this->assertInstanceOf(Response::class, $response->baseResponse);
     }
 
-    /** @test */
-    public function it_allows_before_response_callback()
+    #[Test]
+    public function it_allows_before_response_callback(): void
     {
         $response = $this->getAjax('users/before');
         $response->assertOk();
@@ -69,8 +71,8 @@ public function it_allows_before_response_callback()
         $this->assertEquals($row['name'].'X', $row['nameX']);
     }
 
-    /** @test */
-    public function it_allows_response_callback()
+    #[Test]
+    public function it_allows_response_callback(): void
     {
         $response = $this->getAjax('users/response');
         $response->assertOk();
@@ -79,28 +81,36 @@ public function it_allows_response_callback()
         $this->assertEquals(1, $response->json('recordsFiltered'));
     }
 
+    #[Test]
+    public function it_is_macroable(): void
+    {
+        $dataTable = new class extends DataTable {};
+
+        $this->assertObjectHasProperty('macros', $dataTable);
+        $this->assertTrue(method_exists($dataTable, 'macro'), 'Method macro does not exist.');
+        $this->assertTrue(method_exists($dataTable, 'mixin'), 'Method mixin does not exist.');
+
+        DataTable::macro('macroMethod', fn () => 'macro');
+
+        $this->assertEquals('macro', $dataTable->macroMethod());
+    }
+
     protected function setUp(): void
     {
         parent::setUp();
 
         $router = $this->app['router'];
-        $router->get('/users', function (UsersDataTable $dataTable) {
-            return $dataTable->render('tests::users');
-        });
-
-        $router->get('/users/before', function (UsersDataTable $dataTable) {
-            return $dataTable->before(function (EloquentDataTable $dataTable) {
-                $dataTable->addColumn('nameX', fn (User $user) => $user->name.'X');
-            })->render('tests::users');
-        });
-
-        $router->get('/users/response', function (UsersDataTable $dataTable) {
-            return $dataTable->response(function (Collection $data) {
-                $data['recordsTotal'] = 2;
-                $data['recordsFiltered'] = 1;
-
-                return $data;
-            })->render('tests::users');
-        });
+        $router->get('/users', fn (UsersDataTable $dataTable) => $dataTable->render('tests::users'));
+
+        $router->get('/users/before', fn (UsersDataTable $dataTable) => $dataTable->before(function (EloquentDataTable $dataTable) {
+            $dataTable->addColumn('nameX', fn (User $user) => $user->name.'X');
+        })->render('tests::users'));
+
+        $router->get('/users/response', fn (UsersDataTable $dataTable) => $dataTable->response(function (Collection $data) {
+            $data['recordsTotal'] = 2;
+            $data['recordsFiltered'] = 1;
+
+            return $data;
+        })->render('tests::users'));
     }
 }
diff --git a/tests/DataTables/UsersDataTable.php b/tests/DataTables/UsersDataTable.php
index 374620c..0a05c98 100644
--- a/tests/DataTables/UsersDataTable.php
+++ b/tests/DataTables/UsersDataTable.php
@@ -10,12 +10,10 @@
 
 class UsersDataTable extends DataTable
 {
-    /**
-     * @throws \Yajra\DataTables\Exceptions\Exception
-     */
     public function dataTable(Builder $query): EloquentDataTable
     {
-        return datatables()->eloquent($query)->setRowId('id');
+        return (new EloquentDataTable($query))
+            ->setRowId('id');
     }
 
     public function query(User $user): Builder
@@ -26,12 +24,12 @@ public function query(User $user): Builder
     public function html(): \Yajra\DataTables\Html\Builder
     {
         return $this->builder()
-                    ->setTableId('users-table')
-                    ->minifiedAjax()
-                    ->columns([
-                        Column::make('id'),
-                        Column::make('name'),
-                    ]);
+            ->setTableId('users-table')
+            ->minifiedAjax()
+            ->columns([
+                Column::make('id'),
+                Column::make('name'),
+            ]);
     }
 
     protected function filename(): string
diff --git a/tests/Providers/TestServiceProvider.php b/tests/Providers/TestServiceProvider.php
index ee09792..23ca2f6 100644
--- a/tests/Providers/TestServiceProvider.php
+++ b/tests/Providers/TestServiceProvider.php
@@ -6,7 +6,7 @@
 
 class TestServiceProvider extends ServiceProvider
 {
-    public function boot()
+    public function boot(): void
     {
         $this->loadViewsFrom(__DIR__.'/../views', 'tests');
     }
diff --git a/tests/TestCase.php b/tests/TestCase.php
index e72296a..d063f36 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,7 +2,6 @@
 
 namespace Yajra\DataTables\Buttons\Tests;
 
-use Barryvdh\Snappy\ServiceProvider;
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Testing\TestResponse;
 use Orchestra\Testbench\TestCase as BaseTestCase;
@@ -23,7 +22,7 @@ protected function setUp(): void
         $this->seedDatabase();
     }
 
-    protected function migrateDatabase()
+    protected function migrateDatabase(): void
     {
         /** @var \Illuminate\Database\Schema\Builder $schemaBuilder */
         $schemaBuilder = $this->app['db']->connection()->getSchemaBuilder();
@@ -62,7 +61,7 @@ protected function migrateDatabase()
         }
     }
 
-    protected function seedDatabase()
+    protected function seedDatabase(): void
     {
         $adminRole = Role::create(['role' => 'Administrator']);
         $userRole = Role::create(['role' => 'User']);
@@ -111,16 +110,15 @@ protected function getPackageProviders($app): array
             DataTablesServiceProvider::class,
             ButtonsServiceProvider::class,
             HtmlServiceProvider::class,
-            ServiceProvider::class,
         ];
     }
 
-    public function getAjax($uri, array $headers = []): TestResponse
+    public function getAjax(string $uri, array $headers = []): TestResponse
     {
         return $this->getJson($uri, array_merge(['X-Requested-With' => 'XMLHttpRequest'], $headers));
     }
 
-    public function postAjax($uri, array $headers = []): TestResponse
+    public function postAjax(string $uri, array $headers = []): TestResponse
     {
         return $this->postJson($uri, array_merge(['X-Requested-With' => 'XMLHttpRequest'], $headers));
     }
