Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Orderly Laravel Package

baril/orderly

Add sortable, orderable behavior to Laravel Eloquent models. Store a position column (default: position), use the Orderable trait, and move records with helpers like moveToOffset() and moveToStart(). Supports Laravel 6–12 with version mapping.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require baril/orderly
    

    Register the service provider in config/app.php (if not using discovery):

    'providers' => [
        Baril\Orderly\OrderlyServiceProvider::class,
    ],
    
  2. Database Migration: Add a position column (or custom name) to your table:

    Schema::table('articles', function (Blueprint $table) {
        $table->unsignedInteger('position');
    });
    
  3. Model Integration: Use the Orderable trait and guard the position column:

    class Article extends Model {
        use \Baril\Orderly\Concerns\Orderable;
        protected $guarded = ['position'];
    }
    
  4. First Use Case: Fetch ordered models:

    $articles = Article::ordered()->get();
    

Implementation Patterns

Core Workflows

  1. Single Model Reordering:

    $article = Article::find(1);
    $article->moveUp(); // Moves up by 1 position
    $article->moveToPosition(5); // Sets explicit position
    
  2. Grouped Ordering (e.g., by section_id):

    class Article extends Model {
        use \Baril\Orderly\Concerns\Orderable;
        protected $groupColumn = 'section_id';
    }
    
  3. Many-to-Many Relationships:

    class Post extends Model {
        use \Baril\Orderly\Concerns\HasOrderableRelationships;
        public function tags() {
            return $this->belongsToManyOrderable(Tag::class);
        }
    }
    

    Reorder tags:

    $post->tags()->setOrder([1, 3, 2]);
    
  4. Mass Reordering:

    $articles = Article::all()->sortBy('title');
    $articles->saveOrder(); // Persists new order
    

Integration Tips

  • API Endpoints: Use moveToOffset() for drag-and-drop UIs (e.g., Vue/Draggable.js):
    $article->moveToOffset($newIndex);
    
  • Admin Panels: Combine with previous()/next() for navigation:
    $article->next()->first(); // Get next article
    
  • Caching: Cache ordered collections (e.g., Article::ordered()->get()) to reduce DB load.

Gotchas and Tips

Pitfalls

  1. Database Locking:

    • Concurrent move* operations may cause race conditions. Use transactions:
      DB::transaction(function () use ($model) {
          $model->moveUp();
      });
      
  2. Grouped Ordering Quirks:

    • Forgetting $groupColumn causes global ordering instead of per-group.
    • Ensure groupColumn values are consistent (e.g., section_id exists).
  3. Many-to-Many Pitfalls:

    • setOrder() only reorders models within the collection. Exclude unrelated models:
      $post->tags()->whereIn('id', [1, 2, 3])->setOrder([3, 1, 2]);
      
    • Detaching models after reordering avoids position gaps.
  4. Performance:

    • Avoid move* in loops (e.g., foreach ($models) { $model->moveUp(); }). Use saveOrder() instead.

Debugging

  • Position Gaps: Run the Artisan command to fix:
    php artisan orderly:fix-positions App\Article
    
  • Unexpected Order: Check for:
    • Missing $groupColumn in grouped models.
    • Overridden position column values (guarded by default).
    • Custom scopes interfering with ordered().

Extension Points

  1. Custom Order Logic: Override getOrderColumn() in your model:

    protected function getOrderColumn(): string {
        return 'custom_order_field';
    }
    
  2. Query Scopes: Extend the ordered() scope for complex logic:

    public function scopePublishedOrdered($query) {
        return $query->where('published', true)->ordered();
    }
    
  3. Event Hooks: Listen for orderly.saving to validate positions:

    Event::listen('orderly.saving', function ($model) {
        if ($model->position < 0) {
            throw new \Exception('Invalid position');
        }
    });
    
  4. Database Support: For non-MySQL (e.g., PostgreSQL), ensure position is integer (not bigint if using moveToOffset(-1)).

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity