Skip to content

Instantly share code, notes, and snippets.

@noamanahmed
Created April 30, 2020 17:50
Show Gist options
  • Save noamanahmed/8749a829294e250d5aca7f88971f8bfe to your computer and use it in GitHub Desktop.
Save noamanahmed/8749a829294e250d5aca7f88971f8bfe to your computer and use it in GitHub Desktop.
A Datatable Class written for insanely fast generation of add and edit columns with the help of PHP Reflection methods.
<?php
namespace App\Datatables;
use Str;
class BaseTable
{
use FiltersTrait;
/**
* Reflection Object for this class
*
* @var object
*/
public $dt_reflection;
/**
* Datatables
*
* @var object
*/
public $dt;
/**
* Eloquent Modal
*
* @var object
*/
public $modal;
/**
* Names of the columns to be displayed raw
*
* @var array
*/
public $raw_columns = ['actions'];
/**
* EagerLoad Relationships in query
*
* @var array
*/
public $with = [];
/**
* EagerLoad Relationships Count in query
*
* @var array
*/
public $with_count = [];
/**
* JSON Reponse
*
* @var boolean
*/
public $json = true;
/**
* Add DT_RowIndex in JSON Response
*
* @var boolean
*/
public $add_index_column = true;
/**
* Boot all pre-requistics
*
* @return void
*/
public function boot()
{
//Load Datatables
$this->dt = datatables();
//Get Reflection object for this object
$this->dt_reflection = new \ReflectionObject($this);
}
/**
* Here all the magic happens
*
* @param Eloquent|Collection|QueryBuilder $query
* @return void
*/
public function make($query)
{
//Get datatbles
$dt = $this->dt;
//Make datatables query
$dt = $dt->of($query);
//Add Columns
foreach ($this->get_add_columns() as $key => $column) {
$dt->addColumn($key, function ($data) use ($column) {
return $this->$column($data);
});
}
//Edit Columns
foreach ($this->get_edit_columns() as $key => $column) {
$dt->editColumn($key, function ($data) use ($column) {
return $this->$column($data);
});
}
//Raw Columns
if (!empty($this->raw_columns)) {
$dt->rawColumns($this->raw_columns);
}
//Remove Columns which are not required
if (!empty($this->remove_columns)) {
foreach ($this->remove_columns as $column) {
$dt->removeColumns($column);
}
}
//Add Index Columns
if ($this->add_index_column) {
$dt->addIndexColumn();
}
//Save DT incase of reuse
$this->dt = $dt;
return $dt;
}
/**
* Get all the methods for this class
*
* @return array
*/
public function get_methods()
{
return $this->dt_reflection->getMethods();
}
/**
* Get All Add Columns functions
*
* @return void
*/
public function get_add_columns()
{
//Get all methods
$methods = $this->get_methods();
//Set default to empty
$add_columns = [];
foreach ($methods as $method) {
//Only Add editColumn methods
if (strpos($method->name, 'addColumn') === 0) {
//Sanity Check
//Check if there is an editColumn function
if (strlen(substr($method->name, strlen('addColumn'))) == 0) {
//Ignore this function
continue;
}
//Convert Key to snake case and store the callback
$add_columns[Str::snake(substr($method->name, strlen('addColumn')))] = $method->name;
}
}
//Return the columns
return $add_columns;
}
/**
* Get all the edit column functions
*
* @return void
*/
public function get_edit_columns()
{
//Get all methods
$methods = $this->get_methods();
//Set default to empty
$edit_columns = [];
foreach ($methods as $method) {
//Only Add editColumn methods
if (strpos($method->name, 'editColumn') === 0) {
//Sanity Check
//Check if there is an editColumn function
if (strlen(substr($method->name, strlen('editColumn'))) == 0) {
//Ignore this function
continue;
}
//Convert Key to snake case and store the callback
$edit_columns[Str::snake(substr($method->name, strlen('editColumn')))] = $method->name;
}
}
//Return the columns
return $edit_columns;
}
/**
* Get all the apply filters functions
*
* @return void
*/
public function get_apply_filters()
{
//Get all methods
$methods = $this->get_methods();
//Set default to empty
$apply_filters = [];
foreach ($methods as $method) {
//Only Add applyFilter methods
if (strpos($method->name, 'applyFilter') === 0) {
//Sanity Check
//Check if there is an applyFilter function
if (strlen(substr($method->name, strlen('applyFilter'))) == 0) {
//Ignore this function
continue;
}
//Convert Key to snake case and store the callback
$apply_filters[Str::snake(substr($method->name, strlen('applyFilter')))] = $method->name;
}
}
//Return the columns
return $apply_filters;
}
/**
* Generate datatables and function to be called in controller
*
* @param Eloquent|Collection|QueryBuilder $query
* @param Illuminate\Database\Eloquent\Model $modal
* @return mixed
*/
public function datatables($query, $modal)
{
//Boot
$this->boot();
//Store Modal
$this->modal = $modal;
//Apply Filters
$filtered_query = $this->query($query);
//Make Datatables from the query
$datatables = $this->make($filtered_query);
//Generate JSON if Set
if ($this->json) {
$datatables = $datatables->toJson();
}
//Send table data back to controller
return $datatables;
}
/**
* Modify Query/Collection
*
* @param Eloquent|Collection|QueryBuilder $query
* @return mixed Eloquent|Collection|QueryBuilder
*/
public function query($query)
{
if ($query instanceof \Illuminate\Database\Eloquent\Builder) {
$query = $this->applyQueryFilters($query);
}
if (!empty($this->with)) {
$query = $query->with($this->with);
}
if (!empty($this->with_count)) {
$query = $query->withCount($this->with_count);
}
return $query;
}
/**
* Apply filters for query
*
* @param Illuminate\Database\Eloquent\Builder $query
* @return void
*/
public function applyQueryFilters($query)
{
$filters = $this->get_apply_filters();
foreach ($filters as $filter) {
$query = $this->$filter($query);
}
return $query;
}
/**
* Get Modal Short Name for Datatables
*
* @return void
*/
public function getModalShortName()
{
$this->modal_reflection = new \ReflectionObject($this->modal);
return $this->modal_reflection->getShortName();
}
public function getModalShortNameInLowerCase()
{
return strtolower($this->getModalShortName());
}
}
<?php
namespace App\Datatables;
use App\Datatables\Filters\DateFilter;
use App\Datatables\Filters\NameFilter;
use Carbon\Carbon;
class Brand extends BaseTable
{
use ActionsTrait;
use NameFilter;
use DateFilter;
/**
* EagerLoad Relationships in query
*
* @var array
*/
public $with = [];
/**
* EagerLoad Relationships Count in query
*
* @var array
*/
public $with_count = ['records'];
/**
* Names of the columns to be displayed raw
*
* @var array
*/
public $raw_columns = ['actions', 'status', 'records_count'];
public function editColumnRecordsCount($data)
{
return '<span class="badge badge-primary text-white p-2">' . $data['records_count'] . '</span>';
}
}
<?php
namespace App\Datatables\Filters;
trait DateFilter
{
public function applyFilterDate($query)
{
if (!$this->has_filter('date')) {
return $query;
}
$date = $this->get_filter('date');
if (empty($date)) {
return $query;
}
$date = Carbon::parse($date);
return $query->whereDate('date', $date);
}
}
<?php
namespace App\Datatables;
use Str;
trait FiltersTrait
{
public function has_filter($key)
{
if (is_null(request()->filter)) {
return false;
}
$filters = request()->filter;
if (!is_array($filters)) {
return false;
}
if (!array_key_exists($key, $filters)) {
return false;
}
return true;
}
public function get_filter($key)
{
if (!$this->has_filter($key)) {
return false;
}
return request()->filter[$key];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment