Using Subclasses and Accessors with Member Visibility to Protect PHP 5 Class Data

It’s quite probable that you want to see what happens when a private property defined by a parent is retrieved from inside a child class, or if it’s possible to access it via an “accessor” method. Therefore, in the next few lines, I’m going to develop a bunch of practical examples that will help you grasp how to work with private properties in these situations.

Like many other robust, object-oriented languages available nowadays, PHP 5 comes equipped with a handy feature called “member visibility.” This permits you to explicitly specify the level of access to the methods and properties of a given class. It’s possible to declare data members public, protected, and private entities respectively, which helps to establish different grades of protection.

However, it’s possible that you’re a PHP developer who’s just starting to use the object model of PHP 5 and you want to learn how to use member visibility when building your own classes. If this is true, then you’ve come to the right place, since in this series of articles, you’ll be provided with the right pointers to help you start coding public, protected, and private data members within your neatly-crafted classes.

And now that I’ve mentioned the series, you’ll certainly recall that in the last article, I explained how to work with a couple of private properties that partially comprised the API of a basic class, which is useful for saving simple strings to a specified text file.

With that class available for testing purposes, I demonstrated how the PHP interpreter triggered a fatal error each time the private properties in question were accessed from outside of the originating class. Nevertheless, there are still some additional aspects concerning the use of private properties within PHP 5 classes that need to be covered.

Now, let’s get rid of the preliminaries and continue learning useful things about using private properties with PHP 5 classes. Let’s get going!

{mospagebreak title=Accessing private properties globally}

Before I start showing you how to access some private properties directly from a child class, first, let me reintroduce a practical example that I developed in the previous tutorial. It illustrated how the PHP interpreter behaves when it accesses a couple of private class properties globally.

As you’ll possibly recall, the properties in question were declared within a rudimentary data saving class, whose signature looked like this:


// define ‘DataSaver’ class (properties are defined private)


class DataSaver{

private $filePath;

private $data;

public function __construct($data,$filePath){

if(!$data||strlen($data)>1024){

throw new Exception(‘Invalid data for being saved to target file.’);

}

if(!file_exists($filePath)){

throw new Exception(‘Invalid target file.’);

}

$this->data=$data;

$this->filePath=$filePath;

}

// save data to target file

public function save(){

if(!$fp=fopen($this->filePath,’w')){

throw new Exception(‘Error opening target file.’);

}

if(!fwrite($fp,$this->data)){

throw new Exception(‘Error writing data to target file.’);

}

fclose($fp);

}

// get target file via an accessor

public function getFilePath(){

return $this->filePath;

}

// get data via an accessor

public function getData(){

return $this->data;

}

}


Since the above “DataSaver” class was introduced in the first article of this series, I assume that you’re pretty familiar with its functionality, so I won’t spend any time here explaining how it works. Instead, you should pay attention to the following script, which shows what happens when the private properties of this class are accessed directly in the global scope.

Here’s the corresponding code sample:


try{

// create new instance of ‘DataSaver’ class

$dataSaver=new DataSaver(‘This string of data will be saved to a target file!’,'datafile.txt’);

// save data to target file

$dataSaver->save();

// try to print value of private properties

echo ‘Target file is the following : ‘.$dataSaver->filePath.’<br />’;

echo ‘Data for being saved to target file is the following : ‘.$dataSaver->data;

 

/* displays the following

Cannot access private property DataSaver::$filePath in path/to/file/

*/

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


As you can see, the prior script demonstrates how the PHP interpreter launches a fatal error each time the private properties of the previous “DataSaver” class are retrieved directly from outside of it. Even though this example is pretty basic in its definition, it helps to show how useful the member visibility feature can be when it comes to protecting the data members of a given PHP 5 class.

So far, so good, right? Now that you hopefully understand how the previous hands-on example works, it’s time to learn a few more things about working with private properties of PHP 5 classes.

So, in accordance with the concepts that I went over in the beginning of this article, in the section to come, I’m going to develop yet another practical example aimed at demonstrating what happens when the private properties of the same “DataSaver” class are accessed from a subclass.

The topic will be very insightful, trust me. Thus, if you want to learn more about it, please click on the link shown below and keep reading.

{mospagebreak title=Accessing private properties from a subclass}

As I stated in the prior section, it’d be quite useful to demonstrate what occurs when a specific private property (defined by a parent class) is accessed by one of its subclasses. In recreating this scenario, you’ll understand how helpful it is to use private data members within a particular class, especially when it comes to protecting them from unwanted access.

This being said, here are the things that I plan to do in the next few lines: first, I’m going to list the same sample “DataSaver” class that you saw earlier. Then, I’m going to create a trivial subclass from it. And in the end, an instance of this child class will attempt to access the pair of private properties declared by the retaining parent.

Here’s the signature of the aforementioned “DataSaver” class:


// define ‘DataSaver’ class (properties are defined private)


class DataSaver{

private $filePath;

private $data;

public function __construct($data,$filePath){

if(!$data||strlen($data)>1024){

throw new Exception(‘Invalid data for being saved to target file.’);

}

if(!file_exists($filePath)){

throw new Exception(‘Invalid target file.’);

}

$this->data=$data;

$this->filePath=$filePath;

}

// save data to target file

public function save(){

if(!$fp=fopen($this->filePath,’w')){

throw new Exception(‘Error opening target file.’);

}

if(!fwrite($fp,$this->data)){

throw new Exception(‘Error writing data to target file.’);

}

fclose($fp);

}

// get target file via an accessor

public function getFilePath(){

return $this->filePath;

}

// get data via an accessor

public function getData(){

return $this->data;

}

}


Having listed this sample data saving class, it’s time to derive a subclass from it. In this case, I’ve called it “DataHandler,” and its corresponding definition is as follows:


// extends ‘DataSaver’ class and try to access private properties of the parent


class DataHandler extends DataSaver{

// fetch data from target file

public function fetch(){

if(!$data=file_get_contents($this->filePath)){

throw new Exception(‘Error reading data from target file.’);

}

return $data;

}

}


That was pretty easy to grasp, wasn’t it? As you can see, the above “DataHandler” subclass slightly extends the functionality of its respective parent via an additional “fetch()” method. However, the most interesting thing happens when this child class is used to access the private properties declared by the  parent.

The following code snippet demonstrates this particular situation:


try{

// create new instance of ‘DataHandler’ class

$dataHandler=new DataHandler(‘This string of data will be saved to a target file!’,'datafile.txt’);

// save data to target file

$dataHandler->save();

// fetch data from target file

echo $dataHandler->fetch();

// print value of private properties

echo ‘Target file is the following : ‘.$dataHandler->filePath.’<br />’;

echo ‘Data for being saved to target file is the following : ‘.$dataHandler->data;

 

/* displays the following

Undefined property: DataHandler::$filePath in path/to/file/

*/

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


I told you that things would be really interesting! As you can see, the above “DataHandler” class can’t retrieve the value of the private properties defined by its parent, and it simply assumes that these are not defined. This example demonstrates the high level of protection that any class property will have when it’s declared private.

It’s clear from the previous example that the private properties of a given class can only be accessed from inside that class in particular, and nothing else. Period.

However, it’d be pretty useful to see if it’s possible to use the accessor methods of the previous “DataHandler” class to retrieve the respective values of its private properties. What do you say? Is it possible to achieve this or not?

To answer that intriguing question, you’ll have to read the final section of this tutorial, so jump ahead and read the next few lines. I’ll be there, waiting for you.

{mospagebreak title=Retrieving the values of private properties using accessors}

During the previous section, you learned a simple — yet crucial — concept: the private properties of a class can only be accessed from inside of the class. However, it’s possible to play around with this theoretical definition and develop yet another example that shows how the properties in question can be retrieved by way of an accessor method.

To perform this task, I’m going to use the same “DataSaver” class that you saw previously, which, as you’ll surely recall, does have a couple of these accessor methods. If this doesn’t ring any bells, here’s the signature of this class:


class DataSaver{

private $filePath;

private $data;

public function __construct($data,$filePath){

if(!$data||strlen($data)>1024){

throw new Exception(‘Invalid data for being saved to target file.’);

}

if(!file_exists($filePath)){

throw new Exception(‘Invalid target file.’);

}

$this->data=$data;

$this->filePath=$filePath;

}

// save data to target file

public function save(){

if(!$fp=fopen($this->filePath,’w')){

throw new Exception(‘Error opening target file.’);

}

if(!fwrite($fp,$this->data)){

throw new Exception(‘Error writing data to target file.’);

}

fclose($fp);

}

// get target file via an accessor

public function getFilePath(){

return $this->filePath;

}

// get data via an accessor

public function getData(){

return $this->data;

}

}


As you can see, the above data saving class has been provided with a couple of accessors, called “getFilePath()” and “getData()” respectively. With these methods available, I’m going to create a simple script that shows how to use them in order to access the private properties of the class.

Having said that, here’s the script:


try{

// create new instance of ‘DataSaver’ class

$dataSaver=new DataSaver(‘This string of data will be saved to a target file!’,'datafile.txt’);

// save data to target file

$dataSaver->save();

// print value of private properties

echo ‘Target file is the following : ‘.$dataSaver->getFilePath().’<br />’;

echo ‘Data for being saved to target file is the following : ‘.$dataSaver->getData();

 

/* displays the following

Target file is the following : datafile.txt

Data for being saved to target file is the following : This string of data will be saved to a target file!

*/

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


As shown by the previous code snippet, it’s perfectly possible to retrieve the values that correspond to the private properties of the “DataSaver” class by using the respective accessors. The reason is extremely simple: the methods access the properties from inside the class!

Of course, this concept may seem pretty obvious, particularly if you have a lot of experience working with classes in PHP. But if you’re just getting started using its object model, the previous example might help you understand how to work with private properties.

Finally, with all of these code samples at your disposal, don’t excuse yourself from practicing with private class properties in PHP 5!

Final thoughts

In this third episode of the series I concluded this quick overview of working with public, protected, and private class properties. Nonetheless, I’m only scratching the surface when it comes to exploring the advantages of using member visibility in PHP 5; the language permits you to use this same feature with the methods of a class as well. Thus, in the upcoming article, I’ll explain how to implement this handy feature in several class methods.

Now that you’ve been warned about the subject of the next part, you can’t miss it!

Google+ Comments

Google+ Comments