-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add support for inherited nullability from PHP #11814
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
base: 3.6.x
Are you sure you want to change the base?
Conversation
61b1134 to
80d2ee7
Compare
derrabus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've limited inferring nullability to attribute mapping while type inference works with any driver. Why's that?
It seemed like easier option to start with, and I didn't know codebase very well yesterday, now I see that I can do it maybe in |
af3f9cb to
b92befd
Compare
|
I did a rewrite and now it's working for all drivers via Btw in next major version, this could be the default behavior. Now I noticed I selected wrong target branch, because I noticed one bug with default referenced column name and found out it was fixed and there is already 3.4.x branch.. I'll look at it in a few hours and I will switch it. |
23c1c5d to
1795e61
Compare
|
I rebased it onto 3.4.x, it's ready for review, one thing I'm not sure about is to how to treat variables without type, I think it will be better to have them nullable (JoinColumn already is, but Column isn't) when using For now, I left it how it was, but it's more consistent to have them both nullable when using this setting, I don't use untyped properties so I don't mind, but it's a thing to consider and it will be difficult to change it in the future without BC break. |
If there's no type, there's nothing we could infer nullability from. The old defaults are good for those cases. |
That's also my reasoning why I didn't added it in a first place, but then I started doubting it, since it's named as I like the error-prevention of that nullability, because if DB schema is up to date with code, and no |
307736e to
88d2d2d
Compare
|
I would like to prepare PR for phpstan/phpstan-doctrine, so it can read the config ang figure out how to check nullable types, but I don't know if this naming is ok, and if it gets into the 3.4 release. @derrabus do you think I should change it from |
Can I somehow help with that? Are those implications related to the virtual creation of join column? I'm already using this PR on a few projects, so far I didn't have any problems, it completely eliminated need for |
|
Hello, just a friendly reminder since it's been some time, it would be really awesome if this could get to 3.4 release. |
|
I see two problems with this:
So
Therefore I would like to see this limited to only fields and not to associations and only to set nullable=true if allowsNull=true. And there must be a special case for 'id' fields where it does not infer this automatically. |
Sorry, I'm going to release 3.4. Don't get disheartened though, we have already stuff we want to have in 3.5, so it should be released soon after 3.4. |
Well, if you don't access that property, it does not need to be null, I'm using auto-increment and I have all my IDs non-nullable in code and in database, and when I was using UUID, I also didn't have it nullable, because I configured it when constructing entity. If such a case exists and someone want to access uninitialized property, nullability can be always set: #[Id, Column(nullable: false)]
private ?int $id;So I would rather keep it consistent and inherit that nullability, or maybe I don't quite get why would it need to be nullable in code in the first place, I have never had such case. But I guess it's not a problem to make exception for
Can you give me example what code could cause the error? I have multiple one to one associations and so far I didn't encountered an error, some of them are nullable and some of them are not, but I have only 1 bidirectional. I would argue that it can also happen now when someone declares It's also made as opt-in feature via
No problem, just let me know if there will be another branch so I can rebase. |
|
There is another branch already, 3.5.x ;) |
d13cb66 to
50e693d
Compare
|
@beberlei I have implemented an exception for ID columns (also covered by tests), even though I don't think it's a good idea to introduce inconsistent behavior and encourage having Also, have you changed your mind about this feature in associations? You pointed out some bidirectional issues, but I think such cases could be handled with If you're still against it, I would like to suggest two separate booleans: one for regular fields and one for association columns, so it would look like |
The uninitialized state is a footgun. Benjamin is right, we have to allow auto-increment ID fields to be nullable without mapping them to nullable fields in the schema. |
Ok, just to be clear, it was allowed, but it had to be overwritten via |
|
@greg0ire @SenseException I'm going to do a rebase, but I'm unsure how to proceed because of possible BC break related to #12108, there was a short discussion satarted by @morozov #12108 (comment), similar thing was mentioned by @derrabus here, so I added new property I don't know if I should keep this With Btw. could this be please added to 3.6.0 milestone so it's not forgotten? |
|
There hasn't been any activity on this pull request in the past 90 days, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 7 days. |
|
Hello, I would really appreciate it if someone could reply. I mentioned multiple people who know what’s going on, and I even asked about it on Slack two months ago, but I got no reply. Because of that small BC break #12108 where So now I think I should keep But what about This way public property If no one answers by the end of the week, I'm keeping |
|
So I rebased it as I said and tested it in my project (works the same), failed pipeline seems unrelated (it's failed also in 3.6.x). Could I please get a review and could you add this to 3.6 milestone? @greg0ire @beberlei @derrabus @SenseException |
This comment was marked as resolved.
This comment was marked as resolved.
|
I remember a lengthy discussion about this feature at the 2023 hackathon, although I fail to recall the details. One thing I remember was that people may have a need for nullable properties to be able to bind form systems (like Symfony Forms) to entities, where fields may need to be null in code but not in DB… does that make sense? |
I'm not familiar with symfony/forms (I'm using nette/forms and manual mapping), but inherited nullability is not forced, you can always override it with |
Yes, that's basically the problem with nullability of properties. Unitil you persist it, an entity can basically represent an incomplete record. Imagine you create a new entity and then populate the properties one by one with then correct data. Symfony Forms is just one example where this is needed.
Yeah, but this very argument can be brought up in favor of not inferring nullability. Now, what you're proposing is a global flag that will affect all entities managed by an EM. This basically means that there's a single point of time where you can safely change this setting: When bootstrapping a new project. You cannot easily flip this switch on an existing project. You cannot iteratively switch your entities to the new way of inferring nullability. That will hurt the adoption of your feature. You cannot use entities from external packages that have been written with the current defaults in mind. And a package that integrates with ORM by providing entities would need to test with both modes. And to be safe, such a package would need to do the one thing you want to avoid in your own codebase: Define nullability explicitly everywhere because the default might change depending on the EM's configuration. I understand what you're trying to achieve here and that it would help you in your own project. But I believe that a global setting is the wrong way forward. |
|
@derrabus so should I make it as a private constructor property in AttributeDriver and XmlDriver? This way it will be per-mapping and you can configure it in the |
Closes #9744 and #11797, relates to #11620.
It's made as opt-in feature so we don't cause BC break, it can be enabled with
$config->setInferNullabilityFromPHPType(true).Example code before:
Example code after:
I have already tested it also on mid-sized project and new generated migration was ok (I already migrated it, ~25 queries), with default configuration. It helped me discover few database rows with null where should not be null, and it would cause app error if those entities were loaded.
I'm not sure how to treat properties without type, maybe we should make them nullable as well when this feature is enabled, since null is valid value for them. For now I kept original behavior for untyped properties but I think it would be better to make them nullable by default (JoinColumn already is, just Column is not) when this feature is enabled.