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

Data Sourcery Bundle Laravel Package

netdudes/data-sourcery-bundle

A Symfony bundle that integrates Netdudes DataSourcery, helping you define, configure, and reuse data sources in your application. It provides bundle-level service wiring and integration helpers, plus a cleaner way to connect domain data to Symfony services with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is not a Laravel package. netdudes/data-sourcery-bundle is a Symfony bundle (it registers via Kernel::registerBundles(), ships a DependencyInjection/*Extension and Configuration tree, and relies on tagged services and compiler passes). Laravel has no bundle loader — its extension point is a Service Provider. So "getting started" here means reading it, not installing it. Do not run composer require netdudes/data-sourcery-bundle in a Laravel app; expect either a resolution failure (an archived Symfony 2/3-era bundle won't satisfy modern symfony/http-kernel/framework-bundle constraints) or an inert dependency.

30–60 minute source audit — where to look first, in order:

  1. composer.json — the PHP and symfony/* constraints. This tells you instantly whether it is installable at all, and roughly which Symfony era the code targets. Also check whether there is a separate non-bundle core (netdudes/data-sourcery) that the bundle merely wraps; if so, the agnostic surface is larger and the bundle wrapper can be discarded entirely.
  2. DependencyInjection/ — the *Extension and Configuration classes. This is the product specification: it enumerates the config keys (source names, reader types, connection strings, processor wiring) and therefore the whole feature set in a few dozen lines.
  3. The service definition file (Resources/config/services.yml or .xml) — shows what objects exist, what is tagged, and what is injected into what. This is your map of the object graph.
  4. The plain-PHP classes (readers, sources, processors) — separate what is framework-coupled (anything taking ContainerInterface, EntityManager, EventDispatcherInterface) from what is domain logic. The domain logic is the only part worth reusing.
  5. There is no README of substance and no tests — assume nothing works until you run it. Treat every behavior claim you infer as a hypothesis.

Your first real use case, in a Laravel app: don't integrate the bundle. Run the audit, write a one-page note saying "here is the abstraction shape: sources are registered by name, each has a reader, readers emit normalized rows, processors transform them," and then implement that shape natively behind your own DataSource contract. Budget a day. The bundle is prior art for a design, not a dependency — 2 stars, 0 dependents, archived, no maintainer.

If you genuinely have a narrow need the code solves and you accept the maintenance, the only sanctioned path is: fork it under the MIT license, vendor it into your repo (private VCS or app/Support/), and name an owner. Never depend on the public Packagist artifact of an archived repo.

Implementation Patterns

These are the patterns to lift from the source and re-express in Laravel idioms. They are the reason to read the bundle at all.

1. Named source registry, resolved from config. The bundle's core idea — a set of named data sources declared in configuration and resolved from the container — maps cleanly onto Laravel. Instead of a DI extension + Configuration tree, use a config file plus a small factory:

// config/data-sources.php
return [
    'default' => 'customers',
    'sources' => [
        'customers' => [
            'reader'    => \App\DataSources\Readers\CsvReader::class,
            'options'   => ['path' => storage_path('imports/customers.csv'), 'delimiter' => ','],
            'processors'=> [\App\DataSources\Processors\TrimStrings::class],
        ],
    ],
];
// app/DataSources/DataSourceManager.php
class DataSourceManager
{
    public function __construct(private array $config, private Container $app) {}

    public function source(?string $name = null): DataSource
    {
        $name ??= $this->config['default'];
        $def   = $this->config['sources'][$name] ?? throw new InvalidArgumentException("Unknown source: {$name}");

        $reader = $this->app->make($def['reader']); // resolve via container so deps inject
        return new DataSource($reader, $this->resolveProcessors($def['processors'] ?? []));
    }

    private function resolveProcessors(array $classes): array
    {
        return array_map(fn ($c) => $this->app->make($c), $classes);
    }
}

Bind it as a singleton and expose it via a facade only if you must — constructor injection is preferable. This reproduces the bundle's "configurable data source definitions via bundle configuration" without any Symfony machinery.

2. A thin DataSource contract you own. This is the highest-leverage decision in the entire assessment. Define your own interface so the borrowed code never appears in more than one adapter file:

interface Reader
{
    /** @return iterable<array<string, mixed>> */
    public function read(): iterable;
}

interface Processor
{
    public function process(array $row): array;
}

final class DataSource
{
    public function __construct(private Reader $reader, private array $processors = []) {}

    public function rows(): iterable
    {
        foreach ($this->reader->read() as $row) {
            foreach ($this->processors as $p) {
                $row = $p->process($row);
            }
            yield $row;
        }
    }
}

Everything else — CSV parsing, header normalization, type coercion — hangs off this. When the fork rots, this is the only file that changes.

3. Streaming, not materializing. The bundle's readers are the reusable bit; copy the approach, not necessarily the code. Emit rows lazily (yield) so a 500k-row CSV doesn't sit in memory. league/csv is a maintained, drop-in replacement for any hand-rolled reader in the bundle and is what you should actually reach for.

4. Processors as a composable pipeline. Mirror the bundle's reader → processor chain, but keep processors single-purpose and idempotent (TrimStrings, CastDecimals, MapColumns, ValidateRequired). Ordering is explicit in config. This is where the bundle's extension point ("extensible architecture for custom readers and processors") actually pays off — you get the same pluggability with ten lines of container wiring.

5. Import workflow integration. Day-to-day, a data import is a queued job, not a request. Wrap the pipeline:

final class ImportFromSource implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function __construct(public string $source, public int $chunk = 500) {}

    public function handle(DataSourceManager $sources): void
    {
        foreach (array_chunk(iterator_to_array($sources->source($this->source)->rows()), $this->chunk) as $chunk) {
            DB::transaction(fn () => Customer::upsert($chunk, ['external_id'], ['name', 'email']));
        }
    }
}

Chunked upsert inside a transaction is the pattern you'd hand-roll; the bundle gives you no queueing story (it predates Laravel's), so this is Laravel-native regardless.

6. If you must run the original code (legacy Symfony context only). Keep it behind an interface and an adapter at the boundary. If the code is Doctrine-coupled, that boundary is where you'd also have to bridge Doctrine entity metadata to Eloquent — which is a rewrite of the persistence layer, not a wrapper. In practice: don't. Reimplement the ~few hundred lines it almost certainly amounts to.

Gotchas and Tips

  • Composer will likely refuse to install it. The archived bundle pins EOL symfony/framework-bundle/http-kernel constraints. Run composer why-not netdudes/data-sourcery-bundle against a modern Laravel skeleton and treat the output as the go/no-go answer. If it resolves, it will drag you toward an unsupported PHP version.

  • Bundle semantics don't survive the port. Tagged services, compiler passes, and EventDispatcher priority ordering have no Laravel equivalent. Anything the bundle does via tagging becomes explicit config arrays; anything it does via events becomes dispatched jobs or explicit calls. Configuration %parameter% interpolation must be flattened into plain PHP arrays — Laravel's config merge is shallow and won't replicate Symfony's behavior.

  • Doctrine-vs-Eloquent is the sharpest edge. If the bundle's pipeline touches EntityManager, transaction boundaries, or entity identity, adapting to Eloquent is a rewrite. Watch for silent behavioral drift — duplicate or dropped records where the package's identity assumptions no longer hold — which surfaces as bad data, not exceptions.

  • Assume it materializes full result sets until proven otherwise. Pipeline-style abstractions frequently ->fetchAll() internally. Load-test with realistic row counts before pointing it at a large table; this is the most likely production failure mode.

  • No security path, so register the fork in your SBOM. Archived + 0 dependents means no CVE monitoring, no transitive-dependency patches, no ecosystem fork to free-ride. Add the vendored copy to dependency review explicitly, preserve the MIT license and attribution, and record provenance in the file header.

  • Absence of tests is the real documentation gap. Onboarding cost is 2–5 days of code archaeology (double it if Doctrine is involved and the team is Eloquent-native). Mitigate with a short ADR: what the abstraction does, what you kept, what you replaced, who owns it. If the one engineer who read the source leaves, that ADR is the only thing standing between you and re-deriving the design.

  • Extension points worth keeping: reader registration by name and the processor chain. Everything else — the DI extension, the config tree, the event wiring — is Symfony-specific ceremony you should delete rather than port.

  • Sanity-check the framework mismatch yourself. The -bundle suffix and netdudes namespace are strong signals but not proof. Confirm from composer.json (symfony/framework-bundle, type: symfony-bundle) and the presence of DependencyInjection/ before spending time on any integration design.

  • When in doubt, look at maintained alternatives before copying anything. Laravel-native: Eloquent/query builder, league/csv for tabular reads, PhpSpreadsheet for spreadsheets, Laravel Excel for the import workflow, queued jobs for orchestration. The bundle's contribution is the interface shape — named sources, pluggable readers, composable processors — and that is worth an hour, not a dependency.

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.
frankyso/ipaymu
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