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

Component Firi Laravel Package

appsco/component-firi

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require appsco/component-firi
    

    Note: Due to outdated Symfony 2.x dependencies, ensure your project can tolerate these constraints (or fork the package for Symfony 5+ compatibility).

  2. First Use Case: Render a filtered collection of Doctrine entities with custom rendering logic.

    use AppSco\Component\Firi\FilterItemRendererIterator;
    
    $entities = $entityManager->getRepository(Entity::class)->findAll();
    $iterator = new FilterItemRendererIterator(
        new ArrayIterator($entities),
        new \CallbackFilterIterator($entities, fn($item) => $item->isActive()),
        new \CallbackFilterIterator($entities, fn($item) => $item->getPriority() > 0)
    );
    
    foreach ($iterator as $renderedItem) {
        // $renderedItem is the processed output (e.g., array, string, or custom object)
    }
    
  3. Key Classes:

    • FilterItemRendererIterator: Core class combining filtering and rendering.
    • FilterItemRenderer: Base renderer (extend for custom logic).
    • FilterItemRendererFactory: Factory for creating renderers (if available in newer versions).
  4. Where to Look First:

    • src/AppSco/Component/Firi/FilterItemRendererIterator.php (core logic).
    • tests/ (if available) for usage examples.

Implementation Patterns

Workflow: Filtering + Rendering Pipeline

  1. Input:

    • A traversable collection (e.g., ArrayIterator, Doctrine\ORM\QueryBuilder result).
    • Zero or more FilterIterator implementations (e.g., CallbackFilterIterator, custom filters).
  2. Processing:

    $rawData = $entityManager->createQueryBuilder()
        ->select('e')
        ->from(Entity::class, 'e')
        ->getQuery()
        ->iterate();
    
    $filteredIterator = new \CallbackFilterIterator($rawData, fn($item) => $item['isActive']);
    $renderer = new CustomRenderer(); // Extend FilterItemRenderer
    $firi = new FilterItemRendererIterator($filteredIterator, $renderer);
    
  3. Output:

    • Iterate over $firi to get rendered items (e.g., arrays, strings, or transformed objects).
    • Example renderer output:
      class CustomRenderer extends FilterItemRenderer {
          public function render($item) {
              return [
                  'id' => $item->getId(),
                  'name' => $item->getName(),
                  'formatted' => $this->formatValue($item->getValue()),
              ];
          }
      }
      

Integration Tips

  • Doctrine ORM: Use QueryBuilder->iterate() to avoid loading all entities into memory at once.

    $query = $entityManager->createQueryBuilder()
        ->select('e')
        ->from(Entity::class, 'e')
        ->where('e.isActive = :active')
        ->setParameter('active', true)
        ->iterate();
    
  • Symfony Dependency Injection: Bind the factory/iterator as a service (if using Symfony 2.x):

    services:
        firi.iterator:
            class: AppSco\Component\Firi\FilterItemRendererIterator
            arguments:
                - '@filter_iterator'
                - '@renderer'
    
  • Custom Filters: Create reusable filter classes:

    class ActiveFilterIterator extends FilterIterator {
        public function accept() {
            return $this->current()->isActive();
        }
    }
    
  • Batch Processing: Combine with IteratorIterator for lazy loading:

    $iterator = new IteratorIterator(
        new FilterItemRendererIterator(
            $rawData,
            new ActiveFilterIterator($rawData),
            new CustomRenderer()
        )
    );
    

Gotchas and Tips

Pitfalls

  1. Symfony 2.x Dependencies:

    • The package requires Symfony 2.x components. If using Symfony 5/6/Laravel, you may need to:
      • Fork the package and update dependencies (e.g., symfony/options-resolver to ^5.0).
      • Use a compatibility layer like symfony/polyfill.
    • Workaround: Check for forks or alternatives like spatie/array-to-object for rendering.
  2. Memory Leaks:

    • iterate() in Doctrine ORM returns a lazy iterator, but chaining multiple FilterIterators can load data prematurely.
    • Fix: Ensure filters are applied in the database layer (e.g., QueryBuilder->where()) before passing to FilterItemRendererIterator.
  3. Renderer Assumptions:

    • The base FilterItemRenderer may assume certain methods (e.g., render()). Override carefully:
      class MyRenderer extends FilterItemRenderer {
          public function render($item) {
              if (!$item instanceof MyEntity) {
                  throw new \InvalidArgumentException('Expected MyEntity');
              }
              return $item->toArray();
          }
      }
      
  4. No Built-in Factory:

    • The package lacks a factory class in the 2019 release. Manually instantiate:
      $firi = new FilterItemRendererIterator($filteredIterator, $renderer);
      
    • Tip: Create a simple factory if reusing often:
      class FiriFactory {
          public static function create($data, RendererInterface $renderer) {
              return new FilterItemRendererIterator(
                  new ArrayIterator($data),
                  $renderer
              );
          }
      }
      

Debugging

  1. Iterator State:

    • Use iterator_to_array() to inspect intermediate states:
      $filtered = iterator_to_array(new CallbackFilterIterator($rawData, fn($item) => true));
      var_dump($filtered);
      
  2. Renderer Output:

    • Log rendered items to verify transformations:
      foreach ($firi as $item) {
          \Log::debug('Rendered:', ['item' => $item]);
      }
      
  3. Performance:

    • Profile with memory_get_usage() to check for unexpected loading:
      $start = memory_get_usage();
      foreach ($firi as $item) {}
      $end = memory_get_usage();
      \Log::info('Memory used:', ['bytes' => $end - $start]);
      

Extension Points

  1. Custom Renderers:

    • Extend FilterItemRenderer to add logic:
      class JsonRenderer extends FilterItemRenderer {
          public function render($item) {
              return json_encode($item->toArray());
          }
      }
      
  2. Filter Composition:

    • Chain filters for complex logic:
      $iterator = new FilterItemRendererIterator(
          new CallbackFilterIterator($data, fn($item) => $item->isActive()),
          new CallbackFilterIterator($data, fn($item) => $item->isPublished()),
          new CustomRenderer()
      );
      
  3. Event Dispatching:

    • Trigger events before/after rendering (if using Symfony EventDispatcher):
      $dispatcher->addListener('firi.render', function ($event) {
          \Log::info('Rendering item', ['item' => $event->getItem()]);
      });
      
    • Note: Requires integrating Symfony EventDispatcher (not natively supported in this package).
  4. Caching Rendered Output:

    • Cache rendered items in a Renderer subclass:
      class CachedRenderer extends FilterItemRenderer {
          private $cache = [];
      
          public function render($item) {
              if (!isset($this->cache[$item->getId()])) {
                  $this->cache[$item->getId()] = $this->process($item);
              }
              return $this->cache[$item->getId()];
          }
      }
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky