-
Notifications
You must be signed in to change notification settings - Fork 638
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
PHP clone on object w/ behaviors produces unexpected cloned object #2857
Comments
After a little digging, I found the culprit: Given the usage of the content behavior, my assumption here is behaviors SHOULD be cloned ... right? |
Obviously (since fields are managed via the same behavior), the same applies to elements:
We're using the |
I think the reason they do this is because That said, it does seem like a better solution would have been public function __clone()
{
if ($this->_behaviors !== null) {
$behaviors = array_merge($this->_behaviors);
$this->_behaviors = null;
foreach ($behaviors as $name => $behavior) {
$this->attachBehavior($name, clone $behavior);
}
} I'll talk to the Yii people about that. In the meantime you can work around this by doing $newQuery = clone $query;
foreach ($query->getBehaviors() as $name => $behavior) {
$newQuery->attachBehavior($name, clone $behavior);
} |
Right. Since we don't have access to the base component behaviors property anything extending it could do: /**
* @inheritdoc
*/
public function __clone()
{
$behaviors = $this->getBehaviors();
parent::__clone();
foreach($behaviors as $name => $behavior) {
$this->attachBehavior($name, clone $behavior);
}
} |
Yes, that’s how you could do it from a component class in lieu of a Yii fix. But i’m hesitant to start making that change on core Craft classes, if there’s a chance it could be solved from the core Component class instead. |
Good to hear this discussion from you guys, as I'd run into the same situation end of last week. I solved the need then by using Craft functions like entry->setFieldValuesFromRequest(), since I had that data available, but other apparent means to get a proper deep copy weren't that useful. Brandon's idea here looks a good way forward, and reminds me of how many other abilities he's helpet the Yii people to make useful. For me, it kind of points towards all the php people have been doing as well as Yii, to re-invent what we had in objects I am not going to say how many years ago, having gotten in on the ground floor before C++ was public, and when Smalltalk was in flower. The trouble seems to be that they patch together, step after step, without much apparent attention to what's been known about the tougher cases, or indeed, how persons are going to need to use the results in a real world. Probably a poster child for this would be, again, deep clone (or just visit) abilities, in Php itself, for which innings were held here also not long ago. And anyway, the state of documentation on both programs, etc., which is only alleviated by postings on various degrees of solutions others may generate. Ideas alone don't answer needs by themselves, and it's great that you're as able as you are to handle both the application and system worlds, Brandon. Appreciated, and you also Nate, for getting in there. |
@brandonkelly any word from the Yii folks? |
@nateiler here's the related issue and pull request. slated for Yii 2.1: yiisoft/yii2#16247 |
2.1 has a lot of breaking/compatibility changes. Are you thinking Craft 4? |
Yeah. |
Went ahead and rushed a fix for this, as there are core bugs that are affected by this (#3019 and unexpected As of the next release (3.0.13), all classes that extend craft\base\Model or craft\db\Query will include behaviors in their clones. |
Nice! I thought I remembered seeing 'clone' when getting descendants but didn't want to go down that rabbit hole. Thanks! |
And Yii just accepted a PR to fix this from |
I noticed that cloning an object that has behaviors (such as custom fields) results in the behaviors not being copied. So, a query filtering via custom field would result in the cloned query not producing the same criteria.
A quick little example where a custom Plain Text field 'position' is configured for a user.
And idea on how to get around this (except not use behaviors)?
The text was updated successfully, but these errors were encountered: