Skip to content

Commit

Permalink
Documentation, simple use cases functional
Browse files Browse the repository at this point in the history
More thorough config and options
  • Loading branch information
gbrock committed Mar 29, 2015
1 parent 162b62e commit d4ba195
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 40 deletions.
106 changes: 87 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
[![Latest Tag](https://img.shields.io/github/tag/gbrock/laravel-table.svg)](https://github.com/gbrock/laravel-table/releases)
<!--[![Build Status](https://img.shields.io/travis/gbrock/laravel-table.svg)](https://travis-ci.org/gbrock/laravel-table)-->

Adds database-level sorting to Laravel models. **This project is under ongoing development.**
This package contains flexible ways of rendering Eloquent collections as dynamic HTML tables. This includes
techniques for sortable columns, automatic pagination, ~~user-definable amount of rows shown per page, batch action
handling, and extensible filtering~~ (coming soon).


## Installation
Expand All @@ -14,38 +16,104 @@ Require the package in your `composer.json`:
"gbrock/laravel-table": "dev-master"
```

(Optional) Publish the views and config:

```
php artisan vendor:publish
```

## Usage

Add the trait to the models you wish to sort.
**In order to render an HTML table of Eloquent models into a view**, first create a Table object, passing in your
model collection (this could be done in your controller, repository, or any service class):

```php
$rows = User::get(); // Get all users from the database
$table = Table::create($rows); // Generate a Table based on these "rows"
```

Then pass that object to your view:

```php
use Gbrock\Table\TableSortable;
return view('users.index', ['table' => $table]);
```

class User extends Model {
In your view, the table object can be rendered using its `render` function:

use TableSortable;
```php
{!! $table->render() !!}
```

Since no fields are allowed to be sorted by default for security reasons, add a `$sortable` array to your model
describing which fields are allowed to be sorted:
Which would render something like this:

![Basic example](https://raw.githubusercontent.com/gbrock/laravel-table/master/examples/images/basic_initialization.png)

### Sorting

To add links in your headers which sort the indicated column, add the `Sortable` trait to the your model. Since no
fields are allowed to be sorted by default (for security reasons), also add a `sortable` array containing allowed fields.

```php
/**
* The attributes which may be used for sorting dynamically.
*
* @var array
*/
protected $sortable = ['id', 'username', 'email', 'last_login'];
use Gbrock\Table\Traits\Sortable;

class User extends Model {

use Sortable;

/**
* The attributes which may be used for sorting dynamically.
*
* @var array
*/
protected $sortable = ['username', 'email', 'created_at'];
```

This adds the `sortable` scope to your model, which you should use when retrieving rows. Altering our first example,
the database call / Table creation:

```php
$rows = User::sorted()->get(); // Get all users from the database, but listen to the user Request and sort accordingly
```

Last, use the model's `sortable` [scope](http://laravel.com/docs/5.0/eloquent#query-scopes) to get your sorted data:
Now, our table will be rendered with links in the header:

![Sortable example](https://raw.githubusercontent.com/gbrock/laravel-table/master/examples/images/sortable_initialization.png)

The links will contain query strings like `?sort=username&direction=asc`.

### Pagination

If you paginate your Eloquent collection, it will automatically be rendered below the table:

```php
$rows = User::sorted()->paginate(); // Get all users from the database, sort, and paginate
```

### Customizing the Columns

For a bit more control, pass in a second argument to your database call / Table creation, **columns**:

```php
// This is one possible way you could get what the user requested to be sorted.
$sortField = Input::get('sort');
$sortDir = Input::get('dir', 'desc'); // default desc
$table = Table::create($rows, ['username', 'created_at']); // Generate a Table based on these "rows"
```

Since our view is accessing our model's attributes, we can add or modify any column key we'd like by using
[accessors](http://laravel.com/docs/5.0/eloquent#accessors-and-mutators):

// Get the collection of rows using the "sorted" scope
$rows = User::sorted($sortField, $sortDir);
```php
protected function getRenderedCreatedAtAttribute()
{
// We access the following diff string with "$model->rendered_created_at"
return $this->created_at->diffForHumans();
}
```

### Customizing the View

The default view favors the `rendered_foo_bar` attribute, if present, else it uses the `foo_bar` attribute. A copy of
the view file is located in `/resources/vendor/gbrock/tables/` after you've run `php artisan vendor:publish`. You
can copy this file wherever you'd like and alter it, then tell your table to use the new view:

```php
$table->setView('users.table');
```
5 changes: 2 additions & 3 deletions config/tables.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

return [
'key_field' => 'sort',
'key_direction' => 'direction',
'default_direction' => 'asc',

'key_direction' => 'dir',
'default_direction' => 'desc',
];
Binary file modified examples/images/basic_initialization.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/images/sortable_initialization.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 9 additions & 9 deletions src/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static function create()
*/
public function setOptionsFromModel($model)
{
if(in_array($this->getField(), $model->getSortable()))
if($model->is_sortable && in_array($this->getField(), $model->getSortable()))
{
// The model dictates that this column should be sortable
$this->setSortable(true);
Expand All @@ -82,12 +82,12 @@ public function setOptionsFromModel($model)
*/
public function isSorted()
{
if(Request::input('sort') == $this->getField())
if(Request::input(config('gbrock-tables.key_field')) == $this->getField())
{
return true;
}

if(!Request::input('sort') && $this->model && $this->model->getSortingField() == $this->getField())
if(!Request::input(config('gbrock-tables.key_field')) && $this->model && $this->model->getSortingField() == $this->getField())
{
// No sorting was requested, but this is the default field.
return true;
Expand Down Expand Up @@ -115,8 +115,8 @@ public function getSortURL($direction = false)

// Generate and return a URL which may be used to sort this column
return $this->generateUrl(array_filter([
'sort' => $this->getField(),
'direction' => $direction,
config('gbrock-tables.key_field') => $this->getField(),
config('gbrock-tables.key_direction') => $direction,
]));
}

Expand All @@ -129,12 +129,12 @@ public function getDirection()
if($this->isSorted())
{
// If the column is currently being sorted, grab the direction from the query string
$this->direction = Request::input('direction');
$this->direction = Request::input(config('gbrock-tables.key_direction'));
}

if(!$this->direction)
{
$this->direction = 'asc';
$this->direction = config('gbrock-tables.default_direction');
}

return $this->direction;
Expand Down Expand Up @@ -187,8 +187,8 @@ public function generateUrl($parameters = [])
protected function getCurrentInput()
{
return Input::only([
'sort' => Request::input('sort'),
'direction' => Request::input('direction'),
config('gbrock-tables.key_field') => Request::input(config('gbrock-tables.key_field')),
config('gbrock-tables.key_direction') => Request::input(config('gbrock-tables.key_direction')),
]);
}

Expand Down
48 changes: 40 additions & 8 deletions src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class Table {

protected $models;
protected $columns;
protected $view = 'gbrock.tables::table';
protected $viewVars = [];

/**
* @param array $models
Expand Down Expand Up @@ -41,6 +43,26 @@ public function create($rows, $columns = false)
return $table;
}

/**
* @return string
*/
public function getView()
{
return $this->view;
}

/**
* @param string $view
*/
public function setView($view, $vars = true)
{
$this->view = $view;
if(is_array($vars) || !$vars)
{
$this->viewVars = $vars;
}
}

/**
* Add columns based on field names
* @param $columns
Expand Down Expand Up @@ -94,11 +116,21 @@ protected function getFieldsFromModels($models)
return [];
}

$fields = array_keys($models->first()->toArray());
$model = $models->first();

// These are the Laravel basic timestamp fields which we don't want to display, by default
$timestamp_fields = ['created_at', 'updated_at', 'deleted_at'];
// Grab the basic fields from the first model
$fields = array_keys($model->toArray());
// Remove the timestamp fields
$fields = array_diff($fields, $timestamp_fields);
if($model->isSortable)
{
// Add the fields from the model's sortable array
$fields = array_unique(array_merge($fields, $model->getSortable()));
}

// only those non-timestamp fields
return array_diff($fields, $timestamp_fields);
return $fields;
}

/**
Expand All @@ -108,19 +140,19 @@ protected function getFieldsFromModels($models)
public function render()
{
$this->appendPaginationLinks();
return view('gbrock.tables::table', $this->getViewData())->render();
return view($this->view, $this->getData())->render();
}

/**
* Generate the data needed to render the view.
* @return array
*/
protected function getViewData()
public function getData()
{
return [
return array_merge($this->viewVars, [
'rows' => $this->getRows(),
'columns' => $this->getColumns(),
];
]);
}

/**
Expand Down Expand Up @@ -176,7 +208,7 @@ private function appendPaginationLinks()
if(class_basename($this->models) == 'LengthAwarePaginator')
{
// This set of models was paginated. Make it append our current view variables.
$this->models->appends(Input::only('sort', 'direction'));
$this->models->appends(Input::only(config('gbrock-tables.key_field'), config('gbrock-tables.key_direction')));
}
else
{
Expand Down
7 changes: 6 additions & 1 deletion src/Traits/Sortable.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function scopeSorted($query, $field = false, $direction = false)
return $query;
}

// If the direction requested isn't correct, assume ascending
// If the direction requested isn't correct, grab from config
if($direction !== 'asc' && $direction !== 'desc')
{
$direction = config('gbrock-tables.default_direction');
Expand Down Expand Up @@ -83,5 +83,10 @@ protected function getSortingDirection()
// Otherwise return the primary key
return config('gbrock-tables.default_direction');
}

public function getIsSortableAttribute()
{
return true;
}
}

0 comments on commit d4ba195

Please sign in to comment.