darvinstudio/darvin-utils-bundle
Installation:
composer require darvinstudio/darvin-utils-bundle
Add to config/bundles.php:
return [
// ...
DarvinStudio\DarvinUtilsBundle\DarvinUtilsBundle::class => ['all' => true],
];
First Use Case: Use the Flash Notifier for simple flash messages in a controller:
use DarvinStudio\DarvinUtilsBundle\Notifier\FlashNotifierInterface;
class MyController extends AbstractController
{
public function __construct(private FlashNotifierInterface $flashNotifier) {}
public function showSuccess()
{
$this->flashNotifier->success('Operation completed!');
return $this->redirectToRoute('home');
}
}
Where to Look First:
Resources/doc/ directory for component-specific guides.Pattern: Use AccessibilityChecker for fine-grained entity permissions.
use DarvinStudio\DarvinUtilsBundle\Checker\AccessibilityCheckerInterface;
class ProductController
{
public function __construct(
private AccessibilityCheckerInterface $accessChecker
) {}
public function edit(Product $product, User $user)
{
if (!$this->accessChecker->isAccessible($product, $user)) {
throw $this->createAccessDeniedException();
}
// Proceed with edit logic
}
}
Pattern: Clone entities with relationships using Cloner.
use DarvinStudio\DarvinUtilsBundle\Cloner\ClonerInterface;
$clonedOrder = $this->cloner->clone($originalOrder, [
'id' => null, // Reset ID
'createdAt' => new \DateTime(), // Update timestamp
]);
Pattern: Auto-populate fields via annotations.
# src/Entity/Order.php
use DarvinStudio\DarvinUtilsBundle\Annotation\DefaultValue;
/**
* @DefaultValue(property="user.id")
*/
private ?int $userId = null;
Pattern: Context-aware flash messages.
$this->flashNotifier
->add('success', 'Item updated', ['route' => 'edit_item', 'id' => $item->getId()]);
Pattern: Initialize related entities via attributes.
use DarvinStudio\DarvinUtilsBundle\Loader\CustomEntityLoaderInterface;
$user = $this->entityLoader->load(User::class, [
'profile' => ['name' => 'Default Profile']
]);
Cloner or CustomEntityLoader into prePersist/preUpdate lifecycle callbacks.DefaultValue to auto-fill form fields from other entity properties.AccessibilityChecker with Symfony’s Voter for granular API permissions.Annotation Processing:
DefaultValue and MetadataFactory require cache clearing after adding new annotations:
php bin/console cache:clear
composer.json:
"autoload": {
"files": ["vendor/darvinstudio/darvin-utils-bundle/Resources/stubs/annotations.php"]
}
Cloner Limitations:
User->Orders->User) will cause infinite loops. Use Cloner::clone() with a visited array:
$this->cloner->clone($entity, [], ['visited' => [$entity]]);
exclude option:
$this->cloner->clone($user, [], ['exclude' => ['password']]);
Flash Notifier Scope:
FlashNotifier::get() to retrieve them in templates.Accessibility Checker:
AccessibilityChecker to add custom logic:
class CustomAccessibilityChecker extends AbstractAccessibilityChecker
{
public function isAccessible($object, User $user): bool
{
if ($object instanceof SensitiveEntity && !$user->isAdmin()) {
return false;
}
return parent::isAccessible($object, $user);
}
}
Metadata Factory:
$metadata = $this->metadataFactory->getMetadataFor(ClassRegistry::getMetadataFor('Acme\MyClass'));
config/packages/darvin_utils.yaml:
darvin_utils:
debug: true # Logs annotation processing and cloning steps
debug option to log cloned properties:
$this->cloner->clone($entity, [], ['debug' => true]);
$this->get('session')->getFlashBag()->all();
Custom Flash Types:
Extend FlashNotifier to add custom message types (e.g., warning):
$this->flashNotifier->add('warning', 'Low stock', ['product_id' => $product->getId()]);
Cloner Strategies:
Override ClonerInterface to handle custom types (e.g., DateTime formatting):
class CustomCloner extends AbstractCloner
{
protected function cloneProperty($value, string $propertyName)
{
if ($value instanceof \DateTime && $propertyName === 'createdAt') {
return new \DateTime('now');
}
return parent::cloneProperty($value, $propertyName);
}
}
Access Rules:
Create a voter that delegates to AccessibilityChecker:
use DarvinStudio\DarvinUtilsBundle\Checker\AccessibilityCheckerInterface;
class EntityVoter extends Voter
{
public function __construct(private AccessibilityCheckerInterface $accessChecker) {}
protected function supports($attribute, $subject): bool
{
return $attribute === 'EDIT' && $subject instanceof EntityInterface;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
return $this->accessChecker->isAccessible($subject, $token->getUser());
}
}
Metadata Providers:
Add custom metadata sources to MetadataFactory:
# config/packages/darvin_utils.yaml
darvin_utils:
metadata:
providers:
- 'DarvinStudio\DarvinUtilsBundle\Metadata\AnnotationMetadataProvider'
- 'App\Metadata\CustomMetadataProvider' # Your provider
How can I help you explore Laravel packages today?