title: Yajra DataTables service implementation upgrade from Laravel 5 to Laravel 6
body: <p>We have been using Yajra DataTables with Laravel 5 for a few years and have built up a library of over 50 of them, basically for the index page of a BREAD UI. It's finally time to upgrade, and  We're using the service implementation, which looks like this.</p>
  <p>The current code is working against</p>
  <pre><code>&quot;yajra/laravel-datatables-oracle&quot;: &quot;^6.0&quot;,
  </code></pre>
  <p>Here is the Controller:</p>
  <pre><code>&lt;?php
  
  namespace App\Http\Controllers;
  
  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Validator;
  use App\DataTables\WidgetDataTable;
  use App\Models\Widget;
  use Illuminate\Support\Facades\Auth;
  use App\Models\Widgetaccount;
  use App\Events\Widgetcrud;
  use App\DataTables\WidgetHistoryDataTable;
  use Illuminate\Support\Facades\DB;
  
  class WidgetController extends Controller
  {
      /**
       * Create a new controller instance
       *
       * @return void
       */
      public function __construct()
      {
          $this-&gt;middleware('permission:widget_view', ['only' =&gt; ['index', 'history']]);
          $this-&gt;middleware('permission:widget_create', ['only' =&gt; ['create','store']]);
          $this-&gt;middleware('permission:widget_edit', ['only' =&gt; ['edit','update']]);
          $this-&gt;middleware('permission:widget_delete', ['only' =&gt; ['destroy']]);
      }
  
      /**
       * Display a listing of the resource.
       *
       * @param  object $dataTable
       * @return \Illuminate\Http\Response
       */
      public function index(WidgetDataTable $dataTable)
      {
          return $dataTable-&gt;render('widget.index', [
              'title' =&gt; 'Manage Widgets',
          ]);
      }
  
      // other methods here
  
  }
  </code></pre>
  <p>Here is the DataTables class:</p>
  <pre><code>&lt;?php
  
  namespace App\DataTables;
  
  use Illuminate\Support\Facades\DB;
  use Yajra\DataTables\Services\DataTable;
  use Illuminate\Support\Facades\Auth;
  
  class widgetDataTable extends DataTable
  {
  
      /**
       * Display ajax rwidgetonse.
       *
       * @return \Illuminate\Http\JsonResponse
       */
      public function ajax()
      {
          return $this-&gt;datatables
              -&gt;queryBuilder($this-&gt;query())
              -&gt;editColumn(
                  'edit accounts',
                  function ($widget) {
                      return '&lt;a href=&quot;' . route('widgetaccounts.index', 'widgetid=' . $widget-&gt;id)
                          . '&quot; class=&quot;btn btn-xs btn-primary&quot;&gt;&lt;i class=&quot;glyphicon glyphicon-edit&quot;&gt;&lt;/i&gt; &lt;/a&gt;';
  
  
                  }
              )
              -&gt;editColumn(
                  'documentation',
                  function ($widget) {
                      if ($widget-&gt;documentation != null) {
                          return '&lt;a href=&quot;javascript:void(0)&quot; data-value=&quot;' . $widget-&gt;documentation .
                              '&quot; class=&quot;btn btn-xs btn-primary opendocument&quot;&gt;View&lt;/a&gt;';
                      } else {
                          return '';
                      }
                  }
              )
              -&gt;addColumn(
                  'action',
                  function ($widget) {
                      return '&lt;a href=&quot;' . route('widgets.edit', $widget-&gt;id) .
                          '&quot; class=&quot;btn btn-xs btn-primary&quot; dusk=&quot;widget-edit-button-'.$widget-&gt;id .'&quot;&gt;&lt;i class=&quot;glyphicon glyphicon-edit&quot;&gt;&lt;/i&gt; Edit&lt;/a&gt;
              &lt;a href=&quot;javascript:void(0)&quot; data-remote=&quot;' . route('widgets.destroy', $widget-&gt;id) .
                      '&quot; class=&quot;btn btn-xs btn-danger btn-delete&quot; dusk=&quot;widget-delete-button-'.$widget-&gt;id .'&quot;&gt;&lt;i class=&quot;glyphicon glyphicon-trash&quot;&gt;&lt;/i&gt;Delete&lt;/a&gt;';
                  }
              )
              -&gt;make(true);
      }
  
      /**
       * Get the query object to be processed by dataTables.
       *
       * @return \Illuminate\Database\Eloquent\Builder|
       */
      public function query()
      {
          $widget_id = null;
          if ($this-&gt;request()-&gt;has(&quot;widgetid&quot;)) {
              $widget_id = $this-&gt;request()-&gt;get(&quot;widgetid&quot;);
          }
  
          $query = DB::connection('dashboard')
              -&gt;table('widgets')
              -&gt;join('users', 'users.id', '=', 'widgets.user_id')
              -&gt;whereNull('widgets.deleted_at')
              -&gt;when($widget_id,
                  function ($queryvar, $widget_id) {
                      return $queryvar-&gt;where('widgets.id', $widget_id);
              })
              -&gt;select(
                  'widgets.id',
                  'widgets.name',
                  'widgets.active',
                  'users.name as username',
                  'widgets.documentation',
                  'widgets.created_at',
                  'widgets.updated_at',
                  'widgets.deleted_at'
              );
  
          return $this-&gt;applyScopes($query);
      }
  
      /**
       * Optional method if you want to use html builder.
       *
       * @return \Yajra\Datatables\Html\Builder
       */
      public function html()
      {
          if (Auth::user()-&gt;can('distribution_manage_widget_lists_edit')) {
              return $this-&gt;builder()
                      -&gt;columns($this-&gt;getColumns())
                      -&gt;ajax('')
                      -&gt;addAction(['width' =&gt; '80px'])
                      -&gt;parameters([
                          'dom' =&gt; 'lBfrtip',
                          'buttons' =&gt; ['csv', 'excel'],
                          'pageLength' =&gt; 50
              ]);
          }else{
              return $this-&gt;builder()
                      -&gt;columns($this-&gt;getColumns())
                      -&gt;ajax('')
                      -&gt;parameters([
                          'dom' =&gt; 'lBfrtip',
                          'buttons' =&gt; ['csv', 'excel'],
                          'pageLength' =&gt; 50
              ]);
          }
      }
  
      /**
       * Get columns.
       *
       * @return array
       */
      protected function getColumns()
      {
          return [
              'id',
              'name',
              'active',
              'documentation' =&gt; ['searchable' =&gt; false, 'orderable' =&gt; false],
              'edit accounts' =&gt; ['searchable' =&gt; false, 'orderable' =&gt; false],
              'last edited by' =&gt; ['name' =&gt; 'users.name', 'data' =&gt; 'username'],
              'created_at',
              'updated_at',
          ];
      }
  
      /**
       * Get filename for export.
       *
       * @return string
       */
      protected function filename()
      {
          return 'widgetdatatables_'.time();
      }
  }
  </code></pre>
  <p>Here is the view:</p>
  <pre><code>@extends('layouts.main')
  @section('content')
  @include('partials.panel-open', [ 'title' =&gt; &quot;Manage widgets&quot; ])
  &lt;form action=&quot;{{route('widgetsearch')}}&quot;  method=&quot;POST&quot;&gt;
          {{ csrf_field() }}
  &lt;div class=&quot;search_button_group&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-sm-4 col-sm-offset-2&quot;&gt;
        &lt;label&gt;Search for widget-related Settings: &lt;/label&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col-sm-6&quot;&gt;
        &lt;div class=&quot;input-group&quot;&gt;
          &lt;input type=&quot;text&quot; class=&quot;form-control&quot; placeholder=&quot;&quot; name=&quot;search&quot; aria-describedby=&quot;basic-addon1&quot; required=&quot;required&quot;&gt;
          &lt;button class=&quot;input-group-addon btn btn-primary&quot; id=&quot;basic-addon1&quot; type=&quot;submit&quot;&gt;Go&lt;/button&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;/form&gt;
  &lt;div class=&quot;row form-group&quot;&gt;
    &lt;div class=&quot;col-sm-6&quot;&gt;
        @permission(('widget_create'))
        &lt;a href=&quot;{{ route('widgets.create') }}&quot; class=&quot;btn btn-primary&quot; dusk=&quot;widget-create-button&quot;&gt;Add New widget&lt;/a&gt;
      @endpermission
    &lt;/div&gt;
    &lt;div class=&quot;col-sm-6&quot;&gt;
      &lt;div class=&quot;text-right&quot;&gt;
        &lt;a href=&quot;{{ route('widgets.history') }}&quot; class=&quot;btn btn-primary&quot;&gt;widget History&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  {!! $dataTable-&gt;table(['class' =&gt; 'table table-bordered','id' =&gt;'widget-table']) !!}
  @permission(('widget_create'))
      &lt;a href=&quot;{{ route('widgets.create') }}&quot; class=&quot;btn btn-primary&quot;&gt;Add New widget&lt;/a&gt;
  @endpermission
  @include('partials.panel-close')
  &lt;div id=&quot;myModal&quot; class=&quot;modal fade&quot; role=&quot;dialog&quot;&gt;
    &lt;div class=&quot;modal-dialog&quot;&gt;
      &lt;!-- Modal content--&gt;
      &lt;div class=&quot;modal-content&quot;&gt;
        &lt;div class=&quot;modal-header&quot;&gt;
          &lt;button type=&quot;button&quot; class=&quot;close&quot; data-dismiss=&quot;modal&quot;&gt;&amp;times;&lt;/button&gt;
          &lt;h4 class=&quot;modal-title&quot;&gt;Documentation&lt;/h4&gt;
        &lt;/div&gt;
        &lt;div class=&quot;modal-body&quot;&gt;
  
        &lt;/div&gt;
        &lt;div class=&quot;modal-footer&quot;&gt;
          &lt;button type=&quot;button&quot; class=&quot;btn btn-default&quot; data-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  @endsection
  @push('scripts')
  &lt;script src=&quot;/vendor/datatables/buttons.server-side.js&quot;&gt;&lt;/script&gt;
  {!! $dataTable-&gt;scripts() !!}
  &lt;script type=&quot;text/javascript&quot;&gt;
  $('#widget-table').on('click', '.btn-delete[data-remote]', function (e) {
      e.preventDefault();
      if (confirm(&quot;Are you sure you want to delete&quot;))
       {
          $.ajaxSetup({
              headers: {
                  'X-CSRF-TOKEN': $('meta[name=&quot;csrf-token&quot;]').attr('content')
              }
          });
          var url = $(this).data('remote');
           $.ajax({
               url: url,
               type: 'DELETE',
               dataType: 'json',
               data: {method: '_DELETE', submit: true}
           })
               .always(function (data) {
                   var count = data.count;
                   if (count == 0) {
                       $('#widget-table').DataTable().draw(false);
                   } else {
                       alert(&quot;widget can't be deleted as there are associated widget Account/s (#&quot; + count + &quot;) under the same. Kindly remove the widget Account/s first.&quot;);
                   }
               });
      }
  });
  $(document).on(&quot;click&quot;,&quot;.opendocument&quot;,function(){
      $(&quot;.modal-body&quot;).html($(this).data('value'));
      $('#myModal').modal('show');
  });
  &lt;/script&gt;
  @endpush
  </code></pre>
  <p>Now I've updated composer and am trying to use:</p>
  <pre><code>&quot;yajra/laravel-datatables-oracle&quot;: &quot;^9.0&quot;,
  &quot;yajra/laravel-datatables-buttons&quot;: &quot;^4.0&quot;,
  </code></pre>
  <p>And when I view the widget index, I get the ajax error dialog</p>
  <pre><code>DataTables warning: table id=widget-table - 
  Ajax error. For more information about this error, 
  please see http://datatables.net/tn/7
  </code></pre>
  <p>When I look in the Laravel.log:</p>
  <pre><code>[2020-07-24 10:30:55] local.ERROR: Call to a member function queryBuilder() on null 
  {&quot;userId&quot;:19,&quot;exception&quot;:&quot;[object] 
  (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to a member function queryBuilder() on null at /Projects/my-app/app/DataTables/WidgetDataTable.php:20)
  [stacktrace]
  #0 [internal function]: App\\DataTables\\WidgetDataTable-&gt;ajax()
  </code></pre>
  <p>So, it seems that on this line:</p>
  <pre><code>    return $this-&gt;datatables
          -&gt;queryBuilder(...
  </code></pre>
  <p>the <code>datatables</code> property is not set. So, I am stuck as to how to proceed, and have broken my entire application. Looking for advice on what to try or a guide on how to upgrade the Yajra service implementation without having to modify hundreds of files.</p>