resomedia/useful-bundle
A Symfony bundle that collects assorted reusable utilities and helper services in one place, helping ResoMedia projects avoid rewriting the same common code. Install it to share everyday tools and convenience services across your applications instead of duplicating them in every app.
First thing to internalize: this is a Symfony 2 bundle, not a Laravel package. The repo is Arachnias/ShtumiUsefulBundle, published on Composer as resomedia/useful-bundle. There is no service provider, no facade, no config/*.php. In a Laravel or modern Symfony (4/5/6/7) app it will not integrate — do not composer require it there. Its only realistic day-to-day home is a legacy Symfony 2.7/2.8 application you actively maintain.
Minimal path to first use on that legacy app:
composer show resomedia/useful-bundle or read the repo's composer.json. Do not use dev-master — the package is unmaintained and dev-master will drift under you. Pin an exact tag or commit hash.DQL/ — custom Doctrine DQL functions (MySQL FIELD, FIND_IN_SET, date/string helpers)Form/Type/ — autocomplete, dependent-select, datepicker form typesTwig/ — Twig extension classesResources/config/services.yml — what the DI extension wires for you vs. what you must register yourselfapp/AppKernel.php:
new Shtumi\UsefulBundle\ShtumiUsefulBundle(),
php app/console cache:clear and php app/console doctrine:cache:clear-metadata.First use case — DQL functions. They are the least invasive, highest-value part of the bundle and require the least ceremony. Register one in app/config/config.yml:
doctrine:
orm:
dql:
string_functions:
FIELD: Shtumi\UsefulBundle\DQL\FieldFunction
Then in a repository:
$qb->addSelect('FIELD(e.status, :order) AS HIDDEN sortOrder')
->setParameter('order', 'new,pending,done')
->orderBy('sortOrder', 'ASC');
If that single use case works end-to-end, you have extracted most of the day-to-day value the bundle offers. Everything else is commodity code you can lift class-by-class.
Cherry-pick classes instead of depending on the whole bundle. The bundle is explicitly a grab-bag (etc... in the description is doing real work). The durable pattern is to copy the two or three classes you actually need into your own AppBundle, delete the Composer dependency, and eliminate an unmaintained package from your lockfile. A DQL function is roughly 30 lines with no dependencies; a small Twig extension is similar. Copying is cheaper long-term than inheriting an abandoned constraint.
Registering DQL functions is explicit, not automatic. The bundle does not auto-register its DQL functions. You add each one under doctrine.orm.dql (string_functions, numeric_functions, or datetime_functions) yourself. Keep that registration in one app/config/config.yml block so the full inventory is visible in one place — it doubles as your migration checklist.
Custom form types — wire through FormExtension or the form service. Symfony 2 form types in the bundle need to be reachable from your container. Either tag them (form.type) or reference them by service id in FormBuilder::addType(...). For autocomplete/dependent-select types, expect to supply jQuery-UI- or Select2-era JavaScript on the Twig side — the bundle predates stimulus and Symfony UX. Treat the JS as part of the integration work, not a detail.
Twig extensions — enable per template, not globally, if you can. Register the extension as a tagged twig.extension in your services.yml. If you only need it in a few templates, consider whether a plain Twig function/filter defined locally is simpler — you avoid inheriting the extension's minor-version coupling to your Twig version.
Dependency isolation when vendoring. When you copy a class into your own namespace, also copy its tests (if any exist — likely none) or write a thin characterization test. DQL functions in particular are easy to break silently because they only fail when a query runs at runtime. A one-liner test that builds a query and asserts the generated SQL is worth the hour.
Keep setParameter discipline with DQL functions. Custom DQL functions that accept a "list" argument (e.g. FIELD(field, :order) where :order is a comma string) are prone to SQL-injection if you ever build that string from request data. Always pass it as a bound parameter; never concatenate user input into the DQL literal.
Integration tip — inventory first, adopt second. Before writing any wiring, grep your codebase and config for what you actually use: which form types are referenced, which DQL functions are registered, which Twig extensions are enabled. Most "useful bundle" adoptions hinge on one helper out of twenty. Adopt only that helper.
Framework version ceiling. The bundle targets symfony/symfony ~2.x and PHP 5.x-era language features. Your Symfony, Doctrine, and Twig minor versions must stay compatible; an upgrade to Symfony 3+, Doctrine 2.5+ with a changed DQL API, or Twig 2/3 will break it with no upstream fix. Pin both the bundle and your Symfony minor if this matters.
Zero ecosystem = zero safety net. Zero stars, zero dependents, no CI, no tests, no changelog, no issue triage. Anything you adopt becomes your code on day one. Budget for internal ownership: a named maintainer, a fork in your VCS, a pinned version, and a test suite around what you use. If you cannot commit to that, extract only the raw class you need and drop the dependency.
DQL function name collisions. DQL functions register into a single global name registry. If your application or another bundle already defines FIELD, FIND_IN_SET, or a similarly generic helper, registration order determines which one wins — and the failure is subtle (wrong results, not exceptions). Prefix your own copies (APP_FIELD) when you vendor them.
MySQL-specific DQL functions are not portable. Functions like FIELD and FIND_IN_SET are MySQL dialect. If your Doctrine connection might ever point at Postgres or SQLite, these will fail at query time. Audit before relying on them; if portability matters, avoid the DB-side helper entirely and sort in PHP or use a CASE expression.
Twig extension signatures may not match your Twig version. Twig 2/3 changed ExtensionInterface and TwigFunction registration significantly. If your app is on a later Twig 1.x, it may work; on Twig 2+ it will need rewriting. Check the Twig\Extension\AbstractExtension (or older \Twig_Extension) base class the files extend before assuming compatibility.
Cache and metadata are the usual suspects. If a DQL function "is not recognized", the cause is almost always a stale Doctrine metadata cache or a missing doctrine.orm.dql entry — not a bug in the function. Clear both caches after any change to config.yml.
Autoload / namespace collisions when vendoring. If you copy classes into your app namespace while the composer package is still installed, both can be autoloaded. Remove the upstream package from composer.json in the same commit you vendor the code, or you will get "class not found" or, worse, "class already defined" unpredictably.
No documentation — read the tests, or write them. Since there is no usage guide, the most reliable way to learn a helper's contract is to write a small characterization test against it. This simultaneously documents the behavior and guards against future Symfony/Doctrine upgrades that quietly change it.
Extension points. The bundle is a grab-bag, so "extension" means subclassing or copying a specific form type, DQL function, or Twig extension. When you subclass, register the subclass service explicitly; do not rely on the bundle's services.yml to pick it up automatically. And record the decision in your migration backlog — the bundle is framework coupling to unwind, not a dependency to add.
How can I help you explore Laravel packages today?