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

Grid Bundle Laravel Package

cwd/grid-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require cwd/grid-bundle
    

    Ensure the bundle is enabled in config/bundles.php:

    return [
        // ...
        Cwd\GridBundle\CwdGridBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Define a grid in a controller or service:

    use Cwd\GridBundle\Grid\Grid;
    use Cwd\GridBundle\Grid\Column\EnumType;
    
    public function buildGrid(): Grid
    {
        return (new Grid())
            ->add(new EnumType('status', 'user.status', [
                'label' => 'Status',
                'class' => UserStatus::class,
            ]));
    }
    
  3. Enum Definition: Create a PHP 8.1+ enum (e.g., UserStatus.php):

    enum UserStatus: string {
        case ACTIVE = 'active';
        case INACTIVE = 'inactive';
        case PENDING = 'pending';
    }
    
  4. Translations: Add translations in config/packages/translation.yaml and define keys in translations/messages.en.yaml:

    # messages.en.yaml
    active: "Active"
    inactive: "Inactive"
    pending: "Pending"
    
  5. Render the Grid: Use Twig to display the grid in a template:

    {{ render(controller('App\Controller\YourController::buildGrid')) }}
    

Implementation Patterns

Column Configuration

  • Dynamic Enum Classes: Pass the enum class dynamically (e.g., via dependency injection or service container):

    $enumClass = $this->container->getParameter('app.user_status_enum');
    $grid->add(new EnumType('status', 'user.status', ['class' => $enumClass]));
    
  • Reusable Column Factories: Create a factory method to standardize enum column creation:

    public function createEnumColumn(string $name, string $dataKey, string $enumClass, string $label): EnumType
    {
        return new EnumType($name, $dataKey, [
            'label' => $label,
            'class' => $enumClass,
            'allOptionsLabel' => 'all_' . strtolower($label),
        ]);
    }
    

Filtering and Sorting

  • Default Filter Values: Set a default filter value in the column options:

    ->add(new EnumType('status', 'user.status', [
        'class' => UserStatus::class,
        'defaultFilter' => UserStatus::PENDING->value,
    ]))
    
  • Custom Filter Logic: Extend EnumType to override filter behavior (e.g., multi-select):

    class MultiEnumType extends EnumType {
        public function __construct(string $name, string $dataKey, array $options = [])
        {
            $options['multiple'] = true;
            parent::__construct($name, $dataKey, $options);
        }
    }
    

Integration with Forms and APIs

  • Form Type Integration: Use the same enum class in Symfony forms for consistency:

    $builder->add('status', EnumType::class, [
        'class' => UserStatus::class,
        'choice_label' => fn(UserStatus $status) => $this->translator->trans($status->value),
    ]);
    
  • API Responses: Normalize enum values in API responses using a transformer:

    public function transform($object, string $format = null, array $context = [])
    {
        return [
            'status' => $object->status->value,
            'status_label' => $this->translator->trans($object->status->value),
        ];
    }
    

Performance Optimization

  • Lazy-Loading Enums: Load enum classes dynamically to reduce memory usage:

    $enumClass = $this->getEnumClassFromConfig($dataKey);
    $grid->add(new EnumType('status', $dataKey, ['class' => $enumClass]));
    
  • Caching Translations: Cache translated enum labels to avoid repeated translation lookups:

    $translator = $this->container->get('translator');
    $cachedLabels = $translator->getCatalogue()->all('en', 'messages');
    

Gotchas and Tips

Common Pitfalls

  1. Enum Class Not Found:

    • Issue: Class [App\Domain\UserStatus] does not exist.
    • Fix: Ensure the enum class is autoloaded (check composer dump-autoload).
    • Tip: Use fully qualified names (e.g., App\Domain\UserStatus) in the class option.
  2. Translation Keys Missing:

    • Issue: Enum values display as raw strings (e.g., ACTIVE instead of Active).
    • Fix: Verify translation keys match enum case values exactly (case-sensitive).
    • Tip: Use translator:dump to debug missing translations:
      php bin/console translator:dump en messages
      
  3. Filter Dropdown Empty:

    • Issue: The enum filter dropdown appears empty.
    • Fix: Check if the enum class is properly defined and accessible. Debug with:
      var_dump((new \ReflectionClass($enumClass))->getCases());
      
  4. Deprecated Symfony Features:

    • Issue: Errors related to deprecated Symfony components (e.g., Symfony\Component\HttpFoundation\Request).
    • Fix: Update Symfony dependencies to the latest stable version:
      composer require symfony/*:^6.3
      

Debugging Tips

  • Log Enum Data: Add debug logs to inspect enum data flow:

    $grid->add(new EnumType('status', 'user.status', [
        'class' => UserStatus::class,
        'debug' => true, // Hypothetical option; log manually if needed
    ]));
    
  • Check Grid Events: Listen to grid events to debug column rendering:

    $grid->on('column.build', function (ColumnEvent $event) {
        if ($event->getColumn() instanceof EnumType) {
            $this->logger->debug('Enum column built:', [
                'name' => $event->getColumn()->getName(),
                'options' => $event->getColumn()->getOptions(),
            ]);
        }
    });
    

Extension Points

  1. Custom Enum Rendering: Extend EnumType to render enums differently (e.g., badges or icons):

    class BadgeEnumType extends EnumType {
        public function renderCell($value, array $rowData)
        {
            $label = parent::renderCell($value, $rowData);
            return sprintf('<span class="badge bg-%s">%s</span>', $this->getBadgeClass($value), $label);
        }
    
        private function getBadgeClass(string $value): string
        {
            return match ($value) {
                'active' => 'success',
                'inactive' => 'danger',
                default => 'primary',
            };
        }
    }
    
  2. Dynamic Enum Loading: Implement a custom loader for enums fetched from a database or API:

    class DynamicEnumType extends EnumType {
        public function __construct(string $name, string $dataKey, array $options = [])
        {
            $options['class'] = $this->loadEnumClassFromDatabase($dataKey);
            parent::__construct($name, $dataKey, $options);
        }
    
        private function loadEnumClassFromDatabase(string $dataKey): string
        {
            // Logic to fetch enum definition dynamically
            return 'App\Domain\Dynamic\\' . ucfirst($dataKey) . 'Enum';
        }
    }
    
  3. Integration with Doctrine: Use enums in Doctrine entities and sync grid columns:

    // Entity
    #[ORM\Column(enumType: UserStatus::class)]
    private UserStatus $status;
    
    // Grid
    ->add(new EnumType('status', 'user.status', [
        'class' => UserStatus::class,
        'doctrine_enum' => true, // Hypothetical option; validate manually
    ]))
    

Configuration Quirks

  • All Options Label: The allOptionsLabel must be a valid translation key. Defaults to 'all', but ensure it’s defined in translations:

    # messages.en.yaml
    all: "All"
    all_states: "All States" # Custom label for enum columns
    
  • Translatable Option: Setting translatable: false bypasses translation, but ensure the enum values are user-friendly:

    ->add(new EnumType('status', 'user.status', [
        'class' => UserStatus::class,
        'translatable' => false,
    ]))
    
  • Case Sensitivity: Enum case values are case-sensitive in translations. Use strtolower() if needed:

    // In a custom renderer
    $transKey =
    
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.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony