Search icon
Subscription
0
Cart icon
Close icon
You have no products in your basket yet
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
PHP 8 Programming Tips, Tricks and Best Practices

You're reading from  PHP 8 Programming Tips, Tricks and Best Practices

Product type Book
Published in Aug 2021
Publisher Packt
ISBN-13 9781801071871
Pages 528 pages
Edition 1st Edition
Languages
Author (1):
Doug Bierer Doug Bierer
Profile icon Doug Bierer

Table of Contents (17) Chapters

Preface 1. Section 1: PHP 8 Tips
2. Chapter 1: Introducing New PHP 8 OOP Features 3. Chapter 2: Learning about PHP 8's Functional Additions 4. Chapter 3: Taking Advantage of Error-Handling Enhancements 5. Chapter 4: Making Direct C-Language Calls 6. Section 2: PHP 8 Tricks
7. Chapter 5: Discovering Potential OOP Backward-Compatibility Breaks 8. Chapter 6: Understanding PHP 8 Functional Differences 9. Chapter 7: Avoiding Traps When Using PHP 8 Extensions 10. Chapter 8: Learning about PHP 8's Deprecated or Removed Functionality 11. Section 3: PHP 8 Best Practices
12. Chapter 9: Mastering PHP 8 Best Practices 13. Chapter 10: Improving Performance 14. Chapter 11: Migrating Existing PHP Apps to PHP 8 15. Chapter 12: Creating PHP 8 Applications Using Asynchronous Programming 16. Other Books You May Enjoy

Improving code using typed properties

In the first section of this chapter, Using constructor property promotion, we discussed how data types can be used to control the type of data supplied as arguments to functions or class methods. What this approach fails to do, however, is guarantee that the data type never changes. In this section, you will learn how assigning a data type at the property level provides stricter control over the use of variables in PHP 8.

What are typed properties?

This extremely important feature was introduced in PHP 7.4 and continues in PHP 8. Simply put, a typed property is a class property with a data type preassigned. Here is a simple example:

// /repo/ch01/php8_prop_type_1.php
declare(strict_types=1)
class Test {
    public int $id = 0;
    public int $token = 0;
    public string $name = '';
}
$test = new Test();
$test->id = 'ABC';

In this example, if we attempt to assign a value representing a data type other than int to $test->id, a Fatal error is thrown. Here is the output:

Fatal error: Uncaught TypeError: Cannot assign string to property Test::$id of type int in /repo/ch01/php8_prop_type_1.php:11 Stack trace: #0 {main} thrown in /repo/ch01/php8_prop_type_1.php on line 11 

As you can see from the preceding output, a Fatal error is thrown when the wrong data type is assigned to a typed property.

You have already been exposed to one form of property typing: constructor property promotion. All properties defined using constructor property promotion are automatically property typed!

Why is property typing important?

Typed properties is part of a general trend in PHP first seen in PHP 7. The trend is toward making language refinements that restrict and tighten the use of your code. This leads to better code, which means fewer bugs.

The following example illustrates the danger of relying solely upon property-type hinting to control the data type of properties:

// /repo/ch01/php7_prop_danger.php
declare(strict_types=1);
class Test {
    protected $id = 0;
    protected $token = 0;
    protected $name = '';
    public function __construct(
        int $id, int $token, string $name) {
        $this->id = $id;
        $this->token = md5((string) $token);
        $this->name = $name;
    }
}
$test = new Test(111, 123456, 'Fred');
var_dump($test);

In the preceding example, notice in the __construct() method that the $token property is accidentally converted to a string. Here is the output:

object(Test)#1 (3) {
  ["id":protected]=>  int(111)
  ["token":protected]=>
  string(32) "e10adc3949ba59abbe56e057f20f883e"
  ["name":protected]=>  string(4) "Fred"
}

Any subsequent code expecting $token to be an integer might either fail or produce unexpected results. Now, have a look at the same thing in PHP 8 using typed properties:

// /repo/ch01/php8_prop_danger.php
declare(strict_types=1);
class Test {
    protected int $id = 0;
    protected int $token = 0;
    protected string $name = '';
    public function __construct(
        int $id, int $token, string $name) {        
        $this->id = $id;
        $this->token = md5((string) $token);
        $this->name = $name;
    }
}
$test = new Test(111, 123456, 'Fred');
var_dump($test);

Property typing prevents any change to the preassigned data type from occurring, as you can see from the output shown here:

Fatal error: Uncaught TypeError: Cannot assign string to property Test::$token of type int in /repo/ch01/php8_prop_danger.php:12

As you can see from the preceding output, a Fatal error is thrown when the wrong data type is assigned to a typed property. This example demonstrates that not only does assigning a data type to a property prevent misuse when making direct assignments, but it also prevents misuse of the property inside class methods as well!

Property typing can lead to a reduction in code

Another beneficial side effect of introducing property typing to your code is a potential reduction in the amount of code needed. As an example, consider the current practice of marking properties with a visibility of private or protected, and then creating a series of get and set methods to control access (also called getters and setters).

Here is how that might appear:

  1. First, we define a Test class with protected properties, as follows:
    // /repo/ch01/php7_prop_reduce.php
    declare(strict_types=1);
    class Test {
     protected $id = 0;
     protected $token = 0;
     protected $name = '';o
  2. Next, we define a series of get and set methods to control access to the protected properties, as follows:
        public function getId() { return $this->id; }
        public function setId(int $id) { $this->id = $id; 
        public function getToken() { return $this->token; }
        public function setToken(int $token) {
            $this->token = $token;
        }
        public function getName() {
            return $this->name;
        }
        public function setName(string $name) {
            $this->name = $name;
        }
    }
  3. We then use the set methods to assign values, as follows:
    $test = new Test();
    $test->setId(111);
    $test->setToken(999999);
    $test->setName('Fred');
  4. Finally, we display the results in a table, using the get methods to retrieve property values, as follows:
    $pattern = '<tr><th>%s</th><td>%s</td></tr>';
    echo '<table width="50%" border=1>';
    printf($pattern, 'ID', $test->getId());
    printf($pattern, 'Token', $test->getToken());
    printf($pattern, 'Name', $test->getName());
    echo '</table>';

Here is how that might appear:

Table 1.4 – Output using Get methods

Table 1.4 – Output using Get methods

The main purpose achieved by marking properties as protected (or private) and by defining getters and setters is to control access. Often, this translates into a desire to prevent the property data type from changing. If this is the case, the entire infrastructure can be replaced by assigning property types.

Simply changing the visibility to public alleviates the need for get and set methods; however, it does not prevent the property data from being changed! Using PHP 8 property types achieves both goals: it eliminates the need for get and set methods and also prevents the data type from being accidentally changed.

Notice here how much less code is needed to achieve the same results in PHP 8 using property typing:

// /repo/ch01/php8_prop_reduce.php
declare(strict_types=1);
class Test {
    public int $id = 0;
    public int $token = 0;
    public string  $name = '';
}
// assign values
$test = new Test();
$test->id = 111;
$test->token = 999999;
$test->name = 'Fred';
// display results
$pattern = '<tr><th>%s</th><td>%s</td></tr>';
echo '<table width="50%" border=1>';
printf($pattern, 'ID', $test->id);
printf($pattern, 'Token', $test->token);
printf($pattern, 'Name', $test->name);
echo '</table>';

The preceding code example shown produces exactly the same output as the previous example and also achieves even better control over property data types. Using typed properties, in this example, we achieved a 50% reduction in the amount of code needed to produce the same result!

Tip

Best practice: Use typed properties whenever possible, except in situations where you explicitly want to allow the data type to change.

You have been reading a chapter from
PHP 8 Programming Tips, Tricks and Best Practices
Published in: Aug 2021 Publisher: Packt ISBN-13: 9781801071871
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime}