0

I want to override a class from the JMS/serializer bundle. Unfortunately this class is marked "final" and I can't override it. What would be the best method to circumvent this problem please? I'm on symfony5.4

Here is the class I want to override :

<?php

declare(strict_types=1);

namespace JMS\Serializer\Handler;

use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\Serializer\XmlSerializationVisitor;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface as TranslatorContract;

use function get_class;

 final class FormErrorHandler implements SubscribingHandlerInterface
{
    /**
     * @var TranslatorInterface|null
     */
    private $translator;

    /**
     * @var string
     */
    private $translationDomain;
oracle972
  • 77
  • 10
  • You don't. That is the meaning of final. – Markus Zeller Nov 07 '22 at 08:42
  • https://stackoverflow.com/questions/13294629/how-to-extend-a-final-class-in-java – Markus Zeller Nov 07 '22 at 08:47
  • You may want to use a [composite pattern](https://en.wikipedia.org/wiki/Composite_pattern) – Cid Nov 07 '22 at 08:51
  • @MarkusZeller thank you for your answer, unfortunately this class was not marked "final" before and I had overrided this class. Now that I've upgraded the bundle, my override no longer works and my app crashes. – oracle972 Nov 07 '22 at 09:01
  • Why do you want to extend it? Usually, you should decorate it nowadays – Nico Haase Nov 07 '22 at 09:21
  • @NicoHaase the problem is that when I create the decorator, the formErrorHandler class of the fosRestBundle expects to receive a class from the type JMS/FormErrorHandler and not from my decorator – oracle972 Nov 07 '22 at 09:48

2 Answers2

1

The short answer is that you can not override the final classes as long as the package author does not provide a functionality to replace the final class with a custom implmentation.

by taking a look at the source code of the package, you can do so. the SerializeBuilder constructor is something like:

public function __construct(?HandlerRegistryInterface $handlerRegistry = null, ?EventDispatcherInterface $eventDispatcher = null)

which clearly means that you can add your custom handler.

and due to the documentation you can implement your own handler easily.

$builder
    ->configureHandlers(function(JMS\Serializer\Handler\HandlerRegistry $registry) {
        $registry->registerSubscribingHandler(new MyHandler());
    })
;
hassan
  • 7,812
  • 2
  • 25
  • 36
  • hello @hassan I want to override FormErrorHandler class from JMS bundle. This class is used directly in the FormErroHandler class of the FOS/RestBundle. When I create a custom class like in your example, I get an error like: FOS/restBundle expects an instance of JMS/FormErrorHandler , Custom class Given – oracle972 Nov 07 '22 at 09:52
  • can you give an example of how you implement the RestBundle? from what I can see RestBundle is relying on HandlerRegistryInterface, which means that you can easily use your custom implementation, you will need to implement the same interface too to be accepted by RestBundle – hassan Nov 07 '22 at 10:05
  • I didn't modify the RESTBundle, I only override the FormErrorHandler class from the JMS bundle – oracle972 Nov 07 '22 at 10:12
  • I know, I mean you need to share how do you use RestBundle in your code, however, the point is that you can extend the functionality of RestBundle too – hassan Nov 07 '22 at 10:13
  • I use the restBundle in a rather classic way. I installed the bundle and added the annotations on my classes. Then when an error occurs, the fos bundle creates an error response. I don't know what else to tell you. You think I can directly override the FormErrorHandler class from FOSBundle without using the class from JMS? – oracle972 Nov 07 '22 at 10:21
  • You can inject your own Handler to RestBundle, can you check this? https://fosrestbundle.readthedocs.io/en/3.x/4-exception-controller-support.html?highlight=Serializer – hassan Nov 07 '22 at 11:24
  • I finally found a solution. I overridden the FormErrorHandler class from FOS/SerializerbUndle and then I overridden the formErrorHandlere class from JMS which I call in my overload of FOS/FormErrorHandler – oracle972 Nov 07 '22 at 16:35
  • do you mean by overriding that you edited the code within the package itself? – hassan Nov 08 '22 at 10:18
  • no of course, I recreated the FOS/FormErrorHandler class in my application. I don't know the exact term in English – oracle972 Nov 08 '22 at 10:59
  • 1
    OK great, that's whatt I was talking about in my submitted solution, to implement the custom handler by your self – hassan Nov 08 '22 at 11:49
0

I finally found a solution. I overridden the FormErrorHandler class from FOS/SerializerbUndle and then I overridden the formErrorHandlere class from JMS which I call in my overload of FOS/FormErrorHandler. it works perfectly

oracle972
  • 77
  • 10