phpro / soap-client

A general purpose SOAP client for PHP
MIT License
862 stars 175 forks source link

Can't instantiate custom type for GUIDs #531

Closed LazyTechwork closed 2 months ago

LazyTechwork commented 4 months ago
Q A
Version 4.0.0

Support Question

Hello. I have some problem with custom data types. I created a type encoder and also added type replacer. However, the generator gives me this type as a converted name in my namespace. I am using ramsey's uuid library and wanna use UuidInterface for GUIDs. Here's a code:

class GuidEncoder implements XmlEncoder
{
    public function iso(Context $context): Iso
    {
        return new Iso(
            fn (UuidInterface $value): string => $value->toString(),
            static fn (string $value): UuidInterface => Guid::fromString($value)
        );
    }
}
class GuidTypeReplacer implements TypeReplacer
{
    public function __invoke(XsdType $xsdType): XsdType
    {
        $check = new IsOfType('http://microsoft.com/wsdl/types/', 'guid');

        if (!$check($xsdType)) {
            return $xsdType;
        }

        return $xsdType->copy('guid')->withBaseType(UuidInterface::class);
    }
}

In code generation config:

->setTypeReplacementStrategy(
    TypeReplacers::defaults()
        ->add(new GuidTypeReplacer())
)

And in ClientFactory:

->addComplexTypeConverter(
    'http://microsoft.com/wsdl/types/',
    'guid',
    new GuidEncoder()
)

So, the result of code generation is:

/**
 * @var \LazyTechwork\MyClient\Types\RamseyUuidUuidInterface
 */
private \LazyTechwork\MyClient\Types\RamseyUuidUuidInterface $ID;

instead of:

/**
 * @var \Ramsey\Uuid\UuidInterface
 */
private \Ramsey\Uuid\UuidInterface $ID;

Can you help me deal with this problem?

veewee commented 4 months ago

Hello @LazyTechwork,

Thanks for trying it v4 out and reporting this issue.

At the moment, Adding types from a different PHP namespace than the once where the types are generated (or PHP's built-in types) is not supported yet. I'll have to take a look at how it can be implemented.

In the meantime, you could add a smalle Guid wrapper-class in the folder where the types are generated. Something like:

class Guid 
{
     private UuidInterface $id;

    // And also fromString and toString
}

That way you can use it as you'dd expect.

Given the XML contains a simple XML string, you'dd probably need to change the ClientFactory to use a simple type instead of a complex type:

- ->addComplexTypeConverter(
+ ->addSimpleTypeConverter(
    'http://microsoft.com/wsdl/types/',
    'guid',
    new GuidEncoder()
)
LazyTechwork commented 4 months ago

It's a bit disappointing that some custom types aren't currently supported and we need to write a wrapper to work with them. However, I did try the method you suggested and the types worked as expected. Thanks a lot for your help! I truly hope that adding support for custom types will be added to the priority list for future updates.

veewee commented 4 months ago

Hello,

It's a bit disappointing that some custom types aren't currently supported

You are using an early alpha release that introduced this feature. The goal of this release is to get feedback like yours.

The type replacer feature was recently added to solve some other issues and wasn't really designed to do these kind of replacements. But I do recon this is how people would expect to use it. So we need to make code generation smart enough to deal with this.

I truly hope that adding support for custom types will be added to the priority list for future updates.

No worries, it will probably be covered by this package some day. In the meantime, you can use the workaround as described above to overcome your problem until there is a better solution.

Want to speed things up? Find out how you can help out!

veewee commented 2 months ago

Duplicate of #543, closing this for now but will pick it up in there!