note 117929 added to language.oop5.visibility

From: Date: Thu, 03 Sep 2015 01:20:56 +0000
Subject: note 117929 added to language.oop5.visibility
Groups: php.notes 
Request: Send a blank email to php-notes+get-203592@lists.php.net to get a copy of this message
Just wanted to share a trap for the unwary. Where there are several layers of object assignments, setting the bottom object's properties as private will prevent its exposure. However, if the bottom object has public properties, intermediate objects which are themselves set as private but are derived from the bottom object can inadvertently be exposed to updates. This follows logically from the reference model in php ( http://php.net/manual/en/language.oop5.references.php ), but can yield a result that is surprising until one gets the reference model. The following example demonstrates the phenomenon. // underlying class for offering database results to other objects // __construct method yields public results -- bottom object in example class database_result { public $column1; public function __construct() { // . . . database access . . . $this->column1 = 'foo'; } } // application dictionary accesses database and caches results // for application objects -- this is the second layer in the example class dictionary { private $reference_object; public function __construct (){ $this->reference_object = new database_result; } public function get_reference_object() { return ( $this->reference_object ); } } $dictionary = new dictionary; /* $dictionary->reference_object cannot be accessed directly * $dictionary->reference_object->column1 = 'foochanged'; * yields Fatal error: Cannot access private property dictionary::$reference_object in /var/www/html/index.php . . . */ $pointer_to_dictionary = $dictionary; /* * if assign $dictionary to new variable, the new variable is a pointer and its properties are still private * $pointer_to_dictionary->reference_object->column1 = 'foochanged'; * Fatal error: Cannot access private property dictionary::$reference_object in /var/www/html/index.php . . . * $pointer_to_dictionary = $dictionary->reference_object; * Fatal error: Cannot access private property dictionary::$reference_object in /var/www/html/index.php . . . */ // now set up a client class that will use a working copy of the dictionary -- this is the third layer in the example class dictionary_user { private $pointer_to_dictionary; public function __construct () { global $dictionary; // $this->pointer_to_dictionary = $dictionary->reference_object; // Fatal error: Cannot access private property dictionary::$reference_object in /var/www/html/index.php . . . // still cannot directly access dictionary properties even in this context, except through getter $this->pointer_to_dictionary = $dictionary->get_reference_object(); } // however, can now operate on dictionary through the pointer public function set_pointer_to_dictionary ( $value ) { $this->pointer_to_dictionary->column1 = $value; } public function get_pointer_to_reference_object(){ return ($this->pointer_to_dictionary); } } $dictionary_user = new dictionary_user; $dictionary_user->set_pointer_to_dictionary ( 'foochanged' ); echo ('<br/>'); var_dump ( $dictionary_user->get_pointer_to_reference_object()); echo '<br/>'; // object(database_result)#2 (1) { ["column1"]=> string(10) "foochanged" } -- of course, the user object is changed var_dump ( $dictionary->get_reference_object() ); // object(database_result)#2 (1) { ["column1"]=> string(10) "foochanged" } -- however, the private dictionary object is also now corrupted! // Note: If the underlying database result object $column1 as private, this will cause set_pointer_to_dictionary to generate the usual fatal error // but making the bottom object private may defeat its purpose of exposing results. ---- Server IP: 72.52.91.14 Probable Submitter: 96.237.171.230 ---- Manual Page -- http://php.net/manual/en/language.oop5.visibility.php Edit -- https://master.php.net/note/edit/117929 Del: integrated -- https://master.php.net/note/delete/117929/integrated Del: useless -- https://master.php.net/note/delete/117929/useless Del: bad code -- https://master.php.net/note/delete/117929/bad+code Del: spam -- https://master.php.net/note/delete/117929/spam Del: non-english -- https://master.php.net/note/delete/117929/non-english Del: in docs -- https://master.php.net/note/delete/117929/in+docs Del: other reasons-- https://master.php.net/note/delete/117929 Reject -- https://master.php.net/note/reject/117929 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#203592) next »