|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace LukePOLO\LaraCart; |
|
4
|
|
|
|
|
5
|
|
|
use LukePOLO\LaraCart\Contracts\CouponContract; |
|
6
|
|
|
use LukePOLO\LaraCart\Contracts\LaraCartContract; |
|
7
|
|
|
|
|
8
|
|
|
/** |
|
9
|
|
|
* Class LaraCart |
|
10
|
|
|
* |
|
11
|
|
|
* @package LukePOLO\LaraCart |
|
12
|
|
|
*/ |
|
13
|
|
|
class LaraCart implements LaraCartContract |
|
14
|
|
|
{ |
|
15
|
|
|
const SERVICE = 'laracart'; |
|
16
|
|
|
const QTY = 'qty'; |
|
17
|
|
|
const PRICE = 'price'; |
|
18
|
|
|
const HASH = 'generateCartHash'; |
|
19
|
|
|
const RANHASH = 'generateRandomCartItemHash'; |
|
20
|
|
|
|
|
21
|
|
|
public $cart; |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* LaraCart constructor. |
|
25
|
|
|
*/ |
|
26
|
|
|
public function __construct() |
|
27
|
|
|
{ |
|
28
|
|
|
$this->setInstance(\Session::get('laracart.instance', 'default')); |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Sets and Gets the instance of the cart in the session we should be using |
|
33
|
|
|
* |
|
34
|
|
|
* @param string $instance |
|
35
|
|
|
* |
|
36
|
|
|
* @return LaraCart |
|
37
|
|
|
*/ |
|
38
|
|
|
public function setInstance($instance = 'default') |
|
39
|
|
|
{ |
|
40
|
|
|
$this->get($instance); |
|
41
|
|
|
|
|
42
|
|
|
\Session::set('laracart.instance', $instance); |
|
43
|
|
|
|
|
44
|
|
|
\Event::fire('laracart.new'); |
|
45
|
|
|
|
|
46
|
|
|
return $this; |
|
47
|
|
|
} |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* Gets the instance in the session |
|
51
|
|
|
* |
|
52
|
|
|
* @param string $instance |
|
53
|
|
|
* |
|
54
|
|
|
* @return $this cart instance |
|
55
|
|
|
*/ |
|
56
|
|
|
public function get($instance = 'default') |
|
57
|
|
|
{ |
|
58
|
|
|
if (empty($this->cart = \Session::get(config('laracart.cache_prefix', 'laracart').'.'.$instance))) { |
|
59
|
|
|
$this->cart = new Cart($instance); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
return $this; |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Updates cart session |
|
67
|
|
|
*/ |
|
68
|
|
|
public function update() |
|
69
|
|
|
{ |
|
70
|
|
|
\Session::set(config('laracart.cache_prefix', 'laracart').'.'.$this->cart->instance, $this->cart); |
|
71
|
|
|
|
|
72
|
|
|
\Event::fire('laracart.update', $this->cart); |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* |
|
77
|
|
|
* Formats the number into a money format based on the locale and international formats |
|
78
|
|
|
* |
|
79
|
|
|
* @param $number |
|
80
|
|
|
* @param $locale |
|
81
|
|
|
* @param $internationalFormat |
|
82
|
|
|
* @param $format |
|
83
|
|
|
* |
|
84
|
|
|
* @return string |
|
85
|
|
|
*/ |
|
86
|
|
|
public function formatMoney($number, $locale = null, $internationalFormat = null, $format = true) |
|
87
|
|
|
{ |
|
88
|
|
|
if ($format) { |
|
89
|
|
|
setlocale(LC_MONETARY, empty($locale) ? config('laracart.locale', 'en_US.UTF-8') : $locale); |
|
90
|
|
|
|
|
91
|
|
|
if (empty($internationalFormat) === true) { |
|
92
|
|
|
$internationalFormat = config('laracart.international_format', false); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
return money_format($internationalFormat ? '%i' : '%n', $number); |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
return number_format($number, 2, '.', ''); |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Gets an an attribute from the cart |
|
103
|
|
|
* |
|
104
|
|
|
* @param $attribute |
|
105
|
|
|
* @param $defaultValue |
|
106
|
|
|
* |
|
107
|
|
|
* @return mixed |
|
108
|
|
|
*/ |
|
109
|
|
|
public function getAttribute($attribute, $defaultValue = null) |
|
110
|
|
|
{ |
|
111
|
|
|
return array_get($this->cart->attributes, $attribute, $defaultValue); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* Gets all the carts attributes |
|
116
|
|
|
* |
|
117
|
|
|
* @return mixed |
|
118
|
|
|
*/ |
|
119
|
|
|
public function getAttributes() |
|
120
|
|
|
{ |
|
121
|
|
|
return $this->cart->attributes; |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
/** |
|
125
|
|
|
* Adds an Attribute to the cart |
|
126
|
|
|
* |
|
127
|
|
|
* @param $attribute |
|
128
|
|
|
* @param $value |
|
129
|
|
|
*/ |
|
130
|
|
|
public function setAttribute($attribute, $value) |
|
131
|
|
|
{ |
|
132
|
|
|
array_set($this->cart->attributes, $attribute, $value); |
|
133
|
|
|
|
|
134
|
|
|
$this->update(); |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* Removes an attribute from the cart |
|
139
|
|
|
* |
|
140
|
|
|
* @param $attribute |
|
141
|
|
|
*/ |
|
142
|
|
|
public function removeAttribute($attribute) |
|
143
|
|
|
{ |
|
144
|
|
|
array_forget($this->cart->attributes, $attribute); |
|
145
|
|
|
|
|
146
|
|
|
$this->update(); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
/** |
|
150
|
|
|
* Finds a cartItem based on the itemHash |
|
151
|
|
|
* |
|
152
|
|
|
* @param $itemHash |
|
153
|
|
|
* |
|
154
|
|
|
* @return CartItem | null |
|
155
|
|
|
*/ |
|
156
|
|
|
public function getItem($itemHash) |
|
157
|
|
|
{ |
|
158
|
|
|
return array_get($this->getItems(), $itemHash); |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Gets all the items within the cart |
|
163
|
|
|
* |
|
164
|
|
|
* @return array |
|
165
|
|
|
*/ |
|
166
|
|
|
public function getItems() |
|
167
|
|
|
{ |
|
168
|
|
|
$items = []; |
|
169
|
|
|
if (isset($this->cart->items) === true) { |
|
170
|
|
|
foreach ($this->cart->items as $item) { |
|
171
|
|
|
$items[$item->getHash()] = $item; |
|
172
|
|
|
} |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
return $items; |
|
176
|
|
|
} |
|
177
|
|
|
|
|
178
|
|
|
/** |
|
179
|
|
|
* Creates a CartItem and then adds it to cart |
|
180
|
|
|
* |
|
181
|
|
|
* @param $itemID |
|
182
|
|
|
* @param null $name |
|
183
|
|
|
* @param int $qty |
|
184
|
|
|
* @param string $price |
|
185
|
|
|
* @param array $options |
|
186
|
|
|
* @param bool|false $taxable |
|
187
|
|
|
* @param bool|false $lineItem |
|
188
|
|
|
* |
|
189
|
|
|
* @return CartItem |
|
190
|
|
|
*/ |
|
191
|
|
|
public function add( |
|
192
|
|
|
$itemID, |
|
193
|
|
|
$name = null, |
|
194
|
|
|
$qty = 1, |
|
195
|
|
|
$price = '0.00', |
|
196
|
|
|
$options = [], |
|
197
|
|
|
$taxable = true, |
|
198
|
|
|
$lineItem = false |
|
199
|
|
|
) { |
|
200
|
|
|
return $this->addItem( |
|
201
|
|
|
new CartItem( |
|
202
|
|
|
$itemID, |
|
203
|
|
|
$name, |
|
204
|
|
|
$qty, |
|
205
|
|
|
$price, |
|
206
|
|
|
$options, |
|
207
|
|
|
$taxable, |
|
208
|
|
|
$lineItem |
|
209
|
|
|
) |
|
210
|
|
|
); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
/** |
|
214
|
|
|
* Creates a CartItem and then adds it to cart |
|
215
|
|
|
* |
|
216
|
|
|
* @param string|int $itemID |
|
217
|
|
|
* @param null $name |
|
218
|
|
|
* @param int $qty |
|
219
|
|
|
* @param string $price |
|
220
|
|
|
* @param array $options |
|
221
|
|
|
* |
|
222
|
|
|
* @return CartItem |
|
223
|
|
|
*/ |
|
224
|
|
|
public function addLine($itemID, $name = null, $qty = 1, $price = '0.00', $options = [], $taxable = true) |
|
225
|
|
|
{ |
|
226
|
|
|
return $this->add($itemID, $name, $qty, $price, $options, $taxable, true); |
|
|
|
|
|
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Adds the cartItem into the cart session |
|
231
|
|
|
* |
|
232
|
|
|
* @param CartItem $cartItem |
|
233
|
|
|
* |
|
234
|
|
|
* @return CartItem |
|
235
|
|
|
*/ |
|
236
|
|
|
public function addItem(CartItem $cartItem) |
|
237
|
|
|
{ |
|
238
|
|
|
$itemHash = $cartItem->generateHash(); |
|
239
|
|
|
|
|
240
|
|
|
if ($this->getItem($itemHash)) { |
|
241
|
|
|
$this->getItem($itemHash)->qty += $cartItem->qty; |
|
242
|
|
|
} else { |
|
243
|
|
|
$this->cart->items[] = $cartItem; |
|
244
|
|
|
\Event::fire('laracart.addItem', $cartItem); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
$this->update(); |
|
248
|
|
|
|
|
249
|
|
|
return $cartItem; |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
/** |
|
253
|
|
|
* Updates an items attributes |
|
254
|
|
|
* |
|
255
|
|
|
* @param $itemHash |
|
256
|
|
|
* @param $key |
|
257
|
|
|
* @param $value |
|
258
|
|
|
* |
|
259
|
|
|
* @return CartItem |
|
260
|
|
|
* |
|
261
|
|
|
* @throws Exceptions\InvalidPrice |
|
262
|
|
|
* @throws Exceptions\InvalidQuantity |
|
263
|
|
|
*/ |
|
264
|
|
|
public function updateItem($itemHash, $key, $value) |
|
265
|
|
|
{ |
|
266
|
|
|
if (empty($item = $this->getItem($itemHash)) === false) { |
|
267
|
|
|
$item->update($key, $value); |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
$newHash = $item->generateHash(); |
|
271
|
|
|
|
|
272
|
|
|
\Event::fire( |
|
273
|
|
|
'laracart.updateItem', |
|
274
|
|
|
[ |
|
275
|
|
|
'item' => $item, |
|
276
|
|
|
'newHash' => $newHash, |
|
277
|
|
|
] |
|
278
|
|
|
); |
|
279
|
|
|
|
|
280
|
|
|
return $item; |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
/** |
|
284
|
|
|
* Removes a CartItem based on the itemHash |
|
285
|
|
|
* |
|
286
|
|
|
* @param $itemHash |
|
287
|
|
|
*/ |
|
288
|
|
|
public function removeItem($itemHash) |
|
289
|
|
|
{ |
|
290
|
|
|
foreach ($this->cart->items as $itemKey => $item) { |
|
291
|
|
|
if ($item->getHash() == $itemHash) { |
|
292
|
|
|
unset($this->cart->items[$itemKey]); |
|
293
|
|
|
break; |
|
294
|
|
|
} |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
\Event::fire('laracart.removeItem', $itemHash); |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
/** |
|
301
|
|
|
* Get the count based on qty, or number of unique items |
|
302
|
|
|
* |
|
303
|
|
|
* @param bool $withItemQty |
|
304
|
|
|
* |
|
305
|
|
|
* @return int |
|
306
|
|
|
*/ |
|
307
|
|
|
public function count($withItemQty = true) |
|
308
|
|
|
{ |
|
309
|
|
|
$count = 0; |
|
310
|
|
|
foreach ($this->getItems() as $item) { |
|
311
|
|
|
if ($withItemQty) { |
|
312
|
|
|
$count += $item->qty; |
|
313
|
|
|
} else { |
|
314
|
|
|
$count++; |
|
315
|
|
|
} |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
return $count; |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
/** |
|
322
|
|
|
* Empties the carts items |
|
323
|
|
|
*/ |
|
324
|
|
|
public function emptyCart() |
|
325
|
|
|
{ |
|
326
|
|
|
unset($this->cart->items); |
|
327
|
|
|
|
|
328
|
|
|
$this->update(); |
|
329
|
|
|
|
|
330
|
|
|
\Event::fire('laracart.empty', $this->cart->instance); |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
/** |
|
334
|
|
|
* Completely destroys cart and anything associated with it |
|
335
|
|
|
*/ |
|
336
|
|
|
public function destroyCart() |
|
337
|
|
|
{ |
|
338
|
|
|
$this->cart = new Cart($this->cart->instance); |
|
339
|
|
|
|
|
340
|
|
|
$this->update(); |
|
341
|
|
|
|
|
342
|
|
|
\Event::fire('laracart.destroy', $this->cart->instance); |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
/** |
|
346
|
|
|
* Gets the coupons for the current cart |
|
347
|
|
|
* |
|
348
|
|
|
* @return array |
|
349
|
|
|
*/ |
|
350
|
|
|
public function getCoupons() |
|
351
|
|
|
{ |
|
352
|
|
|
return $this->cart->coupons; |
|
353
|
|
|
} |
|
354
|
|
|
|
|
355
|
|
|
/** |
|
356
|
|
|
* // TODO - badly named |
|
357
|
|
|
* Finds a specific coupon in the cart |
|
358
|
|
|
* |
|
359
|
|
|
* @param $code |
|
360
|
|
|
* @return mixed |
|
361
|
|
|
*/ |
|
362
|
|
|
public function findCoupon($code) |
|
363
|
|
|
{ |
|
364
|
|
|
return array_get($this->cart->coupons, $code); |
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
/** |
|
368
|
|
|
* // todo - badly named |
|
369
|
|
|
* Applies a coupon to the cart |
|
370
|
|
|
* |
|
371
|
|
|
* @param CouponContract $coupon |
|
372
|
|
|
*/ |
|
373
|
|
|
public function addCoupon(CouponContract $coupon) |
|
374
|
|
|
{ |
|
375
|
|
|
if(!$this->cart->multipleCoupons) { |
|
376
|
|
|
$this->cart->coupons = []; |
|
377
|
|
|
} |
|
378
|
|
|
|
|
379
|
|
|
$this->cart->coupons[$coupon->code] = $coupon; |
|
|
|
|
|
|
380
|
|
|
|
|
381
|
|
|
$this->update(); |
|
382
|
|
|
} |
|
383
|
|
|
|
|
384
|
|
|
/** |
|
385
|
|
|
* Removes a coupon in the cart |
|
386
|
|
|
* |
|
387
|
|
|
* @param $code |
|
388
|
|
|
*/ |
|
389
|
|
|
public function removeCoupon($code) |
|
390
|
|
|
{ |
|
391
|
|
|
foreach($this->getItems() as $item) { |
|
392
|
|
|
if(isset($item->code) && $item->code == $code) { |
|
393
|
|
|
$item->code = null; |
|
394
|
|
|
$item->discount = null; |
|
395
|
|
|
$item->couponInfo = null; |
|
396
|
|
|
} |
|
397
|
|
|
} |
|
398
|
|
|
|
|
399
|
|
|
array_forget($this->cart->coupons, $code); |
|
400
|
|
|
|
|
401
|
|
|
$this->update(); |
|
402
|
|
|
} |
|
403
|
|
|
|
|
404
|
|
|
/** |
|
405
|
|
|
* Gets a speific fee from the fees array |
|
406
|
|
|
* |
|
407
|
|
|
* @param $name |
|
408
|
|
|
* |
|
409
|
|
|
* @return mixed |
|
410
|
|
|
*/ |
|
411
|
|
|
public function getFee($name) |
|
412
|
|
|
{ |
|
413
|
|
|
return array_get($this->cart->fees, $name, new CartFee(null, false)); |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
/** |
|
417
|
|
|
* Getes all the fees on the cart object |
|
418
|
|
|
* |
|
419
|
|
|
* @return mixed |
|
420
|
|
|
*/ |
|
421
|
|
|
public function getFees() |
|
422
|
|
|
{ |
|
423
|
|
|
return $this->cart->fees; |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
/** |
|
427
|
|
|
* Allows to charge for additional fees that may or may not be taxable |
|
428
|
|
|
* ex - service fee , delivery fee, tips |
|
429
|
|
|
* |
|
430
|
|
|
* @param $name |
|
431
|
|
|
* @param $amount |
|
432
|
|
|
* @param bool|false $taxable |
|
433
|
|
|
* @param array $options |
|
434
|
|
|
*/ |
|
435
|
|
|
public function addFee($name, $amount, $taxable = false, Array $options = []) |
|
436
|
|
|
{ |
|
437
|
|
|
array_set($this->cart->fees, $name, new CartFee($amount, $taxable, $options)); |
|
438
|
|
|
|
|
439
|
|
|
$this->update(); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
/** |
|
443
|
|
|
* Reemoves a fee from the fee array |
|
444
|
|
|
* |
|
445
|
|
|
* @param $name |
|
446
|
|
|
*/ |
|
447
|
|
|
public function removeFee($name) |
|
448
|
|
|
{ |
|
449
|
|
|
array_forget($this->cart->fees, $name); |
|
450
|
|
|
|
|
451
|
|
|
$this->update(); |
|
452
|
|
|
} |
|
453
|
|
|
|
|
454
|
|
|
/** |
|
455
|
|
|
* Gets all the fee totals |
|
456
|
|
|
* |
|
457
|
|
|
* @param boolean $format |
|
458
|
|
|
* |
|
459
|
|
|
* @return string |
|
460
|
|
|
*/ |
|
461
|
|
|
public function feeTotals($format = true) |
|
462
|
|
|
{ |
|
463
|
|
|
$feeTotal = 0; |
|
464
|
|
|
|
|
465
|
|
|
foreach ($this->getFees() as $fee) { |
|
466
|
|
|
$feeTotal += $fee->amount; |
|
467
|
|
|
if ($fee->taxable) { |
|
468
|
|
|
$feeTotal += $fee->amount * $this->cart->tax; |
|
469
|
|
|
} |
|
470
|
|
|
} |
|
471
|
|
|
|
|
472
|
|
|
return $this->formatMoney($feeTotal, null, null, $format); |
|
473
|
|
|
} |
|
474
|
|
|
|
|
475
|
|
|
/** |
|
476
|
|
|
* Gets the total amount discounted |
|
477
|
|
|
* |
|
478
|
|
|
* @param bool|true $format |
|
479
|
|
|
* |
|
480
|
|
|
* @return int|string |
|
481
|
|
|
*/ |
|
482
|
|
|
public function totalDiscount($format = true) |
|
483
|
|
|
{ |
|
484
|
|
|
$total = 0; |
|
485
|
|
|
|
|
486
|
|
|
foreach ($this->cart->coupons as $coupon) { |
|
487
|
|
|
$total += $coupon->discount(); |
|
488
|
|
|
} |
|
489
|
|
|
|
|
490
|
|
|
return $this->formatMoney($total, null, null, $format); |
|
491
|
|
|
} |
|
492
|
|
|
|
|
493
|
|
|
|
|
494
|
|
|
/** |
|
495
|
|
|
* Gets the total tax for the cart |
|
496
|
|
|
* |
|
497
|
|
|
* @param bool|true $format |
|
498
|
|
|
* |
|
499
|
|
|
* @return string |
|
500
|
|
|
*/ |
|
501
|
|
|
public function taxTotal($format = true) |
|
502
|
|
|
{ |
|
503
|
|
|
$totalTax = $this->total(false, false) - $this->subTotal(false, false, false) - $this->feeTotals(false); |
|
504
|
|
|
|
|
505
|
|
|
|
|
506
|
|
|
return $this->formatMoney($totalTax, null, null, $format); |
|
507
|
|
|
} |
|
508
|
|
|
|
|
509
|
|
|
/** |
|
510
|
|
|
* Gets the subtotal of the cart with or without tax |
|
511
|
|
|
* |
|
512
|
|
|
* @param bool|false $tax |
|
513
|
|
|
* @param boolean $format |
|
514
|
|
|
* @param boolean $withDiscount |
|
515
|
|
|
* |
|
516
|
|
|
* @return string |
|
517
|
|
|
*/ |
|
518
|
|
|
public function subTotal($tax = false, $format = true, $withDiscount = true) |
|
519
|
|
|
{ |
|
520
|
|
|
$total = 0; |
|
521
|
|
|
if ($this->count() != 0) { |
|
522
|
|
|
foreach ($this->getItems() as $item) { |
|
523
|
|
|
$total += $item->subTotal($tax, false, $withDiscount); |
|
524
|
|
|
} |
|
525
|
|
|
} |
|
526
|
|
|
|
|
527
|
|
|
return $this->formatMoney($total, null, null, $format); |
|
528
|
|
|
} |
|
529
|
|
|
|
|
530
|
|
|
/** |
|
531
|
|
|
* Gets the total of the cart with or without tax |
|
532
|
|
|
* |
|
533
|
|
|
* @param boolean $format |
|
534
|
|
|
* @param boolean $withDiscount |
|
535
|
|
|
* |
|
536
|
|
|
* @return string |
|
537
|
|
|
*/ |
|
538
|
|
|
public function total($format = true, $withDiscount = true) |
|
539
|
|
|
{ |
|
540
|
|
|
$total = $this->subTotal(true, false, false) + $this->feeTotals(false); |
|
541
|
|
|
|
|
542
|
|
|
if ($withDiscount) { |
|
543
|
|
|
$total -= $this->totalDiscount(false); |
|
544
|
|
|
} |
|
545
|
|
|
|
|
546
|
|
|
return $this->formatMoney($total, null, null, $format); |
|
547
|
|
|
} |
|
548
|
|
|
} |
|
549
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.