Skip to content

Commit ae684c8

Browse files
authored
Doc tweaks (#89)
1 parent c04239a commit ae684c8

File tree

1 file changed

+112
-64
lines changed

1 file changed

+112
-64
lines changed

README.md

Lines changed: 112 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.
44

5-
[![Build Status](https://travis-ci.org/myclabs/DeepCopy.png?branch=master)](https://travis-ci.org/myclabs/DeepCopy) [![Coverage Status](https://coveralls.io/repos/myclabs/DeepCopy/badge.png?branch=master)](https://coveralls.io/r/myclabs/DeepCopy?branch=master) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/myclabs/DeepCopy/badges/quality-score.png?s=2747100c19b275f93a777e3297c6c12d1b68b934)](https://scrutinizer-ci.com/g/myclabs/DeepCopy/)
5+
[![Build Status](https://travis-ci.org/myclabs/DeepCopy.png?branch=master)](https://travis-ci.org/myclabs/DeepCopy)
6+
[![Coverage Status](https://coveralls.io/repos/myclabs/DeepCopy/badge.png?branch=master)](https://coveralls.io/r/myclabs/DeepCopy?branch=master)
7+
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/myclabs/DeepCopy/badges/quality-score.png?s=2747100c19b275f93a777e3297c6c12d1b68b934)](https://scrutinizer-ci.com/g/myclabs/DeepCopy/)
68
[![Total Downloads](https://poser.pugx.org/myclabs/deep-copy/downloads.svg)](https://packagist.org/packages/myclabs/deep-copy)
79

810

@@ -44,8 +46,8 @@ Use simply:
4446
```php
4547
use DeepCopy\DeepCopy;
4648

47-
$deepCopy = new DeepCopy();
48-
$myCopy = $deepCopy->copy($myObject);
49+
$copier = new DeepCopy();
50+
$myCopy = $copier->copy($myObject);
4951
```
5052

5153

@@ -59,7 +61,8 @@ $myCopy = clone $myObject;
5961

6062
- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)?
6163

62-
You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior yourself.
64+
You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior
65+
yourself.
6366

6467
- But how do you handle **cycles** in the association graph?
6568

@@ -85,14 +88,49 @@ Now you're in for a big mess :(
8588

8689
## How it works
8790

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.
91+
DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it
92+
keeps a hash map of all instances and thus preserves the object graph.
93+
94+
To use it:
95+
96+
```php
97+
use function DeepCopy\deep_copy;
98+
99+
$copy = deep_copy($var);
100+
```
101+
102+
Alternatively, you can create your own `DeepCopy` instance to configure it differently for example:
103+
104+
```php
105+
use DeepCopy\DeepCopy;
106+
107+
$copier = new DeepCopy(true);
108+
109+
$copy = $copier->copy($var);
110+
```
111+
112+
It is however recommended to use a difference instance of `DeepCopy` between each object copy as it relies on
113+
`spl_object_hash` internally. As such you may want to roll your own deep copy function:
114+
115+
```php
116+
namespace Acme;
117+
118+
use DeepCopy\DeepCopy;
119+
120+
function deep_copy($var)
121+
{
122+
$copier = new DeepCopy(true);
123+
124+
return $copier->copy($var);
125+
}
126+
```
89127

90128

91129
## Going further
92130

93131
You can add filters to customize the copy process.
94132

95-
The method to add a filter is `$deepCopy->addFilter($filter, $matcher)`,
133+
The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`,
96134
with `$filter` implementing `DeepCopy\Filter\Filter`
97135
and `$matcher` implementing `DeepCopy\Matcher\Matcher`.
98136

@@ -112,8 +150,8 @@ The `PropertyNameMatcher` will match a property by its name:
112150
```php
113151
use DeepCopy\Matcher\PropertyNameMatcher;
114152

153+
// Will apply a filter to any property of any objects named "id"
115154
$matcher = new PropertyNameMatcher('id');
116-
// will apply a filter to any property of any objects named "id"
117155
```
118156

119157

@@ -124,46 +162,49 @@ The `PropertyMatcher` will match a specific property of a specific class:
124162
```php
125163
use DeepCopy\Matcher\PropertyMatcher;
126164

165+
// Will apply a filter to the property "id" of any objects of the class "MyClass"
127166
$matcher = new PropertyMatcher('MyClass', 'id');
128-
// will apply a filter to the property "id" of any objects of the class "MyClass"
129167
```
130168

131169

132170
#### Type
133171

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):
172+
The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of
173+
[gettype()](http://php.net/manual/en/function.gettype.php) function):
135174

136175
```php
137176
use DeepCopy\TypeMatcher\TypeMatcher;
138177

178+
// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
139179
$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
140-
// will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
141180
```
142181

143182

144183
### Filters
145184

146-
- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`.
147-
- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`.
185+
- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`
186+
- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`
148187

149188

150189
#### `SetNullFilter` (filter)
151190

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:
191+
Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have
192+
any ID:
153193

154194
```php
155195
use DeepCopy\DeepCopy;
156196
use DeepCopy\Filter\SetNullFilter;
157197
use DeepCopy\Matcher\PropertyNameMatcher;
158198

159-
$myObject = MyClass::load(123);
160-
echo $myObject->id; // 123
199+
$object = MyClass::load(123);
200+
echo $object->id; // 123
161201

162-
$deepCopy = new DeepCopy();
163-
$deepCopy->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
164-
$myCopy = $deepCopy->copy($myObject);
202+
$copier = new DeepCopy();
203+
$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
165204

166-
echo $myCopy->id; // null
205+
$copy = $copier->copy($object);
206+
207+
echo $copy->id; // null
167208
```
168209

169210

@@ -176,11 +217,11 @@ use DeepCopy\DeepCopy;
176217
use DeepCopy\Filter\KeepFilter;
177218
use DeepCopy\Matcher\PropertyMatcher;
178219

179-
$deepCopy = new DeepCopy();
180-
$deepCopy->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
181-
$myCopy = $deepCopy->copy($myObject);
220+
$copier = new DeepCopy();
221+
$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
182222

183-
// $myCopy->category has not been touched
223+
$copy = $copier->copy($object);
224+
// $copy->category has not been touched
184225
```
185226

186227

@@ -193,26 +234,29 @@ use DeepCopy\DeepCopy;
193234
use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
194235
use DeepCopy\Matcher\PropertyTypeMatcher;
195236

196-
$deepCopy = new DeepCopy();
197-
$deepCopy->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
198-
$myCopy = $deepCopy->copy($myObject);
237+
$copier = new DeepCopy();
238+
$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
239+
240+
$copy = $copier->copy($object);
199241
```
200242

201243

202244
#### `DoctrineEmptyCollectionFilter` (filter)
203245

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`
246+
If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the
247+
`DoctrineEmptyCollectionFilter`
205248

206249
```php
207250
use DeepCopy\DeepCopy;
208251
use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
209252
use DeepCopy\Matcher\PropertyMatcher;
210253

211-
$deepCopy = new DeepCopy();
212-
$deepCopy->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
213-
$myCopy = $deepCopy->copy($myObject);
254+
$copier = new DeepCopy();
255+
$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
214256

215-
// $myCopy->myProperty will return an empty collection
257+
$copy = $copier->copy($object);
258+
259+
// $copy->myProperty will return an empty collection
216260
```
217261

218262

@@ -221,56 +265,60 @@ $myCopy = $deepCopy->copy($myObject);
221265
If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
222266
Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
223267
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!**
268+
**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded
269+
before other filters are applied!**
225270

226271
```php
227272
use DeepCopy\DeepCopy;
228273
use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
229274
use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
230275

231-
$deepCopy = new DeepCopy();
232-
$deepCopy->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
233-
$myCopy = $deepCopy->copy($myObject);
276+
$copier = new DeepCopy();
277+
$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
278+
279+
$copy = $copier->copy($object);
234280

235-
// $myCopy should now contain a clone of all entities, including those that were not yet fully loaded.
281+
// $copy should now contain a clone of all entities, including those that were not yet fully loaded.
236282
```
237283

238284

239285
#### `ReplaceFilter` (type filter)
240286

241-
1. If you want to replace the value of a property:
287+
1. If you want to replace the value of a property:
288+
289+
```php
290+
use DeepCopy\DeepCopy;
291+
use DeepCopy\Filter\ReplaceFilter;
292+
use DeepCopy\Matcher\PropertyMatcher;
293+
294+
$copier = new DeepCopy();
295+
$callback = function ($currentValue) {
296+
return $currentValue . ' (copy)'
297+
};
298+
$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
242299

243-
```php
244-
use DeepCopy\DeepCopy;
245-
use DeepCopy\Filter\ReplaceFilter;
246-
use DeepCopy\Matcher\PropertyMatcher;
300+
$copy = $copier->copy($object);
247301

248-
$deepCopy = new DeepCopy();
249-
$callback = function ($currentValue) {
250-
return $currentValue . ' (copy)'
251-
};
252-
$deepCopy->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
253-
$myCopy = $deepCopy->copy($myObject);
302+
// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
303+
```
254304

255-
// $myCopy->title will contain the data returned by the callback, e.g. 'The title (copy)'
256-
```
305+
2. If you want to replace whole element:
257306

258-
2. If you want to replace whole element:
307+
```php
308+
use DeepCopy\DeepCopy;
309+
use DeepCopy\TypeFilter\ReplaceFilter;
310+
use DeepCopy\TypeMatcher\TypeMatcher;
259311

260-
```php
261-
use DeepCopy\DeepCopy;
262-
use DeepCopy\TypeFilter\ReplaceFilter;
263-
use DeepCopy\TypeMatcher\TypeMatcher;
312+
$copier = new DeepCopy();
313+
$callback = function (MyClass $myClass) {
314+
return get_class($myClass);
315+
};
316+
$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
264317

265-
$deepCopy = new DeepCopy();
266-
$callback = function (MyClass $myClass) {
267-
return get_class($myClass);
268-
};
269-
$deepCopy->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
270-
$myCopy = $deepCopy->copy(array(new MyClass, 'some string', new MyClass));
318+
$copy = $copier->copy([new MyClass, 'some string', new MyClass]);
271319

272-
// $myCopy will contain ['MyClass', 'some string', 'MyClass']
273-
```
320+
// $copy will contain ['MyClass', 'some string', 'MyClass']
321+
```
274322

275323

276324
The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
@@ -293,7 +341,7 @@ $this->deepCopy->addTypeFilter(
293341
);
294342

295343
$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
296-
// all mocks will be just cloned, not deep-copied
344+
// All mocks will be just cloned, not deep copied
297345
```
298346

299347

@@ -307,5 +355,5 @@ DeepCopy is distributed under the MIT license.
307355
Running the tests is simple:
308356

309357
```php
310-
phpunit
358+
vendor/bin/phpunit
311359
```

0 commit comments

Comments
 (0)