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

Getter Setter Accessor Bundle Laravel Package

alexanevsky/getter-setter-accessor-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:
    composer require alexanevsky/getter-setter-accessor-bundle
    
  2. Register the Bundle (if not auto-discovered): Add to config/bundles.php:
    Alexanevsky\GetterSetterAccessorBundle\GetterSetterAccessorBundle::class => ['all' => true],
    
  3. First Use Case: Inject GetterSetterAccessor into a controller or service:
    use Alexanevsky\GetterSetterAccessorBundle\GetterSetterAccessor;
    
    public function __construct(private GetterSetterAccessor $accessor) {}
    
    public function updateProfile(Request $request, User $user) {
        $accessor = $this->accessor->createAccessor($user);
        $accessor->setValue('userName', $request->input('name')); // Set via snake/camel case
        return response()->json(['status' => 'updated']);
    }
    

Implementation Patterns

Core Workflows

  1. Dynamic Property Access: Use getValue()/setValue() for runtime property manipulation without direct reflection:

    $value = $accessor->getValue('userEmail'); // Works for both snake_case and camelCase
    $accessor->setValue('user_email', 'new@example.com');
    
  2. Validation Before Access: Check getter/setter existence before operations:

    if ($accessor->hasGetter('profilePicture')) {
        $image = $accessor->getValue('profilePicture');
    }
    
  3. Bulk Property Inspection: Iterate over available getters to build forms or APIs:

    foreach ($accessor->getGetters() as $getter) {
        echo sprintf(
            'Field: %s, Type: %s, Nullable: %s',
            $getter->getName(),
            implode(', ', $getter->getTypes()),
            $getter->isNullable() ? 'Yes' : 'No'
        );
    }
    
  4. Type-Safe Operations: Use getTypes() to validate input before setting values:

    $types = $accessor->getGetter('age')->getTypes();
    if (!in_array('int', $types)) {
        throw new \InvalidArgumentException('Age must be an integer');
    }
    
  5. Integration with Forms: Dynamically generate form fields from model getters:

    $fields = collect($accessor->getGetters())
        ->map(fn($getter) => [
            'name' => $getter->getName(),
            'label' => ucwords(str_replace('_', ' ', $getter->getName())),
            'type' => $getter->isNullable() ? 'text' : 'required_text',
        ]);
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity:

    • The package converts between snake_case and camelCase, but mixed cases (e.g., userName vs user_name) must be consistent. Test both formats if unsure.
    • Fix: Use hasGetter('userName') to verify the correct format before access.
  2. Non-Public Properties:

    • The package relies on public getters/setters. Private/protected properties won’t be accessible.
    • Fix: Ensure your model uses public methods or add explicit getters/setters.
  3. Circular References:

    • Setting nested objects (e.g., $accessor->setValue('address.city', 'NY')) may fail if the intermediate object isn’t initialized.
    • Fix: Initialize nested objects manually or use a recursive setter pattern.
  4. Performance:

    • getGetters() reflects the entire object. Cache results if called frequently:
      private $gettersCache;
      public function getGetters() {
          return $this->gettersCache ??= $this->accessor->getGetters();
      }
      
  5. Symfony-Specific Quirks:

    • If using with Doctrine entities, ensure @Assert annotations don’t interfere with dynamic access.
    • Fix: Test with @Assert\Type constraints to avoid runtime errors.

Debugging Tips

  1. Inspect Available Getters: Dump the getter list to debug missing properties:

    dd($accessor->getGetters()->map(fn($g) => $g->getName()));
    
  2. Handle Exceptions: Wrap getValue()/setValue() in try-catch for missing methods:

    try {
        $accessor->setValue('invalidProperty', 'value');
    } catch (\RuntimeException $e) {
        // Log or handle gracefully
    }
    
  3. Attribute Introspection: Use getAttribute() to debug custom attributes (e.g., from Symfony UX):

    if ($accessor->getGetter('email')->hasAttribute(\Symfony\UX\Attribute\Email::class)) {
        // Handle email-specific logic
    }
    

Extension Points

  1. Custom Accessor Logic: Extend the base AccessorInterface to add logic (e.g., default values):

    class CustomAccessor implements AccessorInterface {
        public function getValue(string $property) {
            return $this->accessor->getValue($property) ?: 'default_value';
        }
    }
    
  2. Event Listeners: Hook into setter operations via Symfony events (e.g., kernel.request):

    # config/services.yaml
    services:
        App\EventListener\PropertySetterListener:
            tags:
                - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
    
  3. Testing: Mock the accessor in tests to avoid reflection:

    $mockAccessor = $this->createMock(GetterSetterAccessor::class);
    $mockAccessor->method('getValue')->willReturn('test_value');
    
  4. Laravel-Specific:

    • Form Requests: Use the accessor to validate input against model getters:
      public function rules() {
          $getters = $this->accessor->getGetters();
          return collect($getters)
              ->filter(fn($g) => !$g->isNullable())
              ->pluck('name')
              ->mapWithKeys(fn($name) => [$name => 'required'])
              ->toArray();
      }
      
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.
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
spatie/flare-daemon-runtime