3

i have a rest api request response in this form

{
    "first_field": null,
    "elements": [
        {
            "type": "type_1",
            "quantity": 234
        },
        {
            "type": "type_2",
            "quantity": 432
        },
        {
            "type": "type_3",
            "quantity": 112
        },
        {
            "type": "type_4",
            "quantity": 212
        }
    ],
    "third_field": {
        "option1": value1,
        "option2": "value2",
        "option3": "value3",
        "option4": "value4"
    }
}

I would like to pass it to a constructor to create an object. I thought to use the Symfony4 OptionsResolver to configure it.

Dummy and incomplete example

    class Status{

      public function __construct(array $options){
        $resolver = new OptionsResolver();
        $this->configureOptions($resolver);

        $this->options = $resolver->resolve($options);
        $this->init();
      }

     protected function init(){
       foreach($this->options['elements'] as $element){
         switch($element['type']){
           case 'type_1'
             $this->type1 = $element['quantity'];
             break;
           // And so on
         }
       }
     }

    }

How can i define in OptionsResolver the elements array? For third field the solution is the nested options, but it is an array of options, not an array of array of options...

Thanks in advance

EDIT To instantiate a new object from a Json Object a fine solution can be the karriere/json-decoder

1 Answer 1

3

If someone still needs a way to do that, here is a possible implementation

<?php

class Status
{
    public function __construct(array $options)
    {
        $resolver = new OptionsResolver();
        $this->configureOptions($resolver);

        $this->options = $resolver->resolve($options);
        $this->init();
    }

    protected function init()
    {
        foreach($this->options['elements'] as $element) {
            switch($element['type']) {
                case 'type_1':
                    $this->type1 = $element['quantity'];
                    break;
                // And so on
            }
        }
    }

    private function configureOptions(OptionsResolver $resolver)
    {
        $resolver->define('elements')
            ->allowedTypes('array[]')
            ->allowedValues(static function (array &$elements): bool {
                $subResolver = new OptionsResolver();

                $subResolver->define('type')
                    ->required()
                    ->allowedTypes('string');

                $subResolver->define('quantity')
                    ->required()
                    ->allowedTypes('int');

                // Trick is here: use array_map to resolve each elements one by one.
                $elements = array_map([$subResolver, 'resolve'], $elements);
                return true;
            });
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.