You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've did a review of the lib and did some cleanup, tweaks and added missing tests.
- Bumped minimal version to PHP 5.6.
- Fixed the PHPUnit config to exclude `deep_copy.php` from the coverage report
- Fixed a bug when using `useCloneMethod`: the old object was returned unchanged instead of returning the cloned object
- Make the coverage stricter by adding the `@covers` annotations
- Add missing tests
- Cosmetic cleanup
@@ -65,22 +67,27 @@ Now you're in for a big mess :(
65
67
66
68

67
69
70
+
68
71
### Using simply `clone`
69
72
70
73

71
74
75
+
72
76
### Overridding `__clone()`
73
77
74
78

75
79
80
+
76
81
### With `DeepCopy`
77
82
78
83

79
84
85
+
80
86
## How it works
81
87
82
88
DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it keeps a hash map of all instances and thus preserves the object graph.
83
89
90
+
84
91
## Going further
85
92
86
93
You can add filters to customize the copy process.
@@ -91,11 +98,13 @@ and `$matcher` implementing `DeepCopy\Matcher\Matcher`.
91
98
92
99
We provide some generic filters and matchers.
93
100
101
+
94
102
### Matchers
95
103
96
104
-`DeepCopy\Matcher` applies on a object attribute.
97
105
-`DeepCopy\TypeMatcher` applies on any element found in graph, including array elements.
98
106
107
+
99
108
#### Property name
100
109
101
110
The `PropertyNameMatcher` will match a property by its name:
@@ -107,6 +116,7 @@ $matcher = new PropertyNameMatcher('id');
107
116
// will apply a filter to any property of any objects named "id"
108
117
```
109
118
119
+
110
120
#### Specific property
111
121
112
122
The `PropertyMatcher` will match a specific property of a specific class:
@@ -118,6 +128,7 @@ $matcher = new PropertyMatcher('MyClass', 'id');
118
128
// will apply a filter to the property "id" of any objects of the class "MyClass"
119
129
```
120
130
131
+
121
132
#### Type
122
133
123
134
The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of [gettype()](http://php.net/manual/en/function.gettype.php) function):
@@ -129,12 +140,14 @@ $matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
129
140
// will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
130
141
```
131
142
143
+
132
144
### Filters
133
145
134
146
-`DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`.
135
147
-`DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`.
136
148
137
-
#### `SetNullFilter`
149
+
150
+
#### `SetNullFilter` (filter)
138
151
139
152
Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have any ID:
If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`:
190
+
191
+
```php
192
+
use DeepCopy\DeepCopy;
193
+
use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
194
+
use DeepCopy\Matcher\PropertyTypeMatcher;
195
+
196
+
$deepCopy = new DeepCopy();
197
+
$deepCopy->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
198
+
$myCopy = $deepCopy->copy($myObject);
199
+
```
200
+
201
+
202
+
#### `DoctrineEmptyCollectionFilter` (filter)
203
+
204
+
If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the `DoctrineEmptyCollectionFilter`
205
+
206
+
```php
207
+
use DeepCopy\DeepCopy;
208
+
use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
209
+
use DeepCopy\Matcher\PropertyMatcher;
210
+
211
+
$deepCopy = new DeepCopy();
212
+
$deepCopy->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
213
+
$myCopy = $deepCopy->copy($myObject);
214
+
215
+
// $myCopy->myProperty will return an empty collection
216
+
```
217
+
218
+
219
+
#### `DoctrineProxyFilter` (filter)
220
+
221
+
If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
222
+
Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
223
+
You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class.
224
+
**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded before other filters are applied!**
225
+
226
+
```php
227
+
use DeepCopy\DeepCopy;
228
+
use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
229
+
use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
230
+
231
+
$deepCopy = new DeepCopy();
232
+
$deepCopy->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
233
+
$myCopy = $deepCopy->copy($myObject);
234
+
235
+
// $myCopy should now contain a clone of all entities, including those that were not yet fully loaded.
236
+
```
237
+
238
+
239
+
#### `ReplaceFilter` (type filter)
173
240
174
241
1. If you want to replace the value of a property:
The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
210
277
211
-
#### `ShallowCopyFilter`
278
+
279
+
#### `ShallowCopyFilter` (type filter)
212
280
213
281
Stop *DeepCopy* from recursively copying element, using standard `clone` instead:
214
282
@@ -228,59 +296,12 @@ $myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDep
228
296
// all mocks will be just cloned, not deep-copied
229
297
```
230
298
231
-
#### `DoctrineCollectionFilter`
232
-
233
-
If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`:
234
-
235
-
```php
236
-
use DeepCopy\DeepCopy;
237
-
use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
238
-
use DeepCopy\Matcher\PropertyTypeMatcher;
239
-
240
-
$deepCopy = new DeepCopy();
241
-
$deepCopy->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
242
-
$myCopy = $deepCopy->copy($myObject);
243
-
```
244
-
245
-
#### `DoctrineEmptyCollectionFilter`
246
-
247
-
If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the `DoctrineEmptyCollectionFilter`
248
-
249
-
```php
250
-
use DeepCopy\DeepCopy;
251
-
use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
252
-
use DeepCopy\Matcher\PropertyMatcher;
253
-
254
-
$deepCopy = new DeepCopy();
255
-
$deepCopy->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
256
-
$myCopy = $deepCopy->copy($myObject);
257
-
258
-
// $myCopy->myProperty will return an empty collection
259
-
```
260
-
261
-
#### `DoctrineProxyFilter`
262
-
263
-
If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
264
-
Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
265
-
You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class.
266
-
**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded before other filters are applied!**
267
-
268
-
```php
269
-
use DeepCopy\DeepCopy;
270
-
use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
271
-
use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
272
-
273
-
$deepCopy = new DeepCopy();
274
-
$deepCopy->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
275
-
$myCopy = $deepCopy->copy($myObject);
276
-
277
-
// $myCopy should now contain a clone of all entities, including those that were not yet fully loaded.
0 commit comments