Skip to content
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

[PHP] Fix array handling #2726

Merged
merged 4 commits into from
May 6, 2016
Merged

[PHP] Fix array handling #2726

merged 4 commits into from
May 6, 2016

Conversation

arnested
Copy link
Contributor

This is an attempt at solving #2625.

The problem is we don't handle models defined as arrays correct in (at least) two different ways:

  • We generate invalid PHP. The following definition:
 "error-parameters": {
      "type": "array",
      "description": "Error parameters list",
      "items": {
        "$ref": "#/definitions/error-parameters-item"
      }
    },

is turned into:

class ErrorParameters extends array<ErrorParametersItem> implements ArrayAccess {
  • We don't implement a correct ArrayAccess interface. It can't be used as a traditional "append to indexed array"
$array[] = $var;

It will only work with associative arrays. Which is fine for all other models but arrays.

For now this pull request is just for gathering feedback on different ways of solving this -- because I'm not sure the current approach is the best.

Feedback is appreciated.

Invalid PHP

The problem comes from the fact that DefaultCodegen.java adds the parent variable to for arrays (line 2194 as well as for objects inheriting from a parent (line 969).

The solution I've tried here (bbe12c1) is using the parentSchema variable for testing whether a parent object exists as parentSchema is only added when inheriting from another object and not when we have an array.

I'm not particular satisfied with this approach. Mostly because I'm not sure of the semantic meaning of parentSchema. I just used it because the code tells me it will be set in the right cases. And then it looks odd to do testing on parentSchema and the outputing parent.

Another approach would be to add an isListContainer property to CodegenModel and use that combined with the parent variable to decide if this is an array or object inheritance.

ArrayAccess interface implementation

To fix the ArrayAccess interface implementation (9f40a82) I had to move all properties into of a model object into a single $container associative array.

I'm not particular satisfied with this approach either. Mostly because I don't like to refactor the internals of all models "just" for getting arrays working. And it makes it more difficult to figure out which type each property is (at least if thinking forward to PHP 7 and type hinting).

A positive side effect of this is that it will avoid bugs if someone decided to introduce a property named i.e. attributeMap in their Swagger model as that would collide with our use of the static property $attributeMap.

A lot of these problems originates from trying to fit everything into one model.mustache template. So another approach would be to use @wing328's approach in #2508 and split the template into several templates. That would require adding the isListContainer property mention above as well.

Looking into this a question popped into my head. Why do we implement ArrayAccess for regular model objects at all? What is the use case for this except providing a way to avoid using the setters and gettes 😄

Tests

I added a test case testing whether arrays works as expected (7f99469).

The current pull request passes this test case and the existing ones as well (I have setup automatic test of the PHP tests for branches on my fork at: https://circleci.com/gh/arnested/swagger-codegen/47).

Test if we implement the ArrayAccess interface correct on out model objects.
`parent` in a model is set not only when the model inherits from another
model but also when a parent container exists.

So We will now use `parentSchema` to check whether a parent class
exists. If si we still use `parent` to output the class name because
that has been converted to a proper model name and `parentSchema`
hasn't.
The models didn't implement a generally working ArrayAccess
interface. This would fail on list container types (array).

This commit refactors some internals of the model object. The model
properties are no longer stored as separate properties on the PHP object
but as entries in a `$container` property.

This is needed to make the model work also for list containers. Besides
it avoids potential problems where the model would specify property
names that could collide with names used by the Swagger model
implementation itself (i.e. `$attributeMap`).
@wing328
Copy link
Contributor

wing328 commented Apr 28, 2016

Looking into this a question popped into my head. Why do we implement ArrayAccess for regular model objects at all? What is the use case for this except providing a way to avoid using the setters and gettes 😄

I didn't have an answer either as I'm not the one adding it.

I think it's a good time to rethink again whether we need to implement ArrayAccess for regular model and I don't mind if it's break change (non-backward compatible) if we've a good reason not to implement it.

@wing328
Copy link
Contributor

wing328 commented Apr 29, 2016

Re: ArrayAccess

I found that stripe-php and google-api-client-php also implements ArrayAccess in their base model:

https://github.com/google/google-api-php-client/blob/998067619ce59a849948b0a8647499b90f70ab41/src/Google/Model.php

https://github.com/stripe/stripe-php/blob/6806fb201dbd545053bf553abca0cad9bb454f92/lib/StripeObject.php

My take is to keep it for now unless it's causing issue.

@wing328
Copy link
Contributor

wing328 commented May 2, 2016

@arnested I'll review this by coming Wed.

@wing328 wing328 merged commit 5d57bb1 into swagger-api:master May 6, 2016
@wing328
Copy link
Contributor

wing328 commented May 6, 2016

@arnested Changes merged into master. Thanks for the fix.

@wing328
Copy link
Contributor

wing328 commented May 6, 2016

@arnested as part of the merge, I resolved the conflicts due to better enum support PR. If you've time, I wonder if you can take a look at the latest master to ensure it looks good from your perspective.

@arnested arnested deleted the php-fix-array-handling branch May 6, 2016 21:47
@arnested
Copy link
Contributor Author

arnested commented May 6, 2016

The merge was fine.

I discovered a minor flaw though when using derived classes (default values from the superclass would not work and a lot of PHP notices would occur when using properties from the superclass as well).

A fix and a test is present in #2793.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants