Skip to content

[BUG]: generated php code is re-declaring functions on global level #2843

@PssbleTrngle

Description

@PssbleTrngle

when having multiple properties with "type": "object", quicktype will generate PHP code with local from() and to() functions. Since the function always lives in the global scope in PHP, calling this twice will throw a redeclaration exception.

Issue Type

output

Context (Environment, Version, Language)

Input Format: JSON Schema
Output Language: PHP

CLI, npm, or app.quicktype.io:
Version: npm@10.9.3

Description

When generating a PHP file from a JSON Schema, that contains two properties with simply the type object, but not defined properties, quicktype does not generate a class for them but simply inline the generated from() and to() functions within the block to directly call them afterwards.

Since in PHP the function keyword always creates a function on the global (or namespace) scope, calling either of these "wrapping" functions that define the from() function twice, or simply ones for two properties will fail with Cannot redeclare to().

You probably expected that the defined function to() does only live within the scope of the parent function it's defined in, as is the case in a lot of language, but this is not how it works in PHP. It works more similar to how the var keyword works in JavaScript.

Instead of inlining these named function from and to here, only to call them directly afterwards, it would make more sense (and actually work without throwing an error) to directly create the \stdClass here and return it.
An example of how this would look like has been provided under "Expected Behaviour/Output".

Input Data

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "type": "object",
  "properties": {
    "a": {
      "type": "object"
    },
    "b": {
      "type": "object"
    }
  }
}

Expected Behaviour / Output

Not defining the function from here, since it does not as you probably expected only live

/**
     * @throws Exception
     * @return ?stdClass
     */
    public function toB(): ?stdClass {
        if (Coordinate::validateB($this->b))  {
            if (!is_null($this->b)) {
                $out = new stdClass();
                foreach ($my as $k => $v) {
                    $my->$k = $v; /*any*/
                }
                return $out;
            } else {
                return  null;
            }
        }
        throw new Exception('never get to this Coordinate::b');
    }

Current Behaviour / Output

/**
     * @throws Exception
     * @return ?stdClass
     */
    public function toB(): ?stdClass {
        if (Coordinate::validateB($this->b))  {
            if (!is_null($this->b)) {
                function to($my): stdClass {
                    $out = new stdClass();
                    foreach ($my as $k => $v) {
                        $my->$k = $v; /*any*/
                    }
                    return $out;
                }
                return to($this->b);
            } else {
                return  null;
            }
        }
        throw new Exception('never get to this Coordinate::b');
    }

Steps to Reproduce

  1. copy-paste the provided schema into the generator
  2. select json-schema input and php output
  3. execute the to() function, which will call the toA() and toB() functions
  4. get thrown Fatal error: Cannot redeclare to()

Possible Solution

Generate something like the example given in "Expected Behaviour/Output"

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions