Doctrine 2.9.1: [OneToMany.php:60] Doctrine\ORM\Mapping\OneToMany::__construct(): Argument #3 ($cascade) must be of type ?array, string given #6735

Open
opened 2026-01-22 15:37:42 +01:00 by admin · 8 comments
Owner

Originally created by @ghdi on GitHub (May 25, 2021).

Hi,

After upgrading from 2.8.4 to 2.9.1 I get the following error:

[OneToMany.php:60] Doctrine\ORM\Mapping\OneToMany::__construct(): Argument #3 ($cascade) must be of type ?array, string given

Is there something I might have missed somewhere?

Regards,

Edwin

Originally created by @ghdi on GitHub (May 25, 2021). Hi, After upgrading from 2.8.4 to 2.9.1 I get the following error: [OneToMany.php:60] Doctrine\ORM\Mapping\OneToMany::__construct(): Argument #3 ($cascade) must be of type ?array, string given Is there something I might have missed somewhere? Regards, Edwin
Author
Owner

@greg0ire commented on GitHub (May 25, 2021):

You probably have some invalid mapping somewhere… check for cascade in your one to many mappings, and check that it is indeed an array.

@greg0ire commented on GitHub (May 25, 2021): You probably have some invalid mapping somewhere… check for `cascade` in your one to many mappings, and check that it is indeed an array.
Author
Owner

@ghdi commented on GitHub (May 26, 2021):

Grégoire, they were indeed all string based,cascade="remove", which worked fine in Doctrine/ORM 2.8.4 and below. Changing all the cascades to cascade={"remove"} indeed solved the issue.

What triggered my confusion was that after upgrading from 2.8.4 to 2.9.1 things stopped working and after downgrading back from 2.9.1 to 2.8.4 things worked again as advertized, without any changes to the code.

Thanks for your help!

@ghdi commented on GitHub (May 26, 2021): Grégoire, they were indeed all string based,cascade="remove", which worked fine in Doctrine/ORM 2.8.4 and below. Changing all the cascades to cascade={"remove"} indeed solved the issue. What triggered my confusion was that after upgrading from 2.8.4 to 2.9.1 things stopped working and after downgrading back from 2.9.1 to 2.8.4 things worked again as advertized, without any changes to the code. Thanks for your help!
Author
Owner

@greg0ire commented on GitHub (May 26, 2021):

It's indeed confusing because we are not supposed to do such BC-breaks. Do you know where you read that cascade="remove" was supported?

@greg0ire commented on GitHub (May 26, 2021): It's indeed confusing because we are not supposed to do such BC-breaks. Do you know where you read that `cascade="remove"` was supported?
Author
Owner

@ghdi commented on GitHub (May 26, 2021):

Grégoire, I've been using doctrine on this project since mid 2017 or thereabouts, so it must have been somewhere in the doctrine documentation of those days.

Likely a moot point by now anyway, given that this page/stackoverflow/etc are not being inundated with this very same question.

@ghdi commented on GitHub (May 26, 2021): Grégoire, I've been using doctrine on this project since mid 2017 or thereabouts, so it must have been somewhere in the doctrine documentation of those days. Likely a moot point by now anyway, given that this page/stackoverflow/etc are not being inundated with this very same question.
Author
Owner

@acoulton commented on GitHub (May 27, 2021):

Yep, we have the same breaking behaviour - again, can't tell where we originally got the idea that the string value was supported but this is quite an old/early doctrine2 project (and it was, until 2.9.1).

Update: I've looked back at the 2.0/2.1 docs and can't find any reference to passing a string, as far as I can see it was always documented as an array so I guess we've just been using it incorrectly and got lucky.

@acoulton commented on GitHub (May 27, 2021): Yep, we have the same breaking behaviour - again, can't tell where we originally got the idea that the string value was supported but this is quite an old/early doctrine2 project (and it was, until 2.9.1). Update: I've looked back at the 2.0/2.1 docs and can't find any reference to passing a string, as far as I can see it was always documented as an array so I guess we've just been using it incorrectly and got lucky.
Author
Owner

@greg0ire commented on GitHub (May 27, 2021):

I think it is OK to close this then 👍 . Thanks for looking into this.

@greg0ire commented on GitHub (May 27, 2021): I think it is OK to close this then 👍 . Thanks for looking into this.
Author
Owner

@ohaag commented on GitHub (Jun 25, 2021):

I kind of disagree with the fact that because it is not explicitly written it shouldn't deserve a warning: it is still a breaking change.
That notation worked for at least 8 years, and now it will crash every apps which are using it. And in that time window, I guess there are a lot. In Symfony that's not even easy to find out where the error came from, because it can be triggered by a getRepository() method call (annotation errors are rarely the easier ones to spot).

Therefore, the notation cascade=REMOVE or cascade=ALL is all over the place in the doc when it is not a code extract.
Like here.
Moreover, it is a common things with annotations to support the fact that when a single value is given, it is automatically converted into an array. Example : Symfony @Route which accepts methods="GET" despite the attribute even presents itself with plural mark.

Like shown in this example, it isn't that hard to keep it backward-compatible, and if there is a choice to no keep it, then it should be mentioned as a BC in the upgrade's documentation.

@ohaag commented on GitHub (Jun 25, 2021): I kind of disagree with the fact that because it is not explicitly written it shouldn't deserve a warning: it is still a breaking change. That notation worked for at least 8 years, and now it will crash every apps which are using it. And in that time window, I guess there are a lot. In Symfony that's not even easy to find out where the error came from, because it can be triggered by a getRepository() method call (annotation errors are rarely the easier ones to spot). Therefore, the notation cascade=REMOVE or cascade=ALL is all over the place in the doc when it is not a code extract. Like [here](https://www.doctrine-project.org/projects/doctrine-orm/en/2.9/reference/working-with-objects.html#removing-entities). Moreover, it is a common things with annotations to support the fact that when a single value is given, it is automatically converted into an array. Example : [Symfony @Route](https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Routing/Annotation/Route.php#L235) which accepts `methods="GET"` despite the attribute even presents itself with plural mark. Like shown in this example, it isn't that hard to keep it backward-compatible, and if there is a choice to no keep it, then it should be mentioned as a BC in the upgrade's documentation.
Author
Owner

@greg0ire commented on GitHub (Jun 25, 2021):

Therefore, the notation cascade=REMOVE or cascade=ALL is all over the place in the doc when it is not a code extract.

You're right, I was not aware of that. And since you are already 3 people to complain about this, I think it's fair to reopen. I think there are 2 ways:

  1. restoring BC in 2.9, adding full support for this in 2.10
  2. restoring BC in 2.9, deprecating it in 2.10, and dropping support for it in 3.0
@greg0ire commented on GitHub (Jun 25, 2021): > Therefore, the notation cascade=REMOVE or cascade=ALL is all over the place in the doc when it is not a code extract. You're right, I was not aware of that. And since you are already 3 people to complain about this, I think it's fair to reopen. I think there are 2 ways: 1. restoring BC in 2.9, adding full support for this in 2.10 2. restoring BC in 2.9, deprecating it in 2.10, and dropping support for it in 3.0
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6735