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

Sexy Field Doctrine Laravel Package

tardigrades/sexy-field-doctrine

Doctrine ORM integration for SexyField, letting you map and persist SexyField form fields on Doctrine entities. Provides field types and storage hooks so apps can use SexyField with Doctrine instead of Eloquent, keeping entity metadata and form definitions in sync.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install both halves of the stack. This is an adapter, not a standalone package — it only makes sense alongside sexy-field itself and a working Doctrine setup:

    composer require tardigrades/sexy-field-doctrine dionsnoeijen/sexy-field doctrine/orm
    

    Check composer.json in the repo for the exact doctrine/orm constraint before you commit; on a 0-star package this is the single most likely thing to block you (ORM 2.x vs 3.x removed the annotation driver and reworked proxy generation).

  2. Register the provider. If the package ships Laravel auto-discovery you're done; otherwise add the service provider from src/ to config/app.php. Confirm the provider name by listing the package contents — there is no README worth trusting, so the source is the documentation.

  3. Publish and read the config. Run php artisan vendor:publish and diff the published files against config/ in the package. Expect a config file covering at least: table/entity class names for field definitions and field values, and the field-type registry. This is where you learn the package's vocabulary.

  4. Generate the schema. The package almost certainly ships Doctrine entity mappings rather than Laravel migrations. Use doctrine/migrations (diff then migrate) or SchemaTool in tests to create the field tables. Read the entity classes in src/Entity to see the actual columns before you write any migration by hand.

  5. First use case: attach a seo field group (title, description, og_image) to an existing Page entity. That exercises the whole loop — definition, attach, persist, render — in under an hour, and it's representative of why anyone installs this package.

Implementation Patterns

Define groups centrally, not ad hoc. Field groups and their field types belong in config or a small dedicated service provider, keyed by a stable name (seo, hero, sidebar). Entities then reference the group by key. Keeping definitions out of the entity class means content editors can be given new fields without touching PHP.

Wire the trait onto the entity. Whatever trait or interface the package provides (HasFields-style), add it to the Doctrine entity and make sure the relation to the field-value entity is mapped with cascade: ["persist", "remove"] and, if values are owned exclusively, orphanRemoval: true. Without cascade you'll silently lose values on flush; without orphanRemoval you'll accumulate dead rows every time a field is removed.

Persist through the Unit of Work, not around it. The idiomatic flow is:

$page->setField('seo.title', 'Acme — Industrial Widgets');
$em->persist($page);
$em->flush();

Never call the field-value repository directly to save a value — you'll bypass the owning entity's collection and Doctrine will either duplicate the row or overwrite your change on the next flush. If you must save values standalone (bulk import, console command), load the owning entity through the EntityManager first so it's managed.

Read with a fetch join. Field values are almost always a to-many association. Rendering a listing of 50 pages with {{ $page->field('seo.title') }} in the loop is the classic N+1:

$qb->select('p', 'fv')
   ->from(Page::class, 'p')
   ->leftJoin('p.fieldValues', 'fv')
   ->addSelect('fv');

Querying by field value is a join plus a WHERE on the value entity's name and value columns, or a subquery if you need "has any value matching." Expect to write this DQL yourself — adapters of this kind rarely provide a query builder, and even when they do it won't cover multi-field predicates.

Form binding. Map submitted arrays onto fields with a single loop over the group's definitions. Validate against the field-type registry (an image field needs a file path, a text field a max length) rather than against the raw request. This is the extension point worth writing once and reusing across every entity type.

Multi-entity reuse. The real payoff is one seo group shared by Page, Post, and Product. Design the field tables to be polymorphic-ish from day one (owner type + owner id) rather than adding a new join table per entity — otherwise you'll be writing migrations every sprint instead of content.

Gotchas and Tips

  • Zero stars, zero dependents, no issues to search. Treat every method signature as unverified. Pin the exact commit in composer.json ("tardigrades/sexy-field-doctrine": "dev-master#abc1234") so an upstream force-push doesn't break your build, and vendor-copy the package into your own namespace if it becomes load-bearing. Budget for maintaining it yourself; there is no one to file a bug with.

  • Table-name collisions with the Eloquent sexy-field migrations. If any part of the app is still Eloquent and running the original package's migrations, both will try to own fields / field_values. Explicitly set table names in the Doctrine mapping and in the config, and verify with doctrine:schema:validate before deploying.

  • Identity map surprises. After flush(), the in-memory entity is authoritative — a raw SQL update or a second EntityManager (e.g. in a queued job) will leave you reading stale values. If a command mutates fields in bulk, $em->clear() between batches and re-fetch.

  • Lazy-loading proxies on serialized output. Serializing an entity to JSON (API resource, cache payload) can trigger a lazy load of the field collection or throw on an uninitialized proxy after clear(). Decide explicitly whether fields are in the serialized representation and use a DTO or ->initializeObject() rather than hoping.

  • Field-type extension is the main extension point. Register a custom type (e.g. color, relation) in the type registry and implement whatever render/validate/normalize contract the package defines — read an existing type in src/ and copy its shape exactly. Don't patch the vendor directory.

  • Cache config in production but not during discovery. php artisan config:cache will freeze the field-group definitions, which is correct for prod and maddening while you're adding fields locally. Clear it after every definition change.

  • Tests: use an in-memory SQLite database plus Doctrine's SchemaTool to build the schema from mappings, then assert round-tripping (persist → flush → clear → find) rather than asserting on internal state. This catches the cascade and orphanRemoval mistakes early, which are the failure modes you'll actually hit.

  • Watch the ORM major version. If the package predates doctrine/orm 3.x, its mapping driver and proxy configuration may simply not load. Verify with a throwaway entity and a SchemaTool run before wiring it into your domain model — finding out at deploy time is much worse.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings