rz/field-type-bundle
rz/field-type-bundle is a PHP package for organizing reusable field type definitions in your applications. It helps centralize field metadata and rendering logic so forms and content models stay consistent, easier to maintain, and simpler to extend as your project grows.
Reality check first. This bundle is archived, has no dependents, and targets Symfony 2.x. Before writing any code, confirm it actually installs against your stack:
composer require rz/field-type-bundle
Expect peer-dependency friction on anything newer than Symfony 2.8/3.x and PHP 7.x. If Composer refuses, you'll need --ignore-platform-reqs or a repositories fork entry — treat either as a signal you're adopting abandoned code.
Where to look first, in this order:
Rz/FieldTypeBundle/RzFieldTypeBundle.php — the bundle class. Note whether it registers compiler passes; that's where the extension mechanism lives.DependencyInjection/RzFieldTypeExtension.php and DependencyInjection/CompilerPass/* — the tag name it collects (something like rz.field_type) and the registry service it builds.Resources/config/services.yml — the public service IDs you'll actually reference (the registry/manager, the form type, any Twig extension).FieldType interface or abstract class — the contract you implement to add a new type.Resources/views/ — template naming conventions, since field types almost always ship a render template.Register the bundle in app/AppKernel.php:
$bundles = [
// ...
new Rz\FieldTypeBundle\RzFieldTypeBundle(),
];
First use case — render one field of a known type. The shortest path to "it works" is: pick a built-in field type, get its service from the container, and render it once in a template. That exercises the registry, the tag-collection compiler pass, and the Twig layer in a single step. Only after that works should you try defining your own type or wiring it into a form.
If there's a README example, follow it literally once before adapting. With 0 stars and no dependents, the README is the only spec you have, and it may not match the code.
Tagged-service registration. This is the dominant Symfony 2 pattern for this kind of bundle and almost certainly what's here: you write a class implementing the bundle's field-type interface, register it as a service, and tag it. The compiler pass folds all tagged services into a registry keyed by an alias.
services:
app.field_type.currency:
class: AppBundle\FieldType\CurrencyType
tags:
- { name: rz.field_type, alias: currency }
Verify the exact tag name and attribute key against the compiler pass source — this is the single most common place to get it wrong.
Pair each field type with a form type. The practical shape of these bundles is: a field type declares (a) a key, (b) a Symfony form type used to edit values, (c) optionally a Doctrine type or serializer for storage, and (d) a Twig template for display. Keep those four concerns in one small class plus one template, and let the registry dispatch on the key. Resist putting rendering logic in the field type class.
Configuration-driven field definitions. If the bundle exposes a config.yml tree for registering types, prefer YAML over hardcoding service IDs in templates. It gives you one place to see every available type and makes it trivial to diff changes in review.
Store the type key, not the class name. When persisting an entity that has a dynamic field, save currency plus a JSON blob of options — never the FQCN. Class names change during refactors; keys are a stable contract. Resolve key → service at render time.
Integration with forms. The cleanest workflow is a custom form type that takes a field_type option and delegates buildForm to the resolved field type's form type. Validate the key in configureOptions so a typo fails at form build, not at render.
Wrap the registry. Do not inject the bundle's registry service directly into a dozen classes. Write a thin App\FieldType\Resolver that depends on it and exposes only what you use. When (not if) you replace this bundle, that wrapper is the only file you rewrite.
Testing. These registries are usually plain classes; instantiate one in a unit test and inject mock field types. You do not need a booted kernel to test type resolution — only to test the compiler pass.
The compiler pass runs at container compile time. In prod, adding a new tagged service without cache:clear means the registry silently lacks it. If a type "doesn't exist" in prod but works in dev, this is why.
Debug the tag, not the code. Use php app/console container:debug --tag=rz.field_type (Symfony 2.x syntax) to list what actually got collected. debug:container <service_id> shows the registry's arguments. This answers 80% of "why isn't my type registered" questions in one command.
Symfony 3.4+ removed synchronized services and Symfony 4 removed the AppKernel/bundle-registration model entirely. If you're porting forward, the compiler pass and services YAML survive; the bundle class does not. Plan the port as "copy the two useful classes into your app," not "upgrade the dependency."
Doctrine schema coupling. If a field type maps to a Doctrine column type, changing the type's storage representation requires a migration and a data backfill. The bundle will not detect this for you. Keep the option blob (json/text) separate from any typed column so schema is stable regardless of type churn.
Template resolution is a hidden contract. Most such bundles resolve RzFieldTypeBundle:Field:currency.html.twig by convention. Overriding requires the exact bundle-relative path; a typo yields a confusing "template not found" that names the conventional path, not your override. Check the Twig loader config, not just your template.
Alias collisions are silent. Two services tagged with the same alias typically means last-one-wins, with no error. Add a debug assertion (or a compiler-pass check in your fork) that throws on duplicate aliases — this saves hours on multi-bundle projects.
There is no upstream. No security advisories will be issued, no PHP 8 fixes will land, and no one has reported the bugs you're about to find. Vendor it: fork to your org, commit the source under src/, pin a commit hash, and add a README note explaining provenance and the removal date you're targeting. Do not leave it as a loose composer require against a public abandoned package — that's an unreviewed supply-chain dependency for a zero-value return.
Extension points worth knowing: overriding the registry service via a compiler pass in your own bundle (cleanest), decorating the Twig extension (if rendering is the only thing you need to change), or overriding templates (fastest but least discoverable). Prefer the first; template overrides tend to fossilize.
When to walk away. If the package is fewer than ~500 lines — likely, given 0 stars and a single-purpose name — reimplement it. A tagged-service registry plus a Twig function is perhaps 80 lines. That buys you Symfony-version currency, tests, and an owner who cares, which this package will never provide.
How can I help you explore Laravel packages today?