Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/s-damian/larasort

Larasort : Column sorting with Laravel - Eloquent sortable
https://github.com/s-damian/larasort

eloquent eloquent-orm laravel laravel-library laravel-package laravel10 laravel11 laravel8 laravel9 orderby php8 php84 sortable sortable-list sorting sorting-library sorting-list

Last synced: 12 days ago
JSON representation

Larasort : Column sorting with Laravel - Eloquent sortable

Awesome Lists containing this project

README

        





# Column Sorting for Laravel - Sortable - Sort By

[![Tests](https://github.com/s-damian/larasort/actions/workflows/tests.yml/badge.svg)](https://github.com/s-damian/larasort/actions/workflows/tests.yml)
[![Static analysis](https://github.com/s-damian/larasort/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/s-damian/larasort/actions/workflows/static-analysis.yml)
[![Total Downloads](https://poser.pugx.org/s-damian/larasort/downloads)](https://packagist.org/packages/s-damian/larasort)
[![Latest Stable Version](https://poser.pugx.org/s-damian/larasort/v/stable)](https://packagist.org/packages/s-damian/larasort)
[![License](https://poser.pugx.org/s-damian/larasort/license)](https://packagist.org/packages/s-damian/larasort)

## Larasort : Column Sorting For Laravel - Sort Easily

### Introduction - Larasort

This package allows you to automate the `ORDER BY` of your SQL queries, as well as to automate the generation of sortable links.

This Open Source library allows you to create **sortable columns** in an automated way with **Laravel**.

You have two packages in one: **Larasort** (for sorting **with** Eloquent ORM) and **LarasortManual** (for sorting **without** Eloquent ORM).

> Sort easily in an automated way 🚀

### Basic Example

- Example in Model:

```php
private array $sortables = [ // The attributes that are sortable.
'email',
'first_name',
'created_at',
];
```

- Example in Controller:

```php
$customers = Customer::whereNotNull('confirmed_at')
->autosort() // Automate ORDER BY and its direction.
->paginate();
```

- Example in View (in blade template):

```html
@sortableLink('email', 'Email')
```

Example rendering of a link in a table:

[![Larasort](https://raw.githubusercontent.com/s-damian/medias/main/packages/larasort-th-example.webp)](https://github.com/s-damian/larasort)

### Author

This package is developed by [Stephen Damian](https://github.com/s-damian).

### Requirements

- PHP `8.0` || `8.1` || `8.2` || `8.3` || `8.4`
- Laravel `8` || `9` || `10` || `11`

## Summary

- [Installation](#installation)
- [Customization with "vendor:publish"](#customization-with-vendorpublish)
- [Larasort - For Eloquent ORM](#larasort---for-eloquent-orm)
- [Basic usage](#basic-usage)
- [Aliasing](#aliasing)
- [Example with ->join()](#example-with--join)
- [Relationships](#relationships)
- [One To One](#one-to-one)
- [One To Many](#one-to-many)
- [Belongs To](#belongs-to)
- [Relationships - Conventions](#relationships---conventions)
- [For a column, specify its table](#for-a-column-specify-its-table)
- [Put "desc" or "asc" by default for some columns](#put-desc-or-asc-by-default-for-some-columns)
- [Clear Larasort static methods](#clear-larasort-static-methods)
- [Larasort - API Doc](#larasort---api-doc)
- [Model properties](#model-properties)
- [Larasort class](#larasort-class)
- [AutoSortable trait](#autosortable-trait)
- [Blade directives](#blade-directives)
- [LarasortManual - For without Eloquent ORM](#larasortmanual---for-without-eloquent-orm)
- [LarasortManual - Basic usage](#larasortmanual---basic-usage)
- [LarasortManual - For a column, specify its table](#larasortmanual---for-a-column-specify-its-table)
- [LarasortManual - Put "desc" or "asc" by default for some columns](#larasortmanual---put-desc-or-asc-by-default-for-some-columns)
- [LarasortManual - API Doc](#larasortmanual---api-doc)
- [LarasortManual class](#larasortmanual-class)
- [Support](#support)
- [License](#license)

## Installation

Installation via Composer:

```
composer require s-damian/larasort
```

## Customization With "vendor:publish"

### Custom Config and Lang and CSS

After installing the package, you have to run the `vendor:publish` command:

```
php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider"
```

The `vendor:publish` command will generate these files:

- `config/larasort.php`
- `public/vendor/larasort/css/larasort.css` (**you must include this CSS in your website**)
- `public/vendor/larasort/images/order.webp`

You can of course customize these files.

### "vendor:publish" with "--tag" argument

Publish only `config` file:

```
php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=config
```

Publish only `CSS` file:

```
php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=css
```

Publish only `images` file:

```
php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=images
```

# Larasort - For Eloquent ORM

**Larasort** is useful when using the Eloquent ORM.

## Basic Usage

First, your Model must use the `AutoSortable` Trait.

Then it is necessary that in your Model you declare `$sortables`. This property is useful for defining the columns (columns in your DB table) allowed to be sorted in the `ORDER BY`.

Note: the first column of the array `$sortables` will be the column used by default for the SQL `ORDER BY`.

Example:

```php
autosort()` magic method:

```php
autosort() // Automate ORDER BY and its direction.
->paginate();

return view('customer.index', [
'customers' => $customers,
]);
}
}

```

And in the view you can do this in the `thead` of a `table` for example:

Note: You must put the CSS class `with-larasort` on a HTML tag which encloses the blade directive (on the `table` or `thead` tag by example).

```html



@sortableLink('first_name', 'First name')


@sortableLink('email', 'Email')


@sortableLink('created_at', 'Register on')

```

Note: 1st parameter is the `column` in database, 2nd parameter is the `title` (`label`). The 2nd parameter is optional. If you don't specify pass, the label will be generated automatically based on the column name.

If you need to keep more control inside a `th`, for more control you can replace `@sortableLink` by `@sortableHref` and `@sortableIcon`.

Example:

```html


Email
@sortableIcon('email')

```

## Aliasing

If for some columns you do not want to specify the table in prefix, you must use the `$sortablesAs` property.

In a concrete case, aliases are especially useful when you make an SQL query with a join.

### Example with ->join()

- Example in the Customer Model:

```php
join(
'articles',
'customers.id', '=', 'articles.customer_id'
)
->autosort() // Automate ORDER BY and its direction.
->paginate();

return view('customer.index', [
'customers' => $customers,
]);
}
}
```

- Example in View (in blade template):

```html
@sortableLink('article_title', 'Article Title')
```

## Relationships

With **Larasort** you can automate the `ORDER BY` of your relations One To One and One To Many.

To do this, you can use the `autosortWith` method.

### One To One

In this example, a `user` has created one `article`, and an `article` has been created by a single `user`.

This therefore creates a **One To One** relationship between `users` and `articles`.

- Example in User Model:

```php
hasOne(Article::class, 'user_id_created_at', 'id');
}
```

- Example in UserController:

```php
'join', // Optional - "leftJoin" by default.
'columns' => ['id', 'username', 'email', 'role'], // Optional - "*" by default.
'related_columns' => ['title AS article_title', 'h1'], // Optional - "*" by default.
])
->paginate();
```

- Example in View (in blade template):

```html
@sortableLink('article.title', 'Article Title')
```

Note: for the 1st argument of `@sortableLink`, use the same convention as in the `$sortablesRelated` property of the Model.

### One To Many

In this example, a `user` has created multiple `articles`, and an `article` has been created by a single `user`.

This therefore creates a **One To Many** relationship between `users` and `articles` (several articles per user, and only one user per article).

- Example in User Model:

```php
hasMany(Article::class, 'user_id_created_at', 'id');
}
```

- Example in UserController:

```php
'join', // Optional - "leftJoin" by default.
'columns' => ['id', 'username', 'email', 'role'], // Optional - "*" by default.
'related_columns' => ['title AS article_title', 'h1'], // Optional - "*" by default.
])
->paginate();
```

- Example in View (in blade template):

```html
@sortableLink('articles.title', 'Article Title')
```

Note: for the 1st argument of `@sortableLink`, use the same convention as in the `$sortablesRelated` property of the Model.

### Belongs To

Whether for a **One To One** or **One To Many** relationship, you must put the **belongsTo** method in the Article Model.

- Example in Article Model:

```php
belongsTo(User::class, 'user_id_created_at', 'id');
}
```

- Example in ArticleController:

```php
'join', // Optional - "leftJoin" by default.
'columns' => ['id', 'slug', 'h1', 'updated_at'], // Optional - "*" by default.
'related_columns' => ['email AS user_email', 'first_name'], // Optional - "*" by default.
])
->paginate();
```

- Example in View (in blade template):

```html
@sortableLink('user.email', 'User Email')
```

Note: for the 1st argument of `@sortableLink`, use the same convention as in the `$sortablesRelated` property of the Model.

### Relationships - Conventions

#### Model $sortablesRelated property

For the columns you put in the `$sortablesRelated` property, the convention is: `{relationship name}{separator}{column in this relationship table}`.

Larasort will use `{relationship name}` to do the `ORDER BY` on its table.

By default the separator is a period. If you wish, you can change it in the config with `relation_column_separator`.

#### ->autosortWith() method options

To do the join, you must specify the name of the relation in the first parameter of `->autosortWith()`.

Inside, you must pass the name of your relation (the name of the relation method that you put in your Model). Larasort will use this name to do the `join`.

##### Options:

PS:
If at the first parameter of `->autosortWith()` you put a relation name different from what you had put at `{relationship name}` of the property `$sortablesRelated`, the `ORDER BY` simply won't happen on the relationship.

- "`join_type`" (optional):

To make another join than the default (the one specified in the config), you can specify the `join_type` option.

- "`columns`" (optional):

If you want to specify the columns to `SELECT` for your Model, you can specify the `columns` option.

You can put either an array or a string. Example with an array: `['id', 'email', 'username']`. Example with a string: `'id, email, username'`.

By default the `SELECT` will be done on all the columns.

- "`related_columns`" (optional):

If you want to specify which columns to `SELECT` for your Model's relationship, you can specify the `related_columns` option.

You can put either an array or a string. Example with an array: `['title AS article_title', 'content']`. Example with a string: `'title AS article_title, content'`.

By default the `SELECT` will be done on all the columns.

## For a Column, Specify its Table

With **Larasort** you can for columns, specify their table (this is useful when you make a SQL query with join).

By default, Larasort will do the `ORDER BY` on the table where the `AutoSortable` trait is included.

Let's take an example where in an SQL query you want to retrieve articles (from a `articles` table) and categories (from a `categories` table), and that for these 2 tables you want to retrieve the `id` column. But you want to do `ORDER BY id` on the `categories` table instead of the `articles` table.

### You can solve this problem with these 2 solutions

#### Solution 1 - With $sortablesToTables property

The `$sortablesToTables` property can optionally be put in the Model:

```php
'categories.id', // Here.
];
}
```

#### Solution 2 - With Larasort::setSortablesToTables(array $sortablesToTables)

The `Larasort::setSortablesToTables(array $sortablesToTables)` method can optionally be put just before the SQL query where you will use `->autosort()` (in the Controller or in the Model, for example).

Example in a ArticleController:

```php
'categories.id']); // Here.

// Here your SQL query with ->autosort()
// Then the rest of the code...
}
}
```

If the `$sortablesToTables` property and the `Larasort::setSortablesToTables(array $sortablesToTables)` method are used at the same time for the same column, the `Larasort::setSortablesToTables(array $sortablesToTables)` method will override the `$sortablesToTables` property.

Using either of these solutions, the result of the SQL query will be: ```ORDER BY `categories`.`id` ASC``` instead of ```ORDER BY `articles`.`id` ASC ```.

## Put "desc" or "asc" by Default For Some Columns

It is possible for some columns, that the order (the direction of the `ORDER BY`) to want it to be by default (or on the 1st click on its link) at `desc` instead of `asc`.

This can optionally be put just before the SQL query where you will use `->autosort()` (in the Controller or in the Model, for example).

Example in a InvoiceController:

```php
['id', 'created_at', 'price_with_vat'], // Here.
]);

// Here your SQL query with ->autosort()
// Then the rest of the code...
}
}
```

### If you change "default_order" in "config/larasort.php" file - Put "asc" by default for some columns

In the `config/larasort.php` config file, you can change the value of `default_order` (which defaults to `asc`).

If you do this: it is possible for some columns, than the order of wanting it to be at `asc` instead of `desc`.

Example in a InvoiceController:

```php
['customer_email', 'customer_first_name'], // Here.
]);

// Here your SQL query with ->autosort()
// Then the rest of the code...
}
}
```

## Clear Larasort static methods

If you need to, you can clear (reset) the static methods of Larasort:

```php
` |
| string | @sortableLink(string $column, string $label) | Return link of a column = href + label + icon. | `Email` |

# LarasortManual - For Without Eloquent ORM

**Larasort** is useful when you weren't using the Eloquent ORM.

If you want to do a manual SQL query (or if you want to do a file listing), an alternative exists: **LarasortManual**.

## LarasortManual - Basic Usage

With **LarasortManual**, the `setSortables(array $sortables)` method is useful to define the columns allowed to be sorted in the `ORDER BY`.

Simple example:

```php
setSortables(['id', 'first_name', 'email', 'created_at']); // Here.
$resultLarasortMan = $larasortMan->get();

$customers = DB::select('
SELECT *
FROM customers
ORDER BY '.$resultLarasortMan['order_by'].' '.$resultLarasortMan['order'].'
');

return view('customer.index', [
'customers' => $customers,
'larasortManAttrs' => $resultLarasortMan['attrs'],
]);
}
}
```

And in the view you can do this in the `thead` of a `table` for example:

```html




First name
{!! $larasortManAttrs['first_name']['icon'] !!}




Email
{!! $larasortManAttrs['email']['icon'] !!}




Register on
{!! $larasortManAttrs['created_at']['icon'] !!}


Actions

```

Note: if you wish, you can also have access to `$larasortManAttrs['column_name']['url']`.

## LarasortManual - For a Column, Specify its Table

With **LarasortManual** also you can for columns, specify their table (this is useful when you make a SQL query with join).

Unlike **Larasort** which makes the SQL query on the table where the `AutoSortable` trait is included, by default, **LarasortManual** will do the `ORDER BY column` without specifying a table in prefix.

So, when you join multiple tables, if you `SELECT` the same column name on several tables, you can end up with an error like: *"Integrity constraint violation: 1052 Column '{colomn}' in order clause is ambiguous"*.

Let's take an example where in an SQL query you want to retrieve articles (from a `articles` table) and categories (from a `categories` table), and that for these 2 tables you want to retrieve the `id` column. And you want to do `ORDER id` on the `categories` table.

You can use the `$larasortMan->setSortablesToTables(array $sortablesToTables)` method to achieve this.

Example:

```php
setSortables(['id', 'title', 'created_at']);
$larasortMan->setSortablesToTables(['id' => 'categories.id']); // Here.
$resultLarasortMan = $larasortMan->get();

// Here your SQL query with $resultLarasortMan['order_by'] and $resultLarasortMan['order']
// Then the rest of the code...
}
}
```

`$resultLarasortMan['order_by']` will generate the SQL query ```ORDER BY `categories`.`id` ASC``` instead of ```ORDER BY `id` ASC```.

## LarasortManual - Put "desc" or "asc" by Default for Some Columns

With **LarasortManual** also you can for some columns, have the order (the direction of ORDER BY) default (or on the 1st click on its link) to `desc` instead of `asc`.

You can do this with the `$larasortMan->setSortablesDefaultOrder(array $sortablesDefaultOrder)` method.

Example:

```php
setSortables(['id', 'ref', 'customer_email', 'created_at', 'price_with_vat']);
$larasortMan->setSortablesDefaultOrder([
'desc' => ['id', 'created_at', 'price_with_vat'], // Here.
]);
$resultLarasortMan = $larasortMan->get();

// Here your SQL query with $resultLarasortMan['order_by'] and $resultLarasortMan['order']
// Then the rest of the code...
}
}
```

### If you change "default_order" at "config/larasort.php" file - Put "asc" by default for some columns

You can do this in exactly the same way as with Larasort. By doing something like this:

```php
setSortablesDefaultOrder([
'asc' => ['customer_email', 'customer_first_name'], // Here.
]);
```

## LarasortManual - API Doc

### LarasortManual class

For `SDamian\Larasort\Manual\LarasortManual` class:

| Return type | Method | Description |
| ----------- | ------------------------------------------------------ | ----------- |
| void | setSortables(array $sortables) | To specify sortable columns. |
| void | setSortablesToTables(array $sortablesToTables) | For column(s), specify its table. |
| void | setSortablesDefaultOrder(array $sortablesDefaultOrder) | Assign default order ("desc" or "asc") for some columns. |
| array | get() | Return the result of LarasortManual instance. |

## Support

If you discover a **bug** or a **security vulnerability**, please send a message to Stephen. Thank you.

All bugs and all security vulnerabilities will be promptly addressed.

## License

This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.