skobkin/useful-bundle
skobkin/useful-bundle is a Symfony bundle that gathers reusable helpers and utilities for PHP projects. It offers a lightweight way to share common functionality and reduce boilerplate across applications, with simple Composer installation.
First, verify what you are actually installing. This is a Symfony 2 bundle (Bundle subclass, XML/YAML DI config, Symfony Form/Twig/Doctrine extension points), not a Laravel package. There is no service provider, no facade, no config/*.php to publish, and no extra.laravel block. Before any composer command, open composer.json in the repo and read the symfony/*, twig/twig, and doctrine/* constraints — those tell you which framework generation the code targets and whether it can coexist with your tree at all.
Minimal steps for the two realistic scenarios:
composer require skobkin/useful-bundle pinned to a commit, register new Shtumi\UsefulBundle\ShtumiUsefulBundle() in app/AppKernel.php, then php app/console container:debug | grep shtumi to see what services you actually got. First use case: a date-range form field on an admin filter form.composer require. Clone the repo, open src/ and the Resources/config/ service definitions, and read the three families of classes: form types, Doctrine FunctionNode subclasses, Twig extensions. Pick the one capability you need and port it into app/Support/. Composer install into a modern Laravel app will resolve into a deadlock against Symfony 6/7, so don't spend an afternoon discovering that.Where to look first, in order: composer.json (compatibility reality check) → DependencyInjection/ (what is configurable, what service ids exist) → the form types / DQL functions / Twig extensions themselves (the actual value). The DI plumbing is disposable; the algorithms are what you're here for.
Legacy Symfony 2 — container-first usage. The bundle exposes services by id; you inject them rather than instantiating. The pattern is always the same: define the form type as a service argument, tag Twig extensions with twig.extension, and register DQL functions under doctrine.orm.entity_managers.*.dql.DQL or globally via doctrine.orm.dql. Typical day-to-day wiring:
# app/config/config.yml
doctrine:
orm:
dql:
string_functions:
DATE: Shtumi\UsefulBundle\DQL\DateFunction
// controller
$form = $this->createForm(DateRangeType::class, null, [
'field_options' => ['widget' => 'single_text'],
]);
Laravel — port by capability, not by package. Each slice of the bundle lands in a different part of your app, and none of them land as a dependency:
FunctionNode subclasses and register them in your own Doctrine config. Write a test that asserts the generated SQL string — that is the only defense against a silently wrong FunctionNode.FormRequest for validation, with a small Alpine/Livewire wrapper if the widget is interactive. Keep the option-resolution logic (defaults, setDefaultOptions-era behavior) — it is the part people get wrong when hand-rolling.app/Support. Port only the pure string/date functions; discard the Twig_Extension registration boilerplate.Workflow that works. Treat the repo as a spec: (1) inventory every class as reusable logic, framework plumbing, or dead weight; (2) confirm a current feature actually needs it; (3) port the smallest useful unit with tests; (4) keep it in first-party code under your own CI. Time-box the whole thing — for most single helpers this is an hour, not a sprint.
Twig_Extension base classes, Symfony 2 Form getName()/setDefaultOptions() lifecycle (removed in favor of configureOptions() in 2.7+), and older Doctrine FunctionNode constructor signatures. Any file you copy needs a pass for removed functions, deprecated dynamic properties (8.2), and implicit nullable parameters.FunctionNode produces valid-but-incorrect SQL — wrong date bucketing, wrong null handling — that passes code review and shows up as bad reporting data weeks later. Never let a ported DQL function sit in a correctness-critical path without an SQL-string assertion test.config/packages/*.yaml skeleton, no env-var interpolation. Read Configuration.php to see the real keys; don't guess from the README.console container:debug, then container:debug <service_id> to confirm arguments resolved. Most "it's not working" reports are a missing tag (twig.extension) or a service not being public.composer.json in a Laravel app. If you need the behavior, you own the code; there is no maintainer to escalate to and no release cadence to track.How can I help you explore Laravel packages today?