Skip to content

Feature: Ability to call setRelation (actually anything) for every Model instance. #2862

@OzanKurt

Description

@OzanKurt

Let me go through it step by step:

1- I extended the default EloquentDataTable and added a method that overwrites the processResults method. This allows me to interact with the DataProcessor object.

<?php

namespace App\DataTables\Engines;

use App\DataTables\Processors\DataProcessor;
use Yajra\DataTables\EloquentDataTable as BaseEloquentDataTable;

class EloquentDataTable extends BaseEloquentDataTable
{
    protected $setRelationsCallback = null;

    public function setRelationsCallback(callable $callable)
    {
        $this->setRelationsCallback = $callable;

        return $this;
    }

    protected function processResults($results, $object = false)
    {
        $processor = new DataProcessor(
            $results,
            $this->getColumnsDefinition(),
            $this->templates,
            $this->request->input('start')
        );

        $processor->setRelationsCallback($this->setRelationsCallback);

        return $processor->process($object);
    }
}

2- I also needed to extend the DataProcessor so that I can customize the process method. This is where we run the callback function we defined for a given model.

<?php

namespace App\DataTables\Processors;

use Yajra\DataTables\Processors\DataProcessor as BaseDataProcessor;
use Yajra\DataTables\Utilities\Helper;

class DataProcessor extends BaseDataProcessor
{
    protected $setRelationsCallback = null;

    public function setRelationsCallback(callable $callable)
    {
        $this->setRelationsCallback = $callable;

        return $this;
    }

    /**
     * Process data to output on browser.
     *
     * @param  bool  $object
     * @return array
     */
    public function process($object = false)
    {
        $this->output = [];
        $indexColumn  = config('datatables.index_column', 'DT_RowIndex');

        foreach ($this->results as $row) {
            $data  = Helper::convertToArray($row, ['hidden' => $this->makeHidden, 'visible' => $this->makeVisible]);

            if ($callback = $this->setRelationsCallback) {
                $callback($row);
            }

            $value = $this->addColumns($data, $row);
            $value = $this->editColumns($value, $row);
            $value = $this->setupRowVariables($value, $row);
            $value = $this->selectOnlyNeededColumns($value);
            $value = $this->removeExcessColumns($value);

            if ($this->includeIndex) {
                $value[$indexColumn] = ++$this->start;
            }

            $this->output[] = $object ? $value : $this->flatten($value);
        }

        return $this->escapeColumns($this->output);
    }
}

3- I think the setRelationsCallback name is wrong, since this gives us the ability to do whatever we want with the Modal instance of every row. Here is what I did with mine:

    public function dataTable($query): DataTableAbstract
    {
        $builder = datatables()->make($query);

        $builder->setRelationsCallback(function (PriceListEntry $priceListEntry) {
            $priceListEntry->setRelation('priceList', $this->priceList);
        });

        // ...
    }

Let me know what you think about this.

I am not sure how useful this might be since it's theoretically just 1 Less Query and 1 Less Model Instance in memory.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions