Installation
composer require sitepark/atoolo-resource-bundle
Add the bundle to config/bundles.php:
return [
// ...
Sitepark\Atoolo\ResourceBundle\AtooloResourceBundle::class => ['all' => true],
];
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
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());
}
}
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');
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');
// Clear cache for a specific resource
$resourceLoader->clearCache('path/to/resource');
// Clear all cache
$resourceLoader->clearAllCache();
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'
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 }
use Sitepark\Atoolo\ResourceBundle\Model\Resource;
public function getResource(Resource $resource)
{
return response()->json([
'id' => $resource->getId(),
'data' => $resource->getData(),
'language' => $resource->getLanguage(),
]);
}
$mockLoader = $this->createMock(ResourceLoaderInterface::class);
$mockLoader->method('load')
->with('test/path')
->willReturn(new Resource(['key' => 'value']));
$this->app->instance(ResourceLoaderInterface::class, $mockLoader);
ResourceNotFoundException.
ResourceLocation::ofPath() for validation:
$location = ResourceLocation::ofPath('path/to/resource');
if (!$location->isValid()) {
throw new \InvalidArgumentException('Invalid resource path');
}
ResourceHierarchyWalker with depth limits:
$walker->walk('parent/path', function ($resource) {}, 5); // Max depth: 5
$resourceLoader->clearCache('path/to/updated/resource');
default_language is set in config (config/atoolo_resource.php):
'default_language' => 'en',
strict_types=1 in custom code.Add to config/atoolo_resource.php:
'debug' => env('APP_DEBUG', false),
Logs resource loading events to storage/logs/atoolo_resource.log.
use Symfony\Component\VarDumper\VarDumper;
public function debugResource(Resource $resource)
{
VarDumper::dump($resource->getData());
}
Use ResourceValidator:
use Sitepark\Atoolo\ResourceBundle\Validator\ResourceValidator;
$validator = new ResourceValidator();
$errors = $validator->validate($resource);
if (!$errors->isEmpty()) {
throw new \RuntimeException('Invalid resource structure');
}
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']
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());
}
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);
}
}
Extend ResourceException:
use Sitepark\Atoolo\ResourceBundle\Exception\ResourceException;
class MyResourceException extends ResourceException {}
Throw in custom loaders:
throw new MyResourceException('Custom error message');
RESOURCE_ROOT Environment Variable.env:
RESOURCE_ROOT=/custom/path/to/resources
atoolo_resource.resource_hostconfig/atoolo_resource.php:
'resource_host' => env('ATOOLO_RESOURCE_HOST', 'default'),
How can I help you explore Laravel packages today?