doctrine/oxm
Doctrine OXM (Object XML Mapper) maps PHP objects to XML documents and back using Doctrine-style metadata. Useful for XML serialization/deserialization in domain models, with mapping drivers and runtime tools to integrate XML workflows into applications.
Installation Add the package via Composer:
composer require doctrine/oxm
Ensure doctrine/orm is also installed (OXM relies on Doctrine ORM components):
composer require doctrine/orm
Basic Setup
Configure OXM in config/doctrine.php (or create it if missing):
'orm' => [
'entity_managers' => [
'default' => [
'mappings' => [
'App\\Models' => [
'type' => 'xml',
'dir' => base_path('app/Models'),
'prefix' => 'App\\Models',
'is_bundle' => false,
],
],
],
],
],
First Use Case: Mapping a Model to XML Annotate a Laravel model with OXM attributes:
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ODM\XMLMapping\Mapping\Driver\AnnotationDriver;
/**
* @ORM\Entity
* @ORM\Table(name="users")
* @ORM\XmlRoot(name="user")
*/
class User extends Model
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\XmlId
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\Column(type="string")
* @ORM\XmlElement
*/
protected $name;
}
Generate XML Schema Use the CLI to generate XML schema from annotations:
php artisan doctrine:schema:update --force
Or manually generate XML mapping files:
vendor/bin/doctrine-mapping-import --path=src/ --output-dir=config/doctrine/xml
CRUD Operations with XML
Use Doctrine's EntityManager to read/write XML:
$em = Doctrine::em();
$user = $em->find('App\Models\User', 1);
$xml = $em->getXMLMapping()->getClassMetadata('App\Models\User')->getXMLSchema();
Bulk XML Export/Import Iterate over collections and serialize to XML:
$users = User::all();
$xml = new \SimpleXMLElement('<users/>');
foreach ($users as $user) {
$userXml = $em->getXMLMapping()->getClassMetadata('App\Models\User')->getXMLSchema();
$xml->addChild('user', $userXml->asXML());
}
Integration with Laravel Events
Trigger XML export on model events (e.g., saved):
User::saved(function ($user) {
$xml = $user->toXml(); // Custom method to serialize
Storage::put("users/{$user->id}.xml", $xml);
});
Doctrine\ODM\XMLMapping\Hydrator\ObjectHydrator for complex mappings.return response($user->toXml(), 200, ['Content-Type' => 'application/xml']);
Annotation vs. XML Mapping
@ORM\Xml*), but conflicts may arise with Doctrine ORM annotations. Ensure consistency:
// Avoid mixing:
@ORM\Column(type="string") // ORM
@ORM\XmlElement(cdata=false) // OXM
Circular References
Bidirectional relationships (e.g., User <-> Role) may cause infinite XML loops. Use @ORM\XmlInverseJoinColumn or lazy-loading:
/**
* @ORM\ManyToMany(targetEntity="Role")
* @ORM\XmlElement
* @ORM\XmlInverseJoinColumn
*/
private $roles;
Namespace Collisions XML namespaces in generated schemas may clash. Explicitly define namespaces in annotations:
@ORM\XmlRoot(namespace="http://example.com/ns")
vendor/bin/doctrine-mapping-import --validate to check for errors.config/doctrine.php:
'logging' => true,
'log_level' => \Doctrine\Common\Logging\LogLevel::DEBUG,
$metadata = $em->getClassMetadata('App\Models\User');
$xmlSchema = $metadata->getXMLSchema();
file_put_contents('debug.xml', $xmlSchema->asXML());
Custom Drivers
Implement Doctrine\Common\Persistence\Mapping\Driver\MappingDriverInterface for non-annotation-based mappings (e.g., YAML).
Event Subscribers
Listen to onFlush or postPersist to modify XML output dynamically:
$em->getEventManager()->addEventSubscriber(new class {
public function postPersist(LifecycleEventArgs $args) {
$entity = $args->getObject();
if ($entity instanceof User) {
$entity->setXmlAttribute('exported_at', now()->toAtomString());
}
}
});
Laravel Service Provider
Bootstrap OXM in AppServiceProvider:
public function boot() {
$this->app->singleton('doctrine.em', function () {
$config = config('doctrine.orm.entity_managers.default');
$em = EntityManager::create($config['connection'], $config['mappings']);
return $em;
});
}
How can I help you explore Laravel packages today?