components-web-app/api-components-bundle
Installation
composer require components-web-app/api-components-bundle
Add to config/app.php under providers:
ComponentsWebApp\ApiComponentsBundle\ComponentsWebAppApiComponentsBundle::class,
Publish Configuration
php artisan vendor:publish --provider="ComponentsWebApp\ApiComponentsBundle\ComponentsWebAppApiComponentsBundle" --tag="config"
This generates config/api_components.php. Review and adjust:
api_prefix)response_formats)cors_allowed_origins)First Use Case: Exposing a Component Create a basic component controller:
namespace App\Http\Controllers;
use ComponentsWebApp\ApiComponentsBundle\Controller\ApiComponentController;
use Symfony\Component\HttpFoundation\Response;
class MyComponentController extends ApiComponentController
{
public function getData(): Response
{
return $this->respond([
'message' => 'Hello from API Components!',
'data' => ['key' => 'value']
]);
}
}
Register the route in routes/api.php:
$router->mount('/my-component', 'App\Http\Controllers\MyComponentController')
->methods(['GET'])
->bind('my_component');
Test the Endpoint
php artisan serve
Visit http://localhost:8000/api/my-component to see the response.
config/api_components.php for bundle settings.ApiComponentController for reusable API logic.src/Resources/doc/ for usage examples (if available).tests/ directory for integration patterns.// routes/api.php
$router->mount('/hero-banner', 'App\Http\Controllers\HeroBannerController')
->methods(['GET'])
->bind('hero_banner');
ApiComponentController's respond() method to enforce a consistent response format:
return $this->respond([
'success' => true,
'data' => $componentData,
'meta' => ['timestamp' => now()->toIso8601String()]
]);
getResponseFormat() in your controller to customize formats (e.g., JSON, XML).use Symfony\Component\Validator\Constraints as Assert;
public function postData()
{
$this->validateRequest([
'name' => new Assert\NotBlank(),
'email' => new Assert\Email()
]);
// ...
}
public function getData()
{
$this->authorize('view', $this->componentModel);
return $this->respond([...]);
}
auth:api).public function getDynamicComponent()
{
$component = $this->getComponentByUserRole(auth()->user()->role);
return $this->respond($component->toArray());
}
Service Providers Bind custom services to the bundle’s container:
$this->app->bind(
ComponentsWebApp\ApiComponentsBundle\Services\ComponentService::class,
App\Services\CustomComponentService::class
);
Event Listeners
Listen to bundle events (e.g., ComponentLoaded) for side effects:
public function handle(ComponentLoaded $event)
{
Log::info("Component {$event->getName()} loaded at {$event->getTimestamp()}");
}
Blade + API Sync Use the API to preload component data for Blade templates:
// Controller
public function show()
{
$componentData = $this->call('my_component')->getData();
return view('page', compact('componentData'));
}
$data = Cache::remember("component_{$id}", now()->addHours(1), function() use ($id) {
return $this->getComponentData($id);
});
// Frontend
fetch('/api/lazy-component')
.then(response => response.json())
.then(data => renderComponent(data));
ApiComponentController:
$controller = $this->createMock(ApiComponentController::class);
$controller->method('respond')->willReturn(new Response('{}'));
Http::get():
$response = Http::get('/api/my-component');
$response->assertStatus(200)->assertJsonStructure(['data']);
Route Conflicts
/api/v1/components) and validate with:
php artisan route:list
CORS Misconfiguration
cors_allowed_origins in config/api_components.php includes your frontend URL:
'cors_allowed_origins' => ['http://localhost:3000', 'https://yourdomain.com'],
Response Format Inconsistencies
getResponseFormat() in your controller or enforce it via middleware:
public function getResponseFormat(): string
{
return 'json'; // Force JSON
}
Dependency Injection Issues
config/app.php.Rate Limiting
throttle middleware:
Route::middleware(['throttle:60,1'])->group(function () {
// Rate-limited routes
});
Log Component Loading Enable debug logs for component events:
// config/logging.php
'channels' => [
'single' => [
'level' => 'debug',
'handlers' => ['stream'],
],
],
Check logs for ComponentLoaded events.
Validate Request Payloads
Use Laravel’s dd() or dump() to inspect request data:
public function postData()
{
dump($this->request->all()); // Debug payload
// ...
}
Check Response Headers Inspect headers for CORS or caching issues:
curl -I http://localhost:8000/api/my-component
Bundle-Specific Debugging
php artisan api-components:debug (if available) to inspect bundle state.APP_DEBUG=true in .env for detailed error pages.Custom Response Formats
Extend the ResponseFormatter service:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->extend(
ComponentsWebApp\ApiComponentsBundle\Services\ResponseFormatter::class,
function ($formatter) {
return new CustomResponseFormatter($formatter);
}
);
}
Add New Component Types Create a trait for reusable component logic:
trait DynamicComponentTrait
{
public function getDynamicData()
{
return $this->fetchFromDatabaseOrCache();
}
}
Use it in controllers:
class MyComponentController extends ApiComponentController
{
use DynamicComponentTrait;
// ...
}
Hook into the Bundle’s Lifecycle
How can I help you explore Laravel packages today?