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

Simple Bus Query Bus Laravel Package

ajgl/simple-bus-query-bus

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • CQRS/Event-Driven Architecture: Enables strict separation of read (queries) and write (commands) operations, reducing side effects and improving scalability. Justifies investment in domain-driven design (DDD) by providing a standardized way to handle queries as first-class citizens.
  • Modular Query Logic: Decouples query handling from controllers/services, allowing for reusable, testable, and maintainable query components. Supports the "fat model, skinny controller" principle by offloading business logic to query handlers.
  • Build vs. Buy Decision: Avoids reinventing a query bus from scratch, reducing technical debt while maintaining flexibility. The MIT license allows for customization if needed, and the package’s extension of SimpleBus ensures compatibility with existing Laravel/PHP ecosystems.
  • Roadmap Priorities:
    • API Layer Refactoring: Replace direct repository calls in controllers with structured query buses (e.g., UserQueryBus->handle(new FindUserById())), improving consistency and reducing boilerplate.
    • Analytics/Reporting: Offload complex read operations (e.g., "sales by region") to dedicated query handlers, enabling easier maintenance and scalability.
    • Microservices Standardization: Standardize query patterns across services for consistency, especially in distributed systems where read operations may span multiple services.
  • Use Cases:
    • Search/Filtering: Replace ad-hoc Eloquent queries (e.g., Model::where()->get()) with structured query objects (e.g., SearchProductsByCriteria), improving readability and reusability.
    • Caching Strategies: Implement caching at the query bus level (via middleware) to reduce database load and improve performance for repeated queries.
    • Audit Logging: Log query execution details (e.g., "User fetched by ID 123") via middleware, enhancing observability and debugging capabilities.
    • Validation: Add query validation logic (e.g., checking for valid search parameters) via middleware before processing, reducing errors in downstream services.

When to Consider This Package

  • Adopt When:
    • Your Laravel/PHP application has complex query logic (e.g., nested filters, joins, or business-logic-heavy reads) that is scattered across controllers or services.
    • You are adopting CQRS or DDD and need a lightweight, standardized way to handle queries as first-class objects.
    • Your team prefers explicit over implicit query design, where queries are defined as objects (e.g., FindActiveUsers) rather than ad-hoc SQL or Eloquent chains.
    • You want to leverage middleware for queries (e.g., caching, logging, validation) without modifying query handlers directly.
    • You are building a microservices architecture and need consistent query patterns across services.
  • Look Elsewhere If:
    • Your queries are simple CRUD operations (e.g., User::find($id)), where the overhead of a query bus is not justified.
    • You rely heavily on Eloquent’s dynamic query builder (e.g., whereHas, with) and need flexible, dynamic SQL generation. Consider Laravel’s built-in query scopes or packages like spatie/laravel-query-builder.
    • Your team lacks experience with PHP/DDD patterns, as this package requires understanding of message handlers, resolvers, and middleware.
    • You need real-time or asynchronous query results (e.g., WebSocket updates). This package is synchronous and not designed for async workflows.
    • Performance is critical for high-throughput queries. Benchmark against direct repository calls or Eloquent queries first, as the query bus may introduce slight overhead.

How to Pitch It (Stakeholders)

For Executives:

*"This package transforms how we handle database queries—turning them into reusable, structured components that behave like API calls. Instead of writing ad-hoc SQL or Eloquent queries in every controller, we’ll define queries as objects (e.g., FindUserByEmail) and let a dedicated query bus handle them. This approach reduces bugs, speeds up development, and makes it easier to add features like caching or analytics later.

Why it matters:

  • Faster Development: Queries become reusable components, like functions but with middleware support for caching, logging, or validation.
  • Lower Maintenance: Changes to query logic (e.g., adding a new filter) only need to be updated in one place.
  • Scalability: Middleware enables features like caching or rate-limiting without touching query handlers, making the system more robust as we grow.

Example: Instead of writing User::where('email', $email)->first() in 10 different places, we define a FindUserByEmail query once and reuse it everywhere. This also makes it easier to add features like caching or audit logs later.

ROI: Reduced technical debt, faster feature delivery, and a more maintainable codebase—especially as our application scales."*


For Engineering:

*"This package extends SimpleBus to support synchronous query buses, filling a gap in Laravel’s ecosystem for structured query handling. Here’s why it’s a strong fit for our stack:

Key Benefits:

  • Decoupled Query Logic: Move query handling out of controllers/services into dedicated handlers (e.g., FindUserByEmailHandler), reducing fat controllers and improving testability.
  • Middleware Support: Add cross-cutting concerns (caching, logging, validation) via middleware without modifying query handlers. For example:
    $queryBus->appendMiddleware(new CacheQueryResultMiddleware());
    
  • Lazy Loading: Only instantiate handlers for queries that are actually used, reducing memory overhead.
  • Testability: Mock the query bus to isolate query logic from dependencies, making unit tests cleaner and more reliable.

Trade-offs:

  • Learning Curve: Requires understanding of message buses and resolvers, but the documentation is clear, and the package is well-structured.
  • Synchronous Only: Not suitable for async workflows (use Laravel Queues or a command bus for those).
  • Small Community: Only 5 stars, but the MIT license means we can fork or maintain it if needed.

Proposal:

  1. Pilot Phase: Implement 2–3 complex queries (e.g., dashboard metrics, search) to validate the approach.
  2. Standardization: Enforce query objects for all new read operations to ensure consistency.
  3. Integration: Add middleware for caching (e.g., Redis) and logging to demonstrate value early.

Alternatives Considered:

  • Roll Our Own: Would take 2–3 dev days; this package gives us that functionality for free.
  • Laravel’s Built-in: No query bus support; would require custom middleware.
  • Other Packages: None combine SimpleBus’s maturity with query-specific features like this one.

Next Steps:

  • Spike: Implement a single query (e.g., GetUserOrders) with this package and compare performance to direct Eloquent calls.
  • Align with DDD/CQRS roadmap if applicable.
  • Prototype middleware for caching or logging to showcase immediate benefits."*

For Developers:

*"This package lets you treat queries like commands—structured, reusable, and decoupled from your controllers. Here’s how it works in practice:

Before (Ad-hoc Queries):

// Controller
public function show(User $user) {
    $orders = Order::where('user_id', $user->id)
                  ->where('status', 'completed')
                  ->with('items')
                  ->get();
    return view('orders', compact('orders'));
}

After (Query Bus):

// Query Object
class FindCompletedUserOrders {
    public function __construct(public User $user) {}
}

// Handler
class FindCompletedUserOrdersHandler {
    public function handle(FindCompletedUserOrders $query) {
        return Order::where('user_id', $query->user->id)
                   ->where('status', 'completed')
                   ->with('items')
                   ->get();
    }
}

// Usage
$queryBus->handle(new FindCompletedUserOrders($user), $orders);

Why This Rocks:

  • No More Fat Controllers: Query logic lives in handlers, not controllers.
  • Reusable Queries: Define FindCompletedUserOrders once and reuse it everywhere.
  • Middleware Power: Add caching, logging, or validation without touching handlers:
    $queryBus->appendMiddleware(new LogQueryExecutionMiddleware());
    
  • Testable: Mock the bus to test handlers in isolation.

Getting Started:

  1. Install the package:
    composer require ajgl/simple-bus-query-bus
    
  2. Set up your query bus (see README).
  3. Start with a simple query and handler, then expand.

Pro Tip: Use this for queries that are used in multiple places or have complex logic. For simple find() calls, Eloquent is still fine!"*

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky