Weave 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

Laravel Xml Laravel Package

bmatovu/laravel-xml

A Laravel package for working with XML. It converts XML requests and responses into arrays, adds XML response helpers and middleware, and lets your APIs accept and return XML alongside JSON, with configurable parsing and validation support.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require bmatovu/laravel-xml

Before you run that, check the support matrix — as of v4.2.0 the package requires PHP 8.2+ and Laravel 12/13. Laravel 10/11 and PHP 8.1 were dropped in that release, so:

composer require bmatovu/laravel-xml:^4.2   # PHP 8.2+, Laravel 12/13
# apps still on Laravel 10/11 or PHP 8.1 are pinned to ^4.1 and no longer receive fixes

If composer require resolves to 4.1.x on your machine, that is the signal your PHP/Laravel combination is below the new floor — confirm with composer why-not bmatovu/laravel-xml 4.2.0 before assuming the package is at fault.

Laravel auto-discovers Bmatovu\LaravelXml\XmlServiceProvider. On older Laravel versions, add the provider to config/app.php. If the package ships a config file, publish it before you need it:

php artisan vendor:publish --provider="Bmatovu\LaravelXml\XmlServiceProvider"

Where to look first

  1. vendor/bmatovu/laravel-xml/README.md — the API surface is small enough to read in five minutes.
  2. The service provider — it is the source of truth for which macros (response()->xml(), $request->xml(), etc.) and middleware actually exist in your pinned version.
  3. The middleware class (typically ParseXml) — this is where incoming XML is turned into request input, and where most surprises live.

First use case: XML out

Add a response to an existing controller without touching your models:

Route::get('/users', fn () => response()->xml(User::all()->toArray()));

First use case: XML in

Register the parse middleware for the route group that speaks XML, then consume the request like any other:

Route::middleware(\Bmatovu\LaravelXml\Middleware\ParseXml::class)->group(function () {
    Route::post('/users', [UserController::class, 'store']);
});

If $request->all() is populated (not just the raw body from getContent()), the middleware ran and did its job.

Implementation Patterns

Response macro from controllers and resources. The lowest-friction pattern is wrapping your existing array output: response()->xml(['users' => $users]). Keep the array shaping in a Resource or a toXml()/toArray() method so JSON and XML endpoints share one data source. Repeated elements need an explicit wrapper key (['user' => $users]) — an array of scalars does not automatically become repeated <user> nodes in most array-to-XML implementations.

Content negotiation. Don't duplicate routes. Inspect $request->header('Accept') (or a ?format=xml query param) and branch:

return $request->wantsXml()
    ? response()->xml($payload)
    : response()->json($payload);

This keeps one controller and one test suite.

Reuse validation untouched. The main benefit of the parse middleware is that incoming XML becomes normal request input, so FormRequest, $request->validate(), and $request->only() all work unchanged. That means your day-to-day workflow is: enable middleware on the XML route group → write validation exactly as you would for JSON → forget XML exists.

Testing. Assert the header, then parse the body rather than string-matching:

$response->assertHeader('Content-Type', 'application/xml');
$xml = simplexml_load_string($response->getContent());
$this->assertSame('Jane', (string) $xml->user->name);

For inbound tests, use $this->call('POST', $uri, [], [], [], ['CONTENT_TYPE' => 'application/xml'], $xmlString); $this->post() with an array will be encoded as form data, not XML.

Integration tip. Put the parse middleware on a dedicated route group (or a named xml middleware group) rather than globally. Global registration forces every JSON and file-upload request through an XML sniff, and the ordering relative to TrimStrings / ConvertEmptyStringsToNull becomes something you have to reason about.

Upgrading to 4.2.0. The 4.1 → 4.2 diff is version floors and CI plumbing, not behaviour — no API removal, no macro or middleware rename. In practice the upgrade is: bump PHP to 8.2 if you haven't, make sure your Laravel constraint allows 12/13, composer update bmatovu/laravel-xml, then re-run your XML output-shape tests. If your app is on Laravel 10/11, plan the framework upgrade first; there is no XML work involved.

Gotchas and Tips

  • Support matrix is now the constraint that bites. 4.2.0 requires PHP 8.2+ / Laravel 12–13. Since Laravel 12/13 are the only supported targets, you effectively cannot stay on the package long-term without keeping the framework current. If you're mid-migration, pin ^4.1 deliberately and write the removal ticket the same day.
  • Everything is a string. Numbers, booleans, and nulls round-trip as text. Consumers must cast; don't ship "1"/"true" where the contract says integer/boolean without documenting it.
  • Attributes are a convention, not a feature. Array-based builders typically use '@attributes' => [...]; if the package doesn't, you'll need to fall back to raw SimpleXMLElement for anything with attributes, namespaces, or CDATA. Don't promise a schema you can't produce.
  • XXE. If the middleware parses with simplexml_load_string without LIBXML_NONET and with entity loading enabled, a malicious body is a real risk. Check the middleware source once and harden or fork if necessary — this is the single most important thing to verify in a low-adoption package. Note that a CI/Dependabot-green release like 4.2.0 says nothing about parser hardening; diff the middleware yourself.
  • Content-Type detection is brittle. Many clients send text/xml, none at all, or application/xml; charset=utf-8. If the middleware only triggers on an exact match, requests silently bypass parsing and $request->all() comes back empty. Log or dd($request->getContent(), $request->all()) when debugging.
  • Empty collections. [] may serialize to <items/> or be omitted entirely depending on the underlying builder; decide and test it, because it's the kind of thing that breaks a consumer's parser in production.
  • Middleware ordering. Register the parser early (mirroring how Laravel's own TransformsRequest sits in the global stack). Later registration means other middleware sees an unparsed body.
  • Macro collisions and Octane. response()->xml() is a macro registered at boot. It's fine under Octane, but if you define your own xml macro for another purpose you'll get a confusing overwrite. Grep before adding.
  • Adoption risk. A small star count and no known dependents means you are one of the few people exercising this code. Pin the exact version in composer.json, add a test that asserts your XML output shape, and accept that the escape hatch is ~30 lines: spatie/array-to-xml for output plus a small request macro for input. Keeping your XML shaping in one Resource method makes that swap cheap.
  • Changelog lives upstream. The compare link in the release notes points at mtvbrianking/laravel-xml, not the bmatovu namespace you installed. That's the same code lineage, but it means release notes aren't where you'd instinctively look — subscribe to the upstream repo's releases or you'll miss the next floor bump the way you may have missed this one.
  • Escape hatch for hard cases. When arrays stop being enough (attributes, mixed content, namespaces), build the SimpleXMLElement yourself and return it with an explicit Content-Type header. Don't contort the array convention.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core