schvoy/base-entity-bundle
Symfony bundle providing reusable Doctrine base entities (ID/UUID/ULID) and traits with common behaviors: timestampable (created/updated), soft delete, and blameable user tracking. Includes automatic listeners and configurable User class support.
Installation
composer require schvoy/base-entity-bundle
Add to config/bundles.php:
return [
// ...
Schvoy\BaseEntityBundle\SchvoyBaseEntityBundle::class => ['all' => true],
];
First Use Case: Create a Base Entity
Extend Schvoy\BaseEntityBundle\Entity\BaseEntity in your custom entity:
namespace App\Entity;
use Schvoy\BaseEntityBundle\Entity\BaseEntity as BaseEntityBundle;
class User extends BaseEntityBundle
{
// Your custom fields/methods
}
Key Features to Explore
Schvoy\BaseEntityBundle\Traits for reusable behaviors (e.g., Timestampable, SoftDeletable).Schvoy\BaseEntityBundle\Repository\BaseRepository for custom logic.prePersist, preUpdate).Entity Creation
use Schvoy\BaseEntityBundle\Entity\BaseEntity;
class Product extends BaseEntity
{
#[ORM\Column]
private string $name;
// Auto-generated: id, createdAt, updatedAt, deletedAt (if SoftDeletable)
}
Repository Integration
use Schvoy\BaseEntityBundle\Repository\BaseRepository;
class ProductRepository extends BaseRepository
{
public function findActive(): array
{
return $this->createQueryBuilder('p')
->where('p.deletedAt IS NULL')
->getQuery()
->getResult();
}
}
Service Layer
Use traits like Timestampable to auto-manage timestamps:
use Schvoy\BaseEntityBundle\Traits\Timestampable;
class ProductService
{
use Timestampable;
public function createProduct(string $name): Product
{
$product = new Product();
$product->setName($name);
$this->setCreatedAt($product); // Auto-set via trait
return $product;
}
}
SoftDeletable trait and configure deletedAt column.Schvoy\BaseEntityBundle\Traits\AuditLoggable for change tracking.Schvoy\BaseEntityBundle\Validator\Constraints (e.g., @UniqueEntity) in entities.Doctrine Events Collisions
BaseRepository, ensure your event subscribers don’t conflict with the bundle’s default listeners.priority in subscriber services or override methods explicitly.Soft Delete Quirks
deletedAt is nullable by default. Ensure your ProductRepository filters for IS NULL when querying "active" records.isDeleted() method to BaseEntity for consistency:
public function isDeleted(): bool
{
return $this->deletedAt !== null;
}
Timestamp Precision
DateTimeImmutable for timestamps. If your app uses DateTime, conflicts may arise.Enable SQL Logging: Add to config/packages/dev/doctrine.yaml:
doctrine:
dbal:
logging: true
profiling: true
Helps verify if deletedAt/timestamps are updating as expected.
Check Event Order: Use Symfony’s debug:event-dispatcher to inspect event priorities:
php bin/console debug:event-dispatcher
Custom Traits
Add your own traits to Schvoy\BaseEntityBundle\Entity\BaseEntity:
namespace App\Entity;
use Schvoy\BaseEntityBundle\Entity\BaseEntity;
use App\Traits\CustomBehavior;
class User extends BaseEntity
{
use CustomBehavior;
}
Override Base Methods
Extend BaseRepository to modify default queries:
class ProductRepository extends BaseRepository
{
public function findByName(string $name): ?Product
{
return $this->createQueryBuilder('p')
->andWhere('p.name = :name')
->setParameter('name', $name)
->getOneOrNullResult();
}
}
Configuration
Override bundle defaults in config/packages/schvoy_base_entity.yaml:
schvoy_base_entity:
soft_delete_column: 'is_deleted' # Custom column name
timestamp_precision: 3 # Milliseconds
How can I help you explore Laravel packages today?