Weave 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

Datasource Bundle Laravel Package

fsi/datasource-bundle

FSi Datasource Bundle integrates the FSi DataSource component with Symfony, providing a reusable abstraction for paginated, filterable, and sortable listings backed by Doctrine or custom sources. Ideal for admin grids, search results, and API collections.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — it ships an Extension/CompilerPass and a Twig extension, so there is no service provider, facade, or config publish step you'd recognise. Treat it as Symfony-only glue around the framework-agnostic fsi/datasource component.

Minimal steps:

composer require fsi/datasource-bundle

Register the bundle the way your Symfony version expects:

// Symfony 3.x / 4.x (AppKernel.php)
$bundles = [ /* ... */ new FSi\Bundle\DataSourceBundle\FSiDataSourceBundle() ];

// Symfony 4.4+/5.x (config/bundles.php)
return [ /* ... */ FSi\Bundle\DataSourceBundle\FSiDataSourceBundle::class => ['all' => true] ];

Where to look first, in this order — the README is thin, so read the code:

  1. DependencyInjection/Configuration.php — the actual config surface (likely a driver key). If it's empty, there's nothing to configure and the bundle is pure wiring.
  2. Resources/config/services.xml (or *.yaml) — the real service IDs; don't guess them, they are the contract you'll inject.
  3. Twig/ — the extension class tells you the exact function names and signatures for rendering a datasource in a template.

First use case: a controller builds a datasource from a QueryBuilder, hands it to Twig, and the template renders it through the bundle's Twig function rather than a hand-rolled foreach.

public function listAction(DataSourceFactory $factory) // fsi_datasource factory service
{
    $datasource = $factory->createDataSource('doctrine', [
        'query'  => $this->getDoctrine()->getRepository(Article::class)->createQueryBuilder('a'),
        'fields' => ['a.title', 'a.createdAt'],
    ]);

    return $this->render('articles/list.html.twig', ['datasource' => $datasource]);
}

Then in the template, use whichever helper the extension registers (commonly datasource_render / fsi_datasource_render — confirm with bin/console debug:twig | grep -i datasource).

Expect roughly 20 minutes to first render if the bundle is Symfony-3/4-era compatible with your app; expect an afternoon if you're on Symfony 6 and need to shim the bundle registration.

Implementation Patterns

Custom datasource classes. The bundle's value is registration, not implementation — your real work is writing datasources. Subclass the component's abstract base (or implement DataSourceInterface) and implement getData() to translate the current filter/sort/page state into your query. If the bundle exposes a tag for datasources, register with it; otherwise instantiate explicitly through the factory.

Prefer the factory over new. A datasource is stateful per request (filters, pagination, sorting). The factory service exists so you get a fresh instance and so driver/type selection stays centralised. Never inject a constructed datasource as a singleton — you'll leak state between requests in long-running workers and between two usages on the same page.

Doctrine pattern. Wrap a QueryBuilder and let the datasource own the where/orderBy/setMaxResults mutation from its own state. Keep the repository query builder untouched until the datasource runs — clone it if the same builder is reused elsewhere in the request.

Twig-first rendering. The bundle's headline feature is that a datasource is renderable. Structure your templates so the datasource is passed in and the bundle function handles the loop, and keep the per-row markup in a small partial so the same datasource can render in a table view and a card view.

{# list.html.twig #}
{{ datasource_render(datasource, 'articles/_row.html.twig') }}

Events as the extension seam. The component fires pre/post data-retrieval events. Use a subscriber to add cross-cutting behaviour — caching, logging of query counts, injecting an owner/tenant filter — instead of editing each datasource:

public function preGetData(DataSourceEvent $event): void
{
    $event->getDataSource()->setData(/* transformed */);
}

Be careful to guard against re-entrancy if your subscriber calls getData().

Keep controllers thin, put assembly in a service. A DataSourceProvider-style service per screen keeps the createDataSource(...) array config testable and lets you reuse the same datasource across a controller action, an API response, and an export command.

Gotchas and Tips

Maintenance risk is the headline. Last release September 2021, 5 stars, zero dependents. Treat it as unmaintained: pin the exact version in composer.json, commit composer.lock, and budget for a fork. The good news is that it's a thin bundle — everything of substance lives in fsi/datasource, so replacing the bundle with ~50 lines of your own services.yaml plus a Twig extension is a realistic escape hatch if you hit a Symfony incompatibility.

Symfony version mismatch is the likely blocker. A 2021 bundle will target Symfony 3/4/5. On Symfony 6+ you'll hit deprecated bundle base classes and possibly ContainerAware usage. The underlying component may still work; the wiring may not. Verify before promising a timeline.

Service IDs are undocumented. Run bin/console debug:container --show-private | grep -i datasource and bin/console debug:twig first — the README doesn't enumerate them and guessing produces confusing "cannot autowire" errors.

Twig extension not loaded. If the function is undefined, debug:twig will show it. If it's absent entirely, the bundle isn't registered for the current environment (config/bundles.php ['all' => true] vs a dev-only key).

Statefulness bugs look like data bugs. Symptoms: pagination page 2 shows page 1's rows, two datasources on one page interfere, filters bleed across a sub-request. Root cause is almost always a shared instance — inject the factory, not the datasource.

Repeated getData() calls mean repeated queries. Events fire each time. Cache the result on the datasource or memoize in your subscriber.

Debugging: bin/console debug:container, bin/console debug:twig, and the Symfony profiler's Doctrine panel (if Doctrine-backed) are where you'll spend your time. There's no logging inside the bundle.

Extension points, in order of usefulness: (1) custom datasource classes, (2) event subscribers on retrieval, (3) decorating the factory service to inject your own defaults, (4) your own Twig function in a separate extension if the bundle's renderer doesn't fit your markup. Forking the bundle itself should be last — the surface is small enough that owning it directly is often cheaper than fighting it.

If you're genuinely on Laravel: skip this bundle. Use fsi/datasource directly, bind the factory as a singleton in a service provider, and expose a Blade directive or a small @datasource($datasource, 'partial') wrapper around view(). You lose Symfony DI conventions, which is most of what this bundle provides.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib