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

Entity Kit Bundle Laravel Package

rami/entity-kit-bundle

Entity Kit Bundle is a reusable PHP toolkit for entity management, providing base classes, traits, and helpers that reduce boilerplate when defining and working with domain entities. Framework-friendly and easy to integrate into Laravel or Symfony projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: despite the description calling it "modern," this is a Symfony bundle, not a Laravel package. There is no service provider, no config/entity-kit.php, and no Eloquent support. If you are on stock Laravel with Eloquent, stop here — this does not apply. It only makes sense if you are running Doctrine ORM inside a Symfony app (or a Laravel app using laravel-doctrine/orm, in which case you will have to hand-wire the services since the bundle's *Extension class is Symfony DI-specific).

Assuming Doctrine + Symfony:

composer require rami/entity-kit-bundle

Register it (Symfony Flex may do this for you in config/bundles.php):

// config/bundles.php
return [
    // ...
    Rami\EntityKitBundle\EntityKitBundle::class => ['all' => true],
];

Where to look first, in this order:

  1. src/ — the behavior directory. This package's value is the trait/attribute list, so read that before anything else and count what you actually get today versus what the README promises.
  2. The bundle's DI extension and any EventSubscriber/EventListener classes — that tells you when each behavior fires (prePersist, preUpdate, onFlush) and whether it is trait-driven or attribute-driven.
  3. composer.json — check the doctrine/orm and symfony/* constraints against your pinned versions.

First use case (do this as a smoke test, not a commitment): take one throwaway entity and add only the timestamp behavior.

#[ORM\Entity]
class Article
{
    use TimestampableTrait; // createdAt / updatedAt, per the package's trait
}

Then bin/console doctrine:migrations:diff, inspect the generated SQL, and verify that a flush() sets both columns and that a subsequent update touches only updatedAt. If the trait names differ, grep -r "trait " vendor/rami/entity-kit-bundle/src and adapt.

If that works, try the slug behavior on a second entity — that is the first one with real edge cases (uniqueness, regeneration).

Implementation Patterns

Trait-per-behavior, composed on the entity. The intended happy path is one use statement per concern, stacked on the entity. Keep your own base entity or AbstractEntity for ID and domain logic, and treat these traits as leaves:

class Post
{
    use TimestampableTrait;
    use SluggableTrait;   // expects a source property, e.g. $title
    use BlameableTrait;   // createdBy / updatedBy
}

The trap with stacking traits is property collisions. If two traits declare $createdAt or a getSlug(), PHP fatals at class load — resolve with insteadof/as in the entity rather than editing vendor code.

Attribute-driven behaviors where available. The composable-attribute angle is the more interesting half of this package: mark a property or class, let a Doctrine subscriber read the attribute via reflection, and set the value in a lifecycle callback. Prefer attributes for anything you might want to enable per-field or per-entity; prefer traits when you need the getter available on the entity for templates/serializers.

#[Sluggable(source: 'title', regenerate: false)]
private ?string $slug = null;

Wire blameable to your security stack explicitly. Auditing traits need to know who. In Symfony that is a TokenStorageInterface injection into the subscriber; in a Laravel-with-Doctrine setup you would swap that for Auth::user(). Confirm the package ships a sane resolver and that it degrades gracefully to null for CLI/queue contexts — anonymous console commands and workers are where blameable code usually NPEs.

Migration discipline. Because these behaviors add real columns, always:

  1. Add the trait/attribute.
  2. Run doctrine:migrations:diff and read the migration.
  3. Make new columns nullable for existing tables, or provide a default, then backfill in a follow-up migration.
  4. Deploy the backfill before making the column NOT NULL.

Do not let Doctrine's --force schema update against production because the attributes "just add a timestamp."

Serialization and API surface. Set #[Groups] on the trait-provided getters if you expose entities through Symfony Serializer — timestamp/audit fields are usually exactly what you want in an API response, but they leak more than you expect by default.

Fixtures and tests. Doctrine lifecycle callbacks fire during doctrine:fixtures:load, which is convenient (fixtures get slugs/timestamps for free) but makes fixture data non-deterministic. For unit tests that assert exact field contents, either freeze the clock or disable the relevant subscriber in the test container.

Gotchas and Tips

Maturity is the headline risk. 10 stars, 0 dependents, a single maintainer, and a release date that reads oddly (2026-10-18 — verify the tag actually exists and matches composer.lock). Treat this as "read the source, then decide," not "composer require and forget." Pin an exact version ("rami/entity-kit-bundle": "1.x.y") and be prepared to fork; the code is MIT and small enough to vendor into src/ if the maintainer disappears. Never let it become load-bearing without a fork of the two or three behaviors you actually use.

Bulk DQL bypasses everything. $em->createQuery('UPDATE ...'), ->delete() via DQL, and raw SQL will not trigger lifecycle callbacks. Timestamps and slugs silently go stale. Use UnitOfWork-aware updates or re-derive after bulk operations.

Slug uniqueness needs a retry loop. The naive implementation produces a duplicate-key exception the first time two posts share a title. Check whether the package handles collision suffixes (-2, -3) or whether you must. Pair the slug column with a unique index so the failure is loud, and wrap creation in a small retry helper if the package does not.

onFlush vs preUpdate matters. If the package hooks preUpdate, changing the field inside the callback can trigger Doctrine's "no changes detected" / re-computation dance and, in older ORM versions, an infinite UnitOfWork loop. If you see the update callback firing repeatedly, that is the cause.

Reflection caching. Attribute readers that scan entities on every flush are cheap per-entity and expensive at scale. If you are importing 50k rows, benchmark it; batch with $em->clear() periodically.

Timezone and immutable types. Check whether timestamps are DateTime or DateTimeImmutable and whether they respect the DB session timezone. Standardize on DateTimeImmutable in your own code and confirm the trait agrees, or you will get mutation bugs from shared instances.

Extension points to prefer: (a) the Doctrine event subscribers — register your own with a higher priority to run before the package's; (b) a custom trait that reuses the package's interfaces but overrides the setter logic; (c) a small decorator around the user resolver. Avoid editing vendor files — everything above is achievable from your src/.

Evaluate the alternatives before committing. gedmo/doctrine-extensions is framework-agnostic, battle-tested, and covers timestampable/sluggable/blameable with years of production use. If you are on Laravel, the native equivalents (spatie/laravel-sluggable, owen-it/laravel-auditing, Eloquent's own $timestamps, SoftDeletes) do this with far less risk. This package's edge is compositional attributes and a Symfony-idiomatic shape — a genuinely nicer DX than Gedmo's annotation-era API — but at 0 dependents you are the QA team. Prototype on a branch, measure what it saves you, and only then put it on a critical path.

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.
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
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle