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

Resource Bundle Laravel Package

atoolo/resource-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require sitepark/atoolo-resource-bundle
    

    Add the bundle to config/bundles.php:

    return [
        // ...
        Sitepark\Atoolo\ResourceBundle\AtooloResourceBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default config:

    php artisan vendor:publish --tag="atoolo-resource-bundle-config"
    

    Update .env with your resource root:

    RESOURCE_ROOT=/path/to/your/resources
    
  3. First Use Case Load a resource via the ResourceLoader service:

    use Sitepark\Atoolo\ResourceBundle\Loader\ResourceLoaderInterface;
    
    class MyController
    {
        public function __construct(
            private ResourceLoaderInterface $resourceLoader
        ) {}
    
        public function showResource()
        {
            $resource = $this->resourceLoader->load('path/to/resource');
            return response()->json($resource->getData());
        }
    }
    

Implementation Patterns

Core Workflows

1. Resource Loading

  • Basic Loading

    $resource = $resourceLoader->load('path/to/resource');
    

    Supports hierarchical paths (e.g., parent/child/resource).

  • Language Fallback

    $resource = $resourceLoader->load('path/to/resource', 'en');
    // Falls back to default language if 'en' translation is missing
    
  • Lazy Loading Use ResourceChannel for lazy-loaded resources:

    $channel = $resourceLoader->getChannel('news');
    $resource = $channel->getResource('latest-article');
    

2. Resource Hierarchies

  • Walk Hierarchies

    $walker = new ResourceHierarchyWalker($resourceLoader);
    $walker->walk('parent/path', function ($resource) {
        // Process each resource in hierarchy
    });
    
  • Find Hierarchy Roots

    $finder = new ResourceHierarchyFinder($resourceLoader);
    $roots = $finder->findRoots('search-index');
    

3. Caching

  • Cache Management
    // Clear cache for a specific resource
    $resourceLoader->clearCache('path/to/resource');
    
    // Clear all cache
    $resourceLoader->clearAllCache();
    

4. Custom Resource Locators

  • Extend ResourceBaseLocator
    use Sitepark\Atoolo\ResourceBundle\Locator\ResourceBaseLocator;
    
    class CustomLocator extends ResourceBaseLocator
    {
        public function locate(string $path): string
        {
            return parent::locate($path) . '.custom';
        }
    }
    
    Register in services.yaml:
    services:
        Sitepark\Atoolo\ResourceBundle\Loader\ResourceLoader:
            arguments:
                $locator: '@custom_locator'
    

Integration Tips

Symfony Integration

  • Dependency Injection Autowire ResourceLoaderInterface directly into controllers/services:

    public function __construct(
        private ResourceLoaderInterface $resourceLoader
    ) {}
    
  • Event Listeners Listen to resource events (e.g., ResourceLoadedEvent):

    use Sitepark\Atoolo\ResourceBundle\Event\ResourceLoadedEvent;
    
    class MyListener
    {
        public function onResourceLoaded(ResourceLoadedEvent $event)
        {
            // Log or transform loaded resources
        }
    }
    

    Register in services.yaml:

    services:
        App\Listener\MyListener:
            tags:
                - { name: kernel.event_listener, event: resource.loaded, method: onResourceLoaded }
    

API Responses

  • Normalize Resources
    use Sitepark\Atoolo\ResourceBundle\Model\Resource;
    
    public function getResource(Resource $resource)
    {
        return response()->json([
            'id' => $resource->getId(),
            'data' => $resource->getData(),
            'language' => $resource->getLanguage(),
        ]);
    }
    

Testing

  • Mock ResourceLoader
    $mockLoader = $this->createMock(ResourceLoaderInterface::class);
    $mockLoader->method('load')
        ->with('test/path')
        ->willReturn(new Resource(['key' => 'value']));
    
    $this->app->instance(ResourceLoaderInterface::class, $mockLoader);
    

Gotchas and Tips

Pitfalls

1. Resource Path Resolution

  • Issue: Incorrect paths may throw ResourceNotFoundException.
    • Fix: Use ResourceLocation::ofPath() for validation:
      $location = ResourceLocation::ofPath('path/to/resource');
      if (!$location->isValid()) {
          throw new \InvalidArgumentException('Invalid resource path');
      }
      

2. Circular References

  • Issue: Hierarchical resources with circular parent references may cause infinite loops.
    • Fix: Use ResourceHierarchyWalker with depth limits:
      $walker->walk('parent/path', function ($resource) {}, 5); // Max depth: 5
      

3. Caching Quirks

  • Issue: Cache invalidation may not reflect immediately.
    • Fix: Clear cache explicitly after updates:
      $resourceLoader->clearCache('path/to/updated/resource');
      

4. Language Fallback

  • Issue: Fallback to default language may not work as expected.
    • Fix: Ensure default_language is set in config (config/atoolo_resource.php):
      'default_language' => 'en',
      

5. PHP Version Compatibility

  • Issue: PHP 8.1 is no longer actively checked (see README).
    • Fix: Test on PHP 8.2+ and use strict_types=1 in custom code.

Debugging Tips

1. Enable Debug Logging

Add to config/atoolo_resource.php:

'debug' => env('APP_DEBUG', false),

Logs resource loading events to storage/logs/atoolo_resource.log.

2. Dump Resource Data

use Symfony\Component\VarDumper\VarDumper;

public function debugResource(Resource $resource)
{
    VarDumper::dump($resource->getData());
}

3. Validate Resource Structure

Use ResourceValidator:

use Sitepark\Atoolo\ResourceBundle\Validator\ResourceValidator;

$validator = new ResourceValidator();
$errors = $validator->validate($resource);
if (!$errors->isEmpty()) {
    throw new \RuntimeException('Invalid resource structure');
}

Extension Points

1. Custom Loaders

Extend ResourceLoaderInterface:

class CustomLoader implements ResourceLoaderInterface
{
    public function load(string $path, ?string $language = null): Resource
    {
        // Custom logic (e.g., database fallback)
        return new Resource(['custom' => 'data']);
    }
}

Register as a service:

services:
    App\Loader\CustomLoader:
        tags: ['atoolo.resource_loader']

2. Custom Resource Models

Extend Resource:

use Sitepark\Atoolo\ResourceBundle\Model\Resource;

class ExtendedResource extends Resource
{
    public function getCustomField(): string
    {
        return $this->getData()['custom_field'] ?? '';
    }
}

Override the loader to return your model:

public function load(string $path): ExtendedResource
{
    $resource = parent::load($path);
    return new ExtendedResource($resource->getData());
}

3. Event Subscribers

Listen to ResourceLoadedEvent or ResourceLoadingEvent:

use Sitepark\Atoolo\ResourceBundle\Event\ResourceLoadedEvent;

class MySubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            ResourceLoadedEvent::class => 'onResourceLoaded',
        ];
    }

    public function onResourceLoaded(ResourceLoadedEvent $event)
    {
        $event->getResource()->setMetadata('processed', true);
    }
}

4. Custom Exceptions

Extend ResourceException:

use Sitepark\Atoolo\ResourceBundle\Exception\ResourceException;

class MyResourceException extends ResourceException {}

Throw in custom loaders:

throw new MyResourceException('Custom error message');

Configuration Quirks

1. RESOURCE_ROOT Environment Variable

  • Must point to the root directory of your resources.
  • Override in .env:
    RESOURCE_ROOT=/custom/path/to/resources
    

2. atoolo_resource.resource_host

  • Used for multi-tenant setups.
  • Configure in config/atoolo_resource.php:
    'resource_host' => env('ATOOLO_RESOURCE_HOST', 'default'),
    

**3. Cache Direct

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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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