Typed PHP, Stronger Types for Cleaner Code (2014)
Structure
Boxing
Boxing is a term given to the practice of wrapping (enclosing) data within a class, so that behaviour can be added to the wrapped data. Let’s look at an example:
1 <?php
2
3 class StringBox
4 {
5 /**
6 * @var string
7 */
8 protected $data;
9
10 /**
11 * @param string $data
12 */
13 public function __construct($data)
14 {
15 $this->data = $data;
16 }
17
18 /**
19 * @return string
20 */
21 public function toString()
22 {
23 return (string) $this->data;
24 }
25
26 /**
27 * @return string
28 */
29 public function toUpperCase()
30 {
31 return strtoupper($this->data);
32 }
33
34 /**
35 * @return string
36 */
37 public function toLowerCase()
38 {
39 return strtolower($this->data);
40 }
41
42 /**
43 * @param string $needle
44 * @param mixed $offset
45 *
46 * @return int
47 */
48 public function getIndexOf($needle, $offset = null)
49 {
50 $index = strpos($this->data, $needle, $offset);
51
52 if ($index === false) {
53 return -1;
54 }
55
56 return $index;
57 }
58 }
59
60 $box = new StringBox("Hello World");
61
62 print $box->toString(); // "hello world"
63 print $box->toUpperCase(); // "HELLO WORLD"
64 print $box->toLowerCase(); // "hello world"
65 print $box->getIndexOf("foo"); // -1
66 print $box->getIndexOf("World"); // 6
This approach is fully supported by PHP, without any additional extensions or dependencies. It’s a simple concept, if you think about it. You’re using protected properties and exposing a public API for setting them, getting them and manipulating them.
The difficulty with it is that it leads to a lot more code than just using the native functions. You need to define wrappers. You need to define setters and getters. You have to use them every time you want to put native types in and get native types out. What do I mean by that last statement?
1 $helloBox = new StringBox("Hello");
2 $worldBox = new StringBox("World");
3
4 $helloWorldBox = new StringBox(
5 $helloBox->toString() . " " . $worldBox->toString()
6 );
This quickly becomes unwieldy. It’s also more memory intensive, and slower than just using the native functions and types.
PHP allows the use of a method called __toString. When a class defines this method (to return a string), and an instance of the class is used in an operation that expects a string; the __toString method is automatically called.
This isn’t enough for us to simulate an extensible type system, or this would be a short book.