Weave Code
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

Darvin Utils Bundle Laravel Package

darvinstudio/darvin-utils-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require darvinstudio/darvin-utils-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        DarvinStudio\DarvinUtilsBundle\DarvinUtilsBundle::class => ['all' => true],
    ];
    
  2. 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');
        }
    }
    
  3. Where to Look First:


Implementation Patterns

Core Workflows

1. Access Control

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
    }
}

2. Entity Cloning

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
]);

3. Default Values

Pattern: Auto-populate fields via annotations.

# src/Entity/Order.php
use DarvinStudio\DarvinUtilsBundle\Annotation\DefaultValue;

/**
 * @DefaultValue(property="user.id")
 */
private ?int $userId = null;

4. Flash Notifications

Pattern: Context-aware flash messages.

$this->flashNotifier
    ->add('success', 'Item updated', ['route' => 'edit_item', 'id' => $item->getId()]);

5. Custom Entity Loading

Pattern: Initialize related entities via attributes.

use DarvinStudio\DarvinUtilsBundle\Loader\CustomEntityLoaderInterface;

$user = $this->entityLoader->load(User::class, [
    'profile' => ['name' => 'Default Profile']
]);

Integration Tips

  • Doctrine Events: Hook Cloner or CustomEntityLoader into prePersist/preUpdate lifecycle callbacks.
  • Symfony Forms: Use DefaultValue to auto-fill form fields from other entity properties.
  • APIs: Combine AccessibilityChecker with Symfony’s Voter for granular API permissions.

Gotchas and Tips

Pitfalls

  1. Annotation Processing:

    • DefaultValue and MetadataFactory require cache clearing after adding new annotations:
      php bin/console cache:clear
      
    • Gotcha: Annotations must be imported in composer.json:
      "autoload": {
          "files": ["vendor/darvinstudio/darvin-utils-bundle/Resources/stubs/annotations.php"]
      }
      
  2. Cloner Limitations:

    • Gotcha: Circular references (e.g., User->Orders->User) will cause infinite loops. Use Cloner::clone() with a visited array:
      $this->cloner->clone($entity, [], ['visited' => [$entity]]);
      
    • Tip: Exclude sensitive fields (e.g., passwords) via the exclude option:
      $this->cloner->clone($user, [], ['exclude' => ['password']]);
      
  3. Flash Notifier Scope:

    • Gotcha: Flash messages are request-scoped. Use FlashNotifier::get() to retrieve them in templates.
    • Tip: For persistent notifications (e.g., after redirect), store messages in the session manually.
  4. Accessibility Checker:

    • Gotcha: Default implementation checks public getter methods. Ensure your entities follow this pattern.
    • Tip: Extend 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);
          }
      }
      
  5. Metadata Factory:

    • Gotcha: Only processes classes loaded by Doctrine. For standalone classes, use:
      $metadata = $this->metadataFactory->getMetadataFor(ClassRegistry::getMetadataFor('Acme\MyClass'));
      

Debugging Tips

  • Enable Debug Mode: Add to config/packages/darvin_utils.yaml:
    darvin_utils:
        debug: true # Logs annotation processing and cloning steps
    
  • Cloner Debugging: Use the debug option to log cloned properties:
    $this->cloner->clone($entity, [], ['debug' => true]);
    
  • Flash Messages: Check the session bag for unexpected messages:
    $this->get('session')->getFlashBag()->all();
    

Extension Points

  1. Custom Flash Types: Extend FlashNotifier to add custom message types (e.g., warning):

    $this->flashNotifier->add('warning', 'Low stock', ['product_id' => $product->getId()]);
    
  2. 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);
        }
    }
    
  3. 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());
        }
    }
    
  4. 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
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle