Skip to content

Instantly share code, notes, and snippets.

@keyurshah
Forked from heroicpixels/gist:f70fd94d8d4d5158ba0f
Last active August 8, 2016 17:57
Show Gist options
  • Save keyurshah/fdcaf19d220830d1a683 to your computer and use it in GitHub Desktop.
Save keyurshah/fdcaf19d220830d1a683 to your computer and use it in GitHub Desktop.
#laravel
class Filterable {
public $model;
public $options;
public function __construct($model) {
$this->model = $model;
}
public function resetFilterableOptions() {
$this->options = array(
'bools' => array('and' => 'where', 'or' => 'orWhere'),
'callbacks' => array(),
'columns' => array(),
'defaultOperator' => '=',
'defaultWhere' => 'where',
'filters' => array(),
'orderby' => 'orderby',
'order' => 'order',
'operators' => array('=', '<', '>', '!=', 'like'),
'qstring' => array()
);
return $this;
}
public function setColumns($columns, $append = true) {
if ( is_null($this->options) ) {
$this->resetFilterableOptions();
}
if ( count(array_filter(array_keys($columns), 'is_string')) == 0 ) {
// Numeric indexes, so build new associative index array
$columns = array_combine($columns, $columns);
}
if ( !$append ) {
// Overwrite data
$this->options['columns'] = array();
}
foreach ( $columns as $k => $v ) {
// Strip off callbacks
if ( is_callable($v) ) {
$this->options['callbacks'][] = $v;
unset($columns[$k]);
}
}
$this->options['columns'] = array_merge($this->options['columns'], $columns);
return $this;
}
public function setQuerystring(array $str = array(), $append = true, $default = true) {
if ( is_null($this->options) ) {
$this->resetFilterableOptions();
}
if ( sizeof($str) == 0 && $default ) {
// Default to PHP query string
parse_str($_SERVER['QUERY_STRING'], $this->options['qstring']);
} else {
$this->options['qstring'] = $str;
}
if ( sizeof($this->options['qstring']) > 0 ) {
if ( !$append ) {
// Overwrite data
$this->options['filters'] = array();
}
foreach ( $this->options['qstring'] as $k => $v ) {
if ( $v == '' ) {
continue;
}
$thisColumn = isset($this->options['columns'][$k]) ? $this->options['columns'][$k] : false;
if ( $thisColumn ) {
// Query string part matches column (or alias)
$this->options['filters'][$thisColumn]['val'] = $v;
// Evaluate boolean parameter in query string
$thisBoolData = isset($this->options['qstring']['bool'][$k]) ? $this->options['qstring']['bool'][$k] : false;
$thisBoolAvailable = $thisBoolData && isset($this->options['bools'][$thisBoolData]) ? $this->options['bools'][$thisBoolData] : false;
if ( $thisBoolData && $thisBoolAvailable ) {
$this->options['filters'][$thisColumn]['boolean'] = $thisBoolAvailable;
} else {
$this->options['filters'][$thisColumn]['boolean'] = $this->options['defaultWhere'];
}
// Evaluate operator parameters in the query string
if ( isset($this->options['qstring']['operator'][$k]) && in_array($this->options['qstring']['operator'][$k], $this->options['operators']) ) {
$this->options['filters'][$thisColumn]['operator'] = $this->options['qstring']['operator'][$k];
} else {
// Default operator
$this->options['filters'][$thisColumn]['operator'] = $this->options['defaultOperator'];
}
}
}
}
return $this;
}
public function filterColumns($columns = array(), $validate = false) {
if ( sizeof($columns) > 0 ) {
// Set columns that can be filtered
$this->setColumns($columns);
}
// Validate columns
if ( $validate ) {
$this->validateColumns();
}
// Ensure that query string is parsed at least once
if ( sizeof($this->options['filters']) == 0 ) {
$this->setQuerystring();
}
// Apply conditions to Eloquent query object
if ( sizeof($this->options['filters']) > 0 ) {
foreach ( $this->options['filters'] as $k => $v ) {
$where = $v['boolean'];
if ( is_array($v['val']) ) {
if ( isset($v['val']['start']) && isset($v['val']['end']) ) {
// BETWEEN a AND b
$this->model->whereBetween($k, array($v['val']['start'], $v['val']['end']));
} else {
// a = b OR c = d OR...
$this->model->{$where}(function($q) use ($k, $v)
{
foreach ( $v['val'] as $key => $val ) {
$q->orWhere($k, $v['operator'], $val);
}
});
}
} else {
// a = b
$this->model->{$where}($k, $v['operator'], $v['val']);
}
}
}
// Apply callbacks
if ( sizeof($this->options['callbacks']) > 0 ) {
foreach ( $this->options['callbacks'] as $v ) {
$v($this->model);
}
}
// Sorting
if ( isset($this->options['qstring'][$this->options['orderby']]) && isset($this->options['columns'][$this->options['qstring'][$this->options['orderby']]]) ) {
$order = isset($this->options['qstring'][$this->options['order']]) ? $this->options['qstring'][$this->options['order']] : 'asc';
$this->model->orderBy($this->options['columns'][$this->options['qstring'][$this->options['orderby']]], $order);
}
return $this->model;
}
/**
*
* Validate the specified columns against the table's actual columns.
*
* @return $this
*/
public function validateColumns() {
if ( class_exists('\\Doctrine\\DBAL\\Driver\\PDOMySql\\Driver') ) {
$columns = DB::connection()->getDoctrineSchemaManager()->listTableColumns($this->getTable());
foreach ( $columns as $column ) {
$name = $column->getName();
$columns[$name] = $name;
}
$this->options['columns'] = array_intersect($this->options['columns'], $columns);
return $this;
}
die('You must have Doctrine installed in order to validate columns');
}
public function __call($name, $arguments) {
$retrieval = in_array($name, array('all', 'find', 'findOrFail', 'first', 'get', 'lists', 'paginate'));
$this->model = call_user_func_array(array($this->model, $name), $arguments);
if ( $retrieval ) {
return $this->model;
} else {
return $this;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment