Skip to content

[ObjectMapper] Add possibility to map multiple objects at once #60518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
markwatney2016 opened this issue May 23, 2025 · 1 comment · May be fixed by #60615
Open

[ObjectMapper] Add possibility to map multiple objects at once #60518

markwatney2016 opened this issue May 23, 2025 · 1 comment · May be fixed by #60615

Comments

@markwatney2016
Copy link

markwatney2016 commented May 23, 2025

Description

Having a method like mapMultiple() alongside map() would be very convenient. AutoMapper+ seems to have such a method: https://github.com/mark-gerarts/automapper-plus?tab=readme-ov-file#using-the-automapper

@makomweb
Copy link

makomweb commented May 26, 2025

A potential solution could look like this.

<?php

namespace MyProject\Tests;

use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\ObjectMapper\ObjectMapper;

final class MapMultipleTest extends TestCase
{
    public function testMapCollection(): void
    {
        $source = [
            new MyUserSource(
                firstName: 'foo',
                lastName: 'bar',
                email: 'foo@bar.com'
            ),
            new MyUserSource(
                firstName: 'abc',
                lastName: 'xyz',
                email: 'abc@xyz.com'
            ),
        ];

        $target = self::mapCollection($source, MyUserTarget::class);

        self::assertIsArray($target);
        self::assertSameObjectType($target);
        self::assertCount(2, $target);
        self::assertInstanceOf(MyUserTarget::class, $target[0]);
    }

    private static function mapCollection(array $collection, string $targetType): array
    {
        self::assertSameObjectType($collection);

        $mapper = new ObjectMapper();

        return array_map(
            static fn (object $src) => $mapper->map($src, $targetType),
            $collection
        );
    }

    /**
     * Asserts that all elements in the array are objects of the same class.
     *
     * @param object[] $objects
     * @throws InvalidArgumentException if not all objects are of the same class
     */
    private static function assertSameObjectType(array $objects): void
    {
        if (empty($objects)) {
            throw new InvalidArgumentException("Array is empty.");
        }

        $firstClass = get_class(reset($objects));

        foreach ($objects as $index => $object) {
            if (!is_object($object)) {
                throw new InvalidArgumentException(sprintf('Element at index %d is not an object.', $index));
            }

            if (get_class($object) !== $firstClass) {
                throw new InvalidArgumentException(sprintf(
                    'Type mismatch at index %d: expected instance of %s, got %s.',
                    $index,
                    $firstClass,
                    get_class($object)
                ));
            }
        }
    }
}

final readonly class MyUserSource {
    public function __construct(
        public string $firstName,
        public string $lastName,
        public string $email,
    ) {  
    }
}

final readonly class MyUserTarget {
    public function __construct(
        public string $firstName,
        public string $lastName,
        public string $email,
    ) {  
    }
}

@makomweb makomweb linked a pull request Jun 1, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants