jailtonsc/laravel-response-xml
composer require jailtonsc/laravel-response-xml
config/app.php:
'providers' => [
// ...
XmlResponse\XmlResponseServiceProvider::class,
],
'aliases' => [
'Xml' => XmlResponse\Facades\XmlFacade::class,
]
php artisan vendor:publish --provider="XmlResponse\XmlResponseServiceProvider"
Replace a JSON response with XML in a controller or route:
Route::get('/users', function () {
return response()->xml(User::all()); // Auto-converts Eloquent collection to XML
});
Xml::asXml($data) for direct XML string conversion.response()->xml($data, $status, $config) for HTTP responses.config/xml.php for customizing root tags, row names, and formatting.API Responses:
// Controller
public function index() {
return response()->xml(User::paginate(10), 200, [
'root' => 'users',
'row' => 'user'
]);
}
Direct XML Generation:
$xmlString = Xml::asXml(Order::with('items')->find(1));
Dynamic Configuration:
$config = config('xml.defaults');
$config['rowName'] = 'record';
return response()->xml(Post::all(), 200, $config);
public function handle($request, Closure $next) {
if ($request->wantsXml()) {
$response = $next($request);
return response()->xml($response->getContent(), $response->status());
}
return $next($request);
}
Illuminate\Foundation\Http\FormRequest to support XML:
public function response(array $data) {
return response()->xml($data);
}
$this->get('/api/users')
->assertHeader('Content-Type', 'application/xml')
->assertSee('<users>');
| Scenario | Implementation |
|---|---|
| Pagination | response()->xml(User::paginate(5)) |
| Single Resource | response()->xml(User::find(1)) |
| Custom Root Tag | response()->xml($data, 200, ['root' => 'custom_root']) |
| Nested Relationships | Auto-handled by package (e.g., User::with('posts')->find(1)) |
Nested Relationships:
User->posts->author->posts) may cause infinite loops. Use ->with() selectively or exclude problematic relations:
User::with(['posts' => function($q) {
$q->where('published', true);
}])->find(1);
Config Overrides:
config/xml.php) may be overridden by inline config, but inline config takes precedence. Test edge cases:
// Overrides global 'root' and 'row' settings
response()->xml($data, 200, ['root' => 'override_root']);
Non-Eloquent Data:
// Explicitly define structure
$config = [
'template' => '<response><items>{items}</items></response>',
'rowName' => 'item'
];
response()->xml(['items' => [1, 2, 3]], 200, $config);
Performance:
$xml = Xml::asXml(User::chunk(100, function($users) {
// Process chunks
}));
Xml::asXml($data) to inspect raw XML before returning a response. Tools like XMLLint can validate the output.Content-Type: application/xml is set. If missing, manually add:
return response()->xml($data)->header('Content-Type', 'application/xml');
\Log::debug('XML Config:', [
'global' => config('xml'),
'inline' => $config
]);
Custom Templates:
Extend the package by publishing and modifying the resources/views/xml templates:
php artisan vendor:publish --tag=xml-views
Then override xml/response.blade.php or xml/collection.blade.php.
Macro Extensions:
Add custom macros to the response object in a service provider:
Response::macro('xmlWithMeta', function ($data, $status = 200) {
$xml = $this->xml($data, $status);
return $xml->withMeta(['count' => count($data)]);
});
Event Listeners:
Listen for XmlResponseGenerating events to modify XML generation:
Event::listen('XmlResponseGenerating', function ($event) {
$event->xml->setAttribute('version', '1.0');
});
root and rowName in config to match common XML conventions:
['root' => 'api-users', 'rowName' => 'user']
api-version middleware to support both XML and JSON:
if ($request->wantsXml()) {
return response()->xml($data)->header('X-API-Version', 'v1');
}
Xml::asXml().How can I help you explore Laravel packages today?