├── .gitignore ├── src ├── Orderable.php └── OrderingScope.php ├── phpunit.xml ├── composer.json ├── LICENCE.txt ├── readme.md └── tests └── OrderableTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.lock 3 | /.idea -------------------------------------------------------------------------------- /src/Orderable.php: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zigastrgar/orderable", 3 | "type": "laravel-package", 4 | "description": "Ordering package for Laravel 5.x", 5 | "homepage": "https://github.com/ZigaStrgar/orderable", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "ZigaStrgar", 10 | "email": "ziga_strgar@hotmail.com" 11 | } 12 | ], 13 | "minimum-stability": "stable", 14 | "autoload": { 15 | "psr-4": { 16 | "ZigaStrgar\\Orderable\\": "src/" 17 | } 18 | }, 19 | "require": { 20 | "illuminate/support": "^5.3" 21 | }, 22 | "require-dev": { 23 | "phpunit/phpunit": "^5.5", 24 | "illuminate/database": "^5.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Žiga Strgar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Orderable Laravel Package 2 | 3 | This is my very first Laravel package. I find it useful for me :) When I work with projects where I need to run a lot of `ORDER BY` queries. 4 | 5 | ## Instalation 6 | 7 | Add the Orderable package to your `composer.json` file. 8 | 9 | ```json 10 | { 11 | "require": { 12 | "zigastrgar/orderable": "^1.0" 13 | } 14 | } 15 | ``` 16 | 17 | OR 18 | 19 | Simply run this in command line 20 | 21 | ```bash 22 | composer require zigastrgar/orderable 23 | ``` 24 | ## Usage 25 | 26 | Go to any model and add this to the model. 27 | 28 | ```php 29 | use ZigaStrgar\Orderable\Orderable; 30 | 31 | class Article extends Model { 32 | use Orderable; 33 | 34 | public function orderable(){ 35 | return [ 36 | 'id' => 'DESC', 37 | 'title' => 'ASC', 38 | 'user_id' 39 | ]; 40 | } 41 | } 42 | ``` 43 | 44 | If you don't use the key like in `user_id` case it will default to `DESC`. 45 | 46 | ### Running "Orderable" 47 | 48 | It's super simple. 49 | 50 | ```php 51 | Article::all(); 52 | ``` 53 | 54 | #### Apply only specific rule 55 | 56 | From now on, you can also do something like this. 57 | 58 | ```php 59 | Article::order(); //Equals to Article::all(); 60 | ``` 61 | 62 | or 63 | 64 | ```php 65 | Article::order(['title']); 66 | ``` 67 | 68 | and only rule for `title` will bi applied. 69 | 70 | 71 | ### Running without "Orderable" 72 | 73 | Same. Very simple stuff. 74 | ```php 75 | Article::unorderable(); 76 | ``` 77 | 78 | No scopes applied. 79 | 80 | #### Remove specific rule 81 | 82 | ```php 83 | Article::unorderable(['title']); 84 | ``` 85 | 86 | In this case the rule for title won't be applied. 87 | -------------------------------------------------------------------------------- /tests/OrderableTest.php: -------------------------------------------------------------------------------- 1 | truncate(); 9 | 10 | $one = factory(Article::class)->create(); 11 | factory(Article::class)->create(); 12 | factory(Article::class)->create([ 'reads' => 10 ]); 13 | $two = factory(Article::class)->create([ 'reads' => 20 ]); 14 | 15 | $this->assertEquals($one->id, Article::all()->last()->id); 16 | $this->assertEquals($two->id, Article::all()->first()->id); 17 | } 18 | 19 | /** @test */ 20 | function it_tests_the_orderable_call() 21 | { 22 | DB::table('articles')->truncate(); 23 | 24 | $one = factory(Article::class)->create([ 'reads' => 20 ]); 25 | factory(Article::class)->create(); 26 | factory(Article::class)->create([ 'reads' => 10 ]); 27 | $two = factory(Article::class)->create(); 28 | 29 | $this->assertEquals($one->id, Article::order([ 'reads' ])->first()->id); 30 | $this->assertEquals($one->id, Article::order()->first()->id); 31 | $this->assertEquals($two->id, Article::order([ 'id' ])->first()->id); 32 | } 33 | 34 | /** @test */ 35 | function it_test_unorderable_without_args() 36 | { 37 | DB::table('articles')->truncate(); 38 | 39 | $one = factory(Article::class)->create(); 40 | factory(Article::class)->create([ 'reads' => 20 ]); 41 | 42 | $this->assertEquals($one->id, Article::unorderable()->first()->id); 43 | } 44 | 45 | /** @test */ 46 | function it_test_unorderable_with_args() 47 | { 48 | DB::table('articles')->truncate(); 49 | 50 | factory(Article::class)->create(); 51 | $one = factory(Article::class)->create([ 'reads' => 20 ]); 52 | $two = factory(Article::class)->create(); 53 | 54 | $this->assertEquals($one->id, Article::unorderable([ 'id' ])->first()->id); 55 | $this->assertEquals($two->id, Article::unorderable([ 'reads' ])->first()->id); 56 | } 57 | } -------------------------------------------------------------------------------- /src/OrderingScope.php: -------------------------------------------------------------------------------- 1 | getOrderByRules($builder) as $column => $order ) { 30 | if ( !is_int($column) ) { 31 | $builder->orderBy($column, $order); 32 | } else { 33 | $builder->orderBy($order, "DESC"); 34 | } 35 | } 36 | } 37 | 38 | /** 39 | * Extend the query builder with the needed functions. 40 | * 41 | * @param \Illuminate\Database\Eloquent\Builder $builder 42 | * 43 | * @return void 44 | */ 45 | public function extend(Builder $builder) 46 | { 47 | foreach ( $this->extensions as $extension ) { 48 | $this->{"add{$extension}"}($builder); 49 | } 50 | } 51 | 52 | /** 53 | * Get the "order by" rules for the builder. 54 | * 55 | * @param \Illuminate\Database\Eloquent\Builder $builder 56 | * 57 | * @return string 58 | */ 59 | protected function getOrderByRules(Builder $builder) 60 | { 61 | return $builder->getModel()->orderable(); 62 | } 63 | 64 | /** 65 | * Add the order extension to the builder. 66 | * 67 | * @param \Illuminate\Database\Eloquent\Builder $builder 68 | */ 69 | protected function addOrder(Builder $builder) 70 | { 71 | $builder->macro('order', function(Builder $builder, $things = []) { 72 | if ( count($things) == 0 ) { 73 | return $builder->applyScopes(); 74 | } 75 | $builder = $builder->getModel()->newQueryWithoutScopes(); 76 | foreach ( $this->getOrderByRules($builder) as $column => $rule ) { 77 | if ( is_numeric($column) ) { 78 | $column = $rule; 79 | $rule = "DESC"; 80 | } 81 | if ( in_array($column, $things) ) { 82 | $builder->orderBy($column, $rule); 83 | } 84 | } 85 | 86 | return $builder; 87 | }); 88 | } 89 | 90 | /** 91 | * Add the unorderable extension to the builder. 92 | * 93 | * @param \Illuminate\Database\Eloquent\Builder $builder 94 | * 95 | * @internal param array $things 96 | */ 97 | protected function addUnorderable(Builder $builder) 98 | { 99 | $builder->macro('unorderable', function(Builder $builder, $things = []) { 100 | if ( count($things) == 0 ) { 101 | return $builder->withoutGlobalScope($this); 102 | } 103 | $builder = $builder->getModel()->newQueryWithoutScopes(); 104 | foreach ( $this->getOrderByRules($builder) as $column => $rule ) { 105 | if ( is_numeric($column) ) { 106 | $column = $rule; 107 | $rule = "DESC"; 108 | } 109 | if ( in_array($column, $things) ) { 110 | continue; 111 | } 112 | $builder->orderBy($column, $rule); 113 | } 114 | 115 | return $builder; 116 | }); 117 | } 118 | } --------------------------------------------------------------------------------