Boxing - Structure - Typed PHP, Stronger Types for Cleaner Code

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.